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

com.scudata.dm.query.SimpleSelect 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.query;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;

import com.scudata.cellset.ICellSet;
import com.scudata.common.MessageManager;
import com.scudata.common.RQException;
import com.scudata.common.UUID;
import com.scudata.dm.BFileWriter;
import com.scudata.dm.BaseRecord;
import com.scudata.dm.ComputeStack;
import com.scudata.dm.Context;
import com.scudata.dm.DataStruct;
import com.scudata.dm.Env;
import com.scudata.dm.FileObject;
import com.scudata.dm.Param;
import com.scudata.dm.Record;
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.FileCursor;
import com.scudata.dm.cursor.ICursor;
import com.scudata.dm.cursor.MemoryCursor;
import com.scudata.dm.cursor.MultipathCursors;
import com.scudata.dm.cursor.SubCursor;
import com.scudata.dm.cursor.SyncCursor;
import com.scudata.dm.op.Derive;
import com.scudata.dm.op.Join;
import com.scudata.dm.op.New;
import com.scudata.dm.op.Operation;
import com.scudata.dm.op.Select;
import com.scudata.dm.query.SimpleSelect.ParamNode;
import com.scudata.dm.query.utils.ExpressionTranslator;
import com.scudata.dm.query.utils.FileUtil;
import com.scudata.dm.sql.FunInfoManager;
import com.scudata.dw.ComTable;
import com.scudata.dw.PhyTable;
import com.scudata.excel.ExcelTool;
import com.scudata.expression.Expression;
import com.scudata.resources.ParseMessage;
import com.scudata.util.CursorUtil;
import com.scudata.util.EnvUtil;
import com.scudata.util.JSONUtil;

public class SimpleSelect
{
	private boolean hasDistinct;
	private int topNumber;
	private int limitNumber;
	private int offsetNumber;
	private int parallelNumber;
	private String distinctGatherField;
	private Map levelMap;
	private List finalList;
	private List aliasList;
	private List columnList;
	private List groupList;
	private List sortList;
	private TableNode tableNode;
	private ExpressionNode havingNode;
	private ExpressionNode whereNode;
	private List selectFieldList;
	private List gatherNodeList;
	private List parameterList;
	private ICursor icur;
	private DataStruct ds;
	private int columnIndex;
	private Context ctx;
	private Map tablePathMap;
	private ICellSet ics;
	private List> subQueryOfExistsEntryList;
	private List> subQueryOfSelectEntryList;
	private List> subQueryOfInEntryList;
	private List> subQueryOfWhereEntryList;
	private Map subQueryOfExistsMap;
	private Map subQueryOfSelectMap;
	private Map subQueryOfInMap;
	private Map subQueryOfWhereMap;
	private String password;
	private boolean isMemory;
	private PhyTable tmd;
	private String topFilter;
	private Sequence fromSeq;	//20240731 xingjl
	
	abstract class Node 
	{
		abstract public boolean hasGather();
		abstract public boolean hasField(Boolean isOrder); //????group by??order by?Ӿ??ж??Ƿ?????ֶΣ??ۺϺ?????һ?㺯???޲??
		abstract public boolean hasField(String fieldName); //????select?Ӿ??ж??Ƿ????ij?ֶΣ??ۺϺ???????????һ?㺯??
		abstract public boolean hasFieldNotGroup();
		abstract public void optimize();
		abstract public void collect();
		abstract public String toExpression();
		abstract public void setFromHaving();
		abstract public void setFromWhere();
	}
	
	class TableNode extends Node
	{
		final public static int TYPE_ICR = -1;
		final public static int TYPE_BIN = 0;
		final public static int TYPE_TXT = 1;
		final public static int TYPE_CSV = 2;
		final public static int TYPE_XLS = 3;
		final public static int TYPE_XLSX = 4;
		final public static int TYPE_GTB = 5;
		final public static int TYPE_JSON = 6;
		
		private String name;
		private String alias;
		private FileObject file;
		private ArrayList files = new ArrayList();
		public ArrayList getFiles() {
			return files;
		}

		public void setFiles(ArrayList files) {
			this.files = files;
			if (this.files == null || this.files.size()==0 && this.file != null) {
				files = new ArrayList();
				files.add(file);
			}
		}

		private PhyTable meta;
		private ArrayList metas;
		private int type;
		private ICursor cursor;
		private DataStruct struct;
		private String[] fields;
		private Expression where;
		private boolean fileAttrQuery=false;
		
		public boolean isFileAttrQuery() {
			return fileAttrQuery;
		}

		public void setFileAttrQuery(boolean fileAttrQuery) {
			this.fileAttrQuery = fileAttrQuery;
		}

		public TableNode(String tableName, String aliasName, FileObject fileObject, int type)
		{
			if(tableName != null)
			{
				this.name = tableName;
			}
			if(aliasName != null)
			{
				if(aliasName.startsWith("\"") && aliasName.endsWith("\"") && aliasName.substring(1, aliasName.length() - 1).indexOf("\"") == -1)
				{
					aliasName = aliasName.substring(1, aliasName.length() - 1);
				}
				this.alias = aliasName;
			}
			
			if(fileObject == null)
			{
				MessageManager mm = ParseMessage.get();
				throw new RQException(mm.getMessage("syntax.error") + ":TableNode.TableNode, ?ļ???????Ϊ??ֵ");
			}

			if(type == TableNode.TYPE_ICR)
			{
				MessageManager mm = ParseMessage.get();
				throw new RQException(mm.getMessage("syntax.error") + ":TableNode.TableNode, ???ļ??????쳣");
			}
			else
			{
				this.cursor = null;
				this.struct = null;
				this.file = fileObject;
				this.meta = null;
				this.type = type;
				this.fields = null;
				this.where = null;
			}
		}
		
		public TableNode(String tableName, String aliasName, ICursor cs, DataStruct ds)
		{
			if(tableName != null)
			{
				this.name = tableName;
			}
			if(aliasName != null)
			{
				if(aliasName.startsWith("\"") && aliasName.endsWith("\"") && aliasName.substring(1, aliasName.length() - 1).indexOf("\"") == -1)
				{
					aliasName = aliasName.substring(1, aliasName.length() - 1);
				}
				this.alias = aliasName;
			}
			this.cursor = cs;
			this.struct = ds;
			this.file = null;
			this.meta = null;
			this.type = TableNode.TYPE_ICR;
			this.fields = null;
		}
		
		public TableNode(String tableName, String aliasName, PhyTable meta)
		{
			if(tableName != null)
			{
				this.name = tableName;
			}
			if(aliasName != null)
			{
				if(aliasName.startsWith("\"") && aliasName.endsWith("\"") && aliasName.substring(1, aliasName.length() - 1).indexOf("\"") == -1)
				{
					aliasName = aliasName.substring(1, aliasName.length() - 1);
				}
				this.alias = aliasName;
			}
			this.cursor = null;
			this.struct = null;
			this.file = null;
			this.meta = meta;
			this.type = TableNode.TYPE_GTB;
			this.fields = null;
		}
		
		public String getName()
		{
			if(this.name == null)
			{
				MessageManager mm = ParseMessage.get();
				throw new RQException(mm.getMessage("syntax.error") + ":TableNode.getName, ??Ч?ı??ڵ?");
			}
			return this.name;
		}
		
		public String getAlias()
		{
			if(this.alias == null)
			{
				MessageManager mm = ParseMessage.get();
				throw new RQException(mm.getMessage("syntax.error") + ":TableNode.getAlias, ??Ч?ı??ڵ?");
			}
			return this.alias;
		}
		
		public int getType()
		{
			return this.type;
		}
		
		public void setWhere(String whereExp) // ???ר????ǰ????
		{
			if(whereExp != null && !whereExp.isEmpty())
			{
				this.where = new Expression(whereExp);
			}
		}
		
		private String[] getDataField() {
			if (this.fields == null || this.fields.length == 0) return this.fields;
			String n = "";
			for (int i=0; i0) return n.substring(1).split(",");
			else return new String[0];
		}
		private String[] getFileField() {
			if (this.fields == null || this.fields.length == 0) return this.fields;
			String n = "";
			for (int i=0; i0) return n.substring(1).split(",");
			else return new String[0];
		}
		
		public ICursor getCursor()
		{
			ICursor icursor = null;
			if(this.file != null || this.meta != null)
			{
				if (this.fileAttrQuery) {
					//return new FileCursor(new FileObject("d:/test/fileAttr.txt"), 1, 1, this.fields, null, null, "t", ctx);
				}
				
				if(this.type == TableNode.TYPE_GTB)	// ????ļ?
				{
					ICursor []cursors2 = new ICursor[this.files.size()];
					metas = new ArrayList(); 
					for (int z=0; z 1)
							{
								ICursor []cursors = new ICursor[parallelNumber];
								for (int i = 0; i < parallelNumber; ++i) 
								{
									cursors[i] = new SyncCursor(icursor);
								}
								cursors2[z] = new MultipathCursors(cursors, ctx);
							}
						}
						else
						{
							if(parallelNumber == 1)
							{
								cursors2[z] = meta.cursor(this.fields, this.where, ctx);
							}
							else if(parallelNumber > 1)
							{
								ICursor []cursors = new ICursor[parallelNumber];
								for (int i = 0; i < parallelNumber; ++i) 
								{
									cursors[i] = meta.cursor(null, fields, where, null, null, null, i+1, parallelNumber, null, ctx);
								}
								cursors2[z] = new MultipathCursors(cursors, ctx);
							}
						}
					}
					if (this.files.size() == 1) icursor = cursors2[0];
					else icursor = new ConjxCursor(cursors2);
				}
				else if(this.type == TableNode.TYPE_BIN) // ???ļ?
				{
					ICursor []cursors2 = new ICursor[this.files.size()];
					for (int z=0; z0) {
								Expression[] exps2 = new Expression[this.fields.length];
								for (int p=0; p0) {
								Expression[] exps2 = new Expression[this.fields.length];
								for (int z=0; z list;
		
		public ExpressionNode(ArrayList nodeList)
		{
			this.list = nodeList;
		}
		
		public ArrayList getNodeList()
		{
			if(this.list == null)
			{
				MessageManager mm = ParseMessage.get();
				throw new RQException(mm.getMessage("syntax.error") + ":ExpressionNode.getNodeList, ??Ч?ı???ʽ?ڵ?");
			}
			
			return this.list;
		}
		
		public boolean hasGather()
		{
			if(this.list == null)
			{
				MessageManager mm = ParseMessage.get();
				throw new RQException(mm.getMessage("syntax.error") + ":ExpressionNode.hasGather, ??Ч?ı???ʽ?ڵ?");
			}
			
			for(int i=0,z=this.list.size();i= 2)
							{
								sb.append(",");
							}
							sb.append(getProcValue(seq.get(i)));
						}
						sb.append("]");
						sb.append(".pos@b(");
						sb.append("$?");
						sb.append(")");
						if(this.not)
						{
							sb.append("==");
						}
						else
						{
							sb.append("!=");
						}
						sb.append("null");
						sb.append(")");
					}
					
					//???coalesce?????ľֲ??Ż?
					String expStr = sb.toString();
					if(this.node.getNodeList().size() == 1  
					&& this.node.getNodeList().get(0) instanceof FunctionNode
					&& ((FunctionNode)this.node.getNodeList().get(0)).getName().equalsIgnoreCase("coalesce"))
					{
						FunctionNode coalesce = (FunctionNode) this.node.getNodeList().get(0);
						String[] paramsStr = getParams(coalesce.getParamNode().toExpression());
						if(paramsStr.length == 2)
						{
							String tmpExpStr = expStr.replace("$?", paramsStr[1]);
							Expression tmpExp = new Expression(tmpExpStr);
							try
							{
								Object objVal = tmpExp.calculate(ctx);
								if(objVal != null && objVal.equals(false))
								{
									expression = paramsStr[0];
								}
							}
							catch(Exception ex)
							{
								throw new RQException(ex.getMessage(), ex);
							}
						}
					}
					//?Ż?????
					expStr = expStr.replace("$?", expression);
					return expStr;
				}
			}
			else //??ͨ????ʽ??IN?Ӿ䣬??????ѯ?ֶε??Ӳ?ѯ??IN?Ӿ?
			{
				String paramStr = this.param.toExpression().trim();
				
				//??join??????Ӳ?ѯ?ֶ???Ϊ?Ǻ????ӵ?
				//??????ѡ???ֶιʲ???Ҫȥ????????
				if(subQueryOfInMap.containsValue(paramStr))
				{
					//???ַ??????????ʺϣ???Ϊ??Ҫ??????ֵ????
					//????????ѯ?ֶ?ֵ??ͬ??????ֵ??ΧҲ??仯
					//??ÿ?????ݶ???Ҫ?????????????????˷?ʱ??
					StringBuffer sb = new StringBuffer();
					if(this.not)
					{
						sb.append("!");
					}
					sb.append(paramStr);
					sb.append(".contain(");
					sb.append(expression);
					sb.append(")");
					//???coalesce?????ľֲ??Ż?????Ҳ????ʹ??
					//??Ϊ??????ѯ?ֶ?ֵ??ͬ???ط?ΧҲ??仯
					//?ʲ???ȷ??coalesce?ڶ????????Ƿ񱻰???
					String expStr = sb.toString();
					return expStr;
				}
				else if(paramStr.startsWith("(") && paramStr.endsWith(")"))
				{
					//????ʱΪ????????Ӳ?ѯ???̶????һ????????Ҫ?ڴ?ȥ??,
					//ͬʱ??Ҳ??Ϊ????????ѯ?ֶε??Ӳ?ѯ?ı?ʶ???ı?־
					paramStr = paramStr.substring(1, paramStr.length()-1);
					
					StringBuffer sb = new StringBuffer();
					String[] params = paramStr.split(",");
					if(params.length <= 2)
					{
						sb.append("(");
						for(int pi = 0, pl = params.length; pi < pl; pi++)
						{
							sb.append(params[pi].trim());
							if(this.not)
							{
								sb.append("!=");
							}
							else
							{
								sb.append("==");
							}
							sb.append("(");
							sb.append("$?");
							sb.append(")");
							if(pi != pl - 1)
							{
								if(this.not)
								{
									sb.append("&&");
								}
								else
								{
									sb.append("||");
								}
							}
						}
						sb.append(")");
					}
					else
					{
						String[] values = getParams(paramStr);
						Map valueMap = new LinkedHashMap();
						Sequence seq = new Sequence();
						for(String value : values)
						{
							Object obj = new Expression(value).calculate(ctx);
							valueMap.put(obj, value);
							seq.add(obj);
						}
						seq.sort("o");//׼???ö??ַ???????????????
						StringBuffer tmp = new StringBuffer();
						for(int i = 1; i <= seq.length(); i++)
						{
							if(i > 1)
							{
								tmp.append(",");
							}
							tmp.append(valueMap.get(seq.get(i)));
						}
						sb.append("(");
						sb.append("[");
						sb.append(tmp.toString());
						sb.append("]");
						sb.append(".pos@b(");
						sb.append("$?");
						sb.append(")");
						if(this.not)
						{
							sb.append("==");
						}
						else
						{
							sb.append("!=");
						}
						sb.append("null");
						sb.append(")");
					}
					//???coalesce?????ľֲ??Ż?
					String expStr = sb.toString();
					if(this.node.getNodeList().size() == 1  
					&& this.node.getNodeList().get(0) instanceof FunctionNode
					&& ((FunctionNode)this.node.getNodeList().get(0)).getName().equalsIgnoreCase("coalesce"))
					{
						FunctionNode coalesce = (FunctionNode) this.node.getNodeList().get(0);
						String[] paramsStr = getParams(coalesce.getParamNode().toExpression());
						if(paramsStr.length == 2)
						{
							String tmpExpStr = expStr.replace("$?", paramsStr[1]);
							Expression tmpExp = new Expression(tmpExpStr);
							try
							{
								Object objVal = tmpExp.calculate(ctx);
								if(objVal != null && objVal.equals(false))
								{
									expression = paramsStr[0];
								}
							}
							catch(Exception ex)
							{
								throw new RQException(ex.getMessage(), ex);
							}
						}
					}
					//?Ż?????
					expStr = expStr.replace("$?", expression);
					return expStr;
				}
				else
				{
					//??join????scanExp????whereʱ?????˴?
					//??????Ӳ?ѯ?ֶ???Ϊ?Ѿ?????????????ѡ???ֶ?
					if(paramStr.startsWith("'$") && paramStr.endsWith("'"))
					{
						//???ַ??????????ʺϣ???Ϊ??Ҫ??????ֵ????
						//????????ѯ?ֶ?ֵ??ͬ??????ֵ??ΧҲ??仯
						//??ÿ?????ݶ???Ҫ?????????????????˷?ʱ??
						StringBuffer sb = new StringBuffer();
						if(this.not)
						{
							sb.append("!");
						}
						sb.append(paramStr);
						sb.append(".contain(");
						sb.append(expression);
						sb.append(")");
						//???coalesce?????ľֲ??Ż?????Ҳ????ʹ??
						//??Ϊ??????ѯ?ֶ?ֵ??ͬ???ط?ΧҲ??仯
						//?ʲ???ȷ??coalesce?ڶ????????Ƿ񱻰???
						String expStr = sb.toString();
						return expStr;
					}
					else
					{
						MessageManager mm = ParseMessage.get();
						throw new RQException(mm.getMessage("syntax.error") + ":InNode.toExpression, ?޷?ʶ???IN?Ӿ?");
					}
				}
			}
		}

		public boolean hasGather() //???ᱻselect??????
		{
			return false;
		}
		
		public boolean hasFieldNotGroup()  //???ᱻselect??????
		{
			return false;
		}

		public void setFromHaving() 
		{
			this.isFromHaving = true;
		}

		public void setFromWhere() 
		{
			this.isFromWhere = true;
		}
		
		public void collect() 
		{
			if(this.node == null)
			{
				MessageManager mm = ParseMessage.get();
				throw new RQException(mm.getMessage("syntax.error") + ":InNode.collect, ??Ч??In?ڵ?");
			}
			
			this.node.collect();
		}
		
		public boolean hasField(Boolean isOrder) 
		{
			MessageManager mm = ParseMessage.get();
			throw new RQException(mm.getMessage("syntax.error") + ":InNode.hasField, In?Ӿ䲻?????ڷ????ֶ?");
		}
		
		public boolean hasField(String fieldName)
		{
			MessageManager mm = ParseMessage.get();
			throw new RQException(mm.getMessage("syntax.error") + ":InNode.hasField, In?Ӿ䲻?????ڲ?ѯ?ֶ?");
		}
	}
	
	class LikeNode extends Node
	{
		private ExpressionNode node;
//		private String pattern;
		private boolean not;
		private boolean isFromHaving;
		private boolean isFromWhere;
		private Token token;
		private SimpleSelect select;

		
		public LikeNode(ExpressionNode expNode, Token token, boolean hasNot, SimpleSelect select)
		{
			this.node = expNode;
			//this.pattern = pattern;
			this.not = hasNot;
			this.token = token;
			this.select = select;
		}
		
		public String getPattern()
		{
			if(this.token == null)
			{
				MessageManager mm = ParseMessage.get();
				throw new RQException(mm.getMessage("syntax.error") + ":LikeNode.getPattern, ??Ч??Like?ڵ?");
			}
			return this.token.getString();
		}
		
		public boolean getNot()
		{
			return this.not;
		}

		public void optimize()
		{
			if(this.node == null)
			{
				MessageManager mm = ParseMessage.get();
				throw new RQException(mm.getMessage("syntax.error") + ":LikeNode.optimize, ??Ч??Like?ڵ?");
			}
			
			this.node.optimize();
		}
		
		public String toExpression() 
		{
			if(this.node == null || this.token == null)
			{
				MessageManager mm = ParseMessage.get();
				throw new RQException(mm.getMessage("syntax.error") + ":LikeNode.toExpression, ??Ч??Like?ڵ?");
			}
			
			//
			String tt = this.token.toString();
			if (tt.indexOf("'") == 0 && tt.lastIndexOf("'") == tt.length() - 1) tt = tt.substring(1,tt.length()-1);
			
			String pattern = "\""+tt+"\"";
			
			if (token.getType() == Tokenizer.PARAMMARK) {
				ParamNode paramNode = new ParamNode();
				String strIndex = token.getString().substring(1);
					
				if(strIndex.length() != 0)
				{
					int paramIndex = Integer.parseInt(strIndex);
					paramNode.setIndex(paramIndex);
				}
				else
				{
					MessageManager mm = ParseMessage.get();
					throw new RQException(mm.getMessage("syntax.error") + ":scanExp, ????ռλ??????????");
				}
				
				pattern = paramNode.toExpression();

			}
			
			pattern = pattern.replace("\\", "\\\\");
			pattern = pattern.replace("*", "\\\\*");
			pattern = pattern.replace("?", "\\\\?");
			
			pattern = pattern.replace("[_]", "" + (char)18 + (char)19);
			pattern = pattern.replace("_", "?");
			pattern = pattern.replace("" + (char)18 + (char)19, "_");
			
			pattern = pattern.replace("[%]", "" + (char)18 + (char)19);
			pattern = pattern.replace("%", "*");
			pattern = pattern.replace("" + (char)18 + (char)19, "%");
			
			pattern = pattern.replace("[[]", "[");
			
			return "like@c(" + this.node.toExpression() +"," + pattern + ")";
		}

		public boolean hasGather()  //???ᱻselect??????
		{
			return false;
		}
		
		public boolean hasFieldNotGroup()  //???ᱻselect??????
		{
			return false;
		}

		public void setFromHaving() 
		{
			this.isFromHaving = true;
		}

		public void setFromWhere() 
		{
			this.isFromWhere = true;
		}
		
		public void collect() 
		{
			if(this.node == null)
			{
				MessageManager mm = ParseMessage.get();
				throw new RQException(mm.getMessage("syntax.error") + ":LikeNode.collect, ??Ч??Like?ڵ?");
			}
			
			this.node.collect();
		}
		
		public boolean hasField(Boolean isOrder) 
		{
			MessageManager mm = ParseMessage.get();
			throw new RQException(mm.getMessage("syntax.error") + ":LikeNode.hasField, Like?Ӿ䲻?????ڷ????ֶ?");
		}
		
		public boolean hasField(String fieldName)
		{
			MessageManager mm = ParseMessage.get();
			throw new RQException(mm.getMessage("syntax.error") + ":LikeNode.hasField, Like?Ӿ䲻?????ڲ?ѯ?ֶ?");
		}
	}
	
	class CaseNode extends Node
	{
		private List list;
		
		public CaseNode(List nodeList)
		{
			this.list = nodeList;
		}
		
		public List getNodeList()
		{
			if(this.list == null)
			{
				MessageManager mm = ParseMessage.get();
				throw new RQException(mm.getMessage("syntax.error") + ":CaseNode.getNodeList, ??Ч??Case?ڵ?");
			}
			return this.list;
		}
		
		public void optimize()
		{
			if(this.list == null)
			{
				MessageManager mm = ParseMessage.get();
				throw new RQException(mm.getMessage("syntax.error") + ":CaseNode.optimize, ??Ч??Case?ڵ?");
			}
			
			for(int i = 0, z = this.list.size(); i < z; i++)
			{
				Node node = this.list.get(i);
				if(node != null)
				{
					node.optimize();
				}
			}
		}
		
		public String toExpression() 
		{
			StringBuffer buf = new StringBuffer(this.list.get(0).toExpression());
			int sz = this.list.size();
			if(this.list.size() % 2 == 0)
			{
				sz = sz - 1;
			}
			for(int i = 1; i < sz; i += 2)
			{
				buf.append(",");
				buf.append(String.format("%s:%s", this.list.get(i).toExpression(), this.list.get(i + 1).toExpression()));
			}
			if(this.list.size() % 2 == 0)
			{
				buf.append(";");
				buf.append(this.list.get(this.list.size() - 1).toExpression());
			}
			return String.format("case(%s)", buf.toString());
		}

		public boolean hasGather()
		{
			if(this.list == null)
			{
				MessageManager mm = ParseMessage.get();
				throw new RQException(mm.getMessage("syntax.error") + ":CaseNode.hasGather, ??Ч?ı???ʽ?ڵ?");
			}
			
			for(int i=0,z=this.list.size();i paramList = null;
		private DataStruct ds = null;
		private DataStruct tabDs = null;
		private List>> subQueryListListList = null;
		private List> fieldNameListList = null;
		private List colNameList = null;
		
		public SubQueryCursor(ICursor cursor, int type, ICellSet ics, List paramList, List colNameList, List>> subQueryListListList, List> fieldNameListList, Context ctx, DataStruct tabDs)
		{
			super(cursor);
			this.type = type;
			if(this.type != Exist_Type && this.type != Select_Type && this.type != In_Type && this.type != Where_Type)
			{
				MessageManager mm = ParseMessage.get();
				throw new RQException(mm.getMessage("function.paramError") + ":SubQueryCursor, ?Ӳ?ѯ?α??ʼ??????????");
			}
			this.ics = ics;
			this.paramList = paramList;
			this.subQueryListListList = subQueryListListList;
			if(this.subQueryListListList == null)
			{
				MessageManager mm = ParseMessage.get();
				throw new RQException(mm.getMessage("function.paramError") + ":SubQueryCursor, ?Ӳ?ѯ?α??ʼ??????????");
			}
			this.fieldNameListList = fieldNameListList;
			if(this.fieldNameListList == null)
			{
				MessageManager mm = ParseMessage.get();
				throw new RQException(mm.getMessage("function.paramError") + ":SubQueryCursor, ?Ӳ?ѯ?α??ʼ??????????");
			}
			this.colNameList = colNameList;
			if(this.colNameList == null)
			{
				MessageManager mm = ParseMessage.get();
				throw new RQException(mm.getMessage("function.paramError") + ":SubQueryCursor, ?Ӳ?ѯ?α??ʼ??????????");
			}
			this.ctx = ctx;
			
			List finalFieldNameList = new ArrayList();
			finalFieldNameList.addAll(Arrays.asList(tabDs.getFieldNames()));
			finalFieldNameList.addAll(this.colNameList);
			String[] finalFieldNames = new String[finalFieldNameList.size()];
			finalFieldNameList.toArray(finalFieldNames);
			this.tabDs = new DataStruct(finalFieldNames);
			this.colNameList.clear();
		}
		
		protected Sequence get(int n) 
		{
			Sequence tab = super.get(n);
			if(tab != null && tab.dataStruct() != null)
			{
				int init = tab.dataStruct().getFieldCount();
				int size = this.fieldNameListList.size();
				for(int i = 0; i < size; i++)
				{
					DataStruct struct = new DataStruct(Arrays.copyOfRange(this.tabDs.getFieldNames(), 0, init + i + 1));
					Table res = new Table(struct);

					List> subQueryListList = this.subQueryListListList.get(i);
					List fieldNameList = this.fieldNameListList.get(i);
					
					for(int m = 1; m <= tab.getMems().size(); m++)
					{
						Object obj = tab.getMems().get(m);
						if(!(obj instanceof BaseRecord))
						{
							MessageManager mm = ParseMessage.get();
							throw new RQException(mm.getMessage("syntax.error") + ":SubQueryCursor.get, ??ѯ??????б????ɼ?¼???");
						}
						BaseRecord rec = (BaseRecord) obj;
						
						int index = 0;
						List subQueryList = new ArrayList();
						subQueryList.addAll(subQueryListList.get(index++));
						for(String fieldName : fieldNameList)
						{
							String fieldValue = getSQLValue(rec.getFieldValue(fieldName));
							Token[] fieldValueTokens = Tokenizer.parse(fieldValue);
							subQueryList.addAll(Arrays.asList(fieldValueTokens));
							if(index < subQueryListList.size())
							{
								subQueryList.addAll(subQueryListList.get(index++));
							}
						}
						Token[] subQuery = new Token[subQueryList.size()];
						subQueryList.toArray(subQuery);
						
						SimpleSQL lq = new SimpleSQL(this.ics, subQuery, 0, subQuery.length, this.paramList, this.ctx, false);
						lq.setMemory(true);
						Object result = lq.execute();
						Sequence sq = result instanceof ICursor ? ((ICursor)result).fetch() : (result instanceof Sequence ? (Sequence)result : null);
						
						Object val = null;
						if(sq != null)
						{
							if(this.type == SubQueryCursor.Exist_Type)
							{
								val = "1";
							}
							else if(this.type == SubQueryCursor.Select_Type || this.type == SubQueryCursor.Where_Type)
							{
								if(sq.length() != 1 || !(sq.get(1) instanceof BaseRecord) || sq.dataStruct() == null || sq.dataStruct().getFieldCount() != 1)
								{
									MessageManager mm = ParseMessage.get();
									throw new RQException(mm.getMessage("syntax.error") + ":SubQueryCursor.get, SELECT/WHERE?Ӿ????Ӳ?ѯ????쳣");
								}
								val = ((BaseRecord)sq.get(1)).getFieldValue(0);
							}
							else if(this.type == SubQueryCursor.In_Type)
							{
								Sequence v = new Sequence();
								for(int p = 1, q = sq.length(); p <= q; p++)
								{
									if(sq.length() == 0 ||!(sq.get(1) instanceof BaseRecord) || sq.dataStruct() == null || sq.dataStruct().getFieldCount() != 1)
									{
										MessageManager mm = ParseMessage.get();
										throw new RQException(mm.getMessage("syntax.error") + ":SubQueryCursor.get, IN?Ӿ????Ӳ?ѯ????쳣");
									}
									v.add(((BaseRecord)sq.get(p)).getFieldValue(0));
								}
								val = v;
							}
						}
						
						BaseRecord newRec = new Record(struct);
						newRec.set(rec);
						newRec.set(init + i, val);
						res.add(newRec);
					}
					
					tab = res;
				}
			}

			return tab;
		}
		
		public DataStruct getDataStruct()
		{
			return this.ds;
		}
		
		public void setDataStruct(DataStruct ds)
		{
			this.ds = ds;
		}
		
		public DataStruct getTableDataStruct()
		{
			return this.tabDs;
		}
	}

	public SimpleSelect(ICellSet ics, Context ctx)
	{
		this.icur = null;
		this.ds = null;
		this.ctx = ctx;
		this.ics = ics;;
		init();
	}
	
	private void init()
	{
		this.hasDistinct = false;
		this.topNumber = -1;
		this.limitNumber = -1;
		this.offsetNumber = -1;
		this.parallelNumber = 1;
		this.distinctGatherField = null; // must be null when init
		this.levelMap = new LinkedHashMap();
		this.finalList = new ArrayList();
		this.aliasList = new ArrayList();
		this.columnList = new ArrayList();
		this.groupList = new ArrayList();
		this.sortList = new ArrayList();
		this.tableNode = null;
		this.havingNode = null;
		this.whereNode = null;
		this.selectFieldList = new ArrayList();
		this.gatherNodeList = new ArrayList();
		this.parameterList = new ArrayList();
		this.columnIndex = 1;
		if(this.ctx == null)
		{
			this.ctx = new Context();
		}
		this.tablePathMap = new HashMap();
		this.subQueryOfExistsEntryList = new ArrayList>();
		this.subQueryOfSelectEntryList = new ArrayList>();
		this.subQueryOfInEntryList = new ArrayList>();
		this.subQueryOfWhereEntryList = new ArrayList>();
		this.subQueryOfExistsMap = new HashMap();
		this.subQueryOfSelectMap = new HashMap();
		this.subQueryOfInMap = new HashMap();
		this.subQueryOfWhereMap = new HashMap();
		this.password = null;
		this.tmd = null;
		this.topFilter = null;
	}
	
	public void setTablePath(String name, String path)
	{
		if(name != null)
		{
			this.tablePathMap.put(name.toLowerCase(), path);
		}
	}
	
	public void setLevelFunction(String levelName, String levelFunction)
	{
		if(levelName == null || levelName.trim().isEmpty() || levelFunction == null || levelFunction.trim().isEmpty())
		{
			MessageManager mm = ParseMessage.get();
			throw new RQException(mm.getMessage("function.paramError") + ":setLevelFunction, ????????Ϊ??ֵ");
		}
		levelName = levelName.toLowerCase();
		levelFunction = levelFunction.toLowerCase();
		Token[] tokens = Tokenizer.parse(levelFunction);
		for(int i=0; i paramList)
	{
		if(paramList != null && !paramList.isEmpty())
		{
			for(Object param : paramList)
			{
				setSQLParameters(param);
			}
		}
	}
	
	private Object getSQLParameters(int paramIndex)
	{		
		if(this.parameterList != null && this.parameterList.size() > paramIndex)
		{
			Object param = this.parameterList.get(paramIndex);
			return param;
		}
		else
		{
			MessageManager mm = ParseMessage.get();
			throw new RQException(mm.getMessage("search.lessParam") + ":getDQLParameters");
		}
	}
	
	private int pos(int p1, int def) 
	{
		if (p1 > 0) return p1;
		return def;
	}
	
	private int pos(int p1, int p2, int def) 
	{
		if (p1 > 0) return p1;
		if (p2 > 0) return p2;
		return def;
	}
	
	private int pos(int p1, int p2, int p3, int def) 
	{
		if (p1 > 0) return p1;
		if (p2 > 0) return p2;
		if (p3 > 0) return p3;
		return def;
	}
	
	private int pos(int p1, int p2, int p3, int p4, int def) 
	{
		if (p1 > 0) return p1;
		if (p2 > 0) return p2;
		if (p3 > 0) return p3;
		if (p4 > 0) return p4;
		return def;
	}
	
	private int pos(int p1, int p2, int p3, int p4, int p5, int p6, int def) 
	{
		if (p1 > 0) return p1;
		if (p2 > 0) return p2;
		if (p3 > 0) return p3;
		if (p4 > 0) return p4;
		if (p5 > 0) return p5;
		if (p6 > 0) return p6;
		return def;
	}
	
	public ICursor query(String dql)
	{
		Token[] dqlTokens = Tokenizer.parse(dql);
		return query(dqlTokens, 0, dqlTokens.length);
	}
	
	public ICursor query(Token[] tokens, int start, int end)
	{
		scanSelect(tokens, start, end);
		execute();
		init();
		return this.icur;
	}
	
	public void scanSelect(Token []tokens, int start, int next) 
	{
		if(tokens[start].isKeyWord("SELECT"))
		{
			start++; // skip over "select"
		}
		else
		{
			MessageManager mm = ParseMessage.get();
			throw new RQException(mm.getMessage("syntax.error") + ":scanSelect, SQL????????SELECT?ؼ??ֿ?ͷ");
		}
		
		if (start >= next) 
		{
			MessageManager mm = ParseMessage.get();
			throw new RQException(mm.getMessage("syntax.error") + ":scanSelect, ??ʼλ?ó???????λ??");
		}
		
		start = scanQuantifies(tokens, start, next);

		int colPos = start;
		int fromPos = -1;
		int havePos = -1;
		int orderPos = -1;
		int limitPos = -1;
		int offsetPos = -1;
		
		for (int i = colPos; i < next; ++i) 
		{
			Token token = tokens[i];
			if(token.isKeyWord()) 
			{
				if (fromPos == -1) 
				{
					if (token.equals("FROM")) 
					{
						fromPos = i;
					}
				} 
				else if (havePos == -1 && token.equals("HAVING")) 
				{
					havePos = i;
				} 
				else if (token.equals("ORDER")) 
				{
					orderPos = i;
				}
				else if (token.equals("LIMIT")) 
				{
					limitPos = i;
				}
				else if (token.equals("OFFSET")) 
				{
					offsetPos = i;
					break;
				}
			}
			else if (token.getType() == Tokenizer.LPAREN) // ????()
			{
				i = Tokenizer.scanParen(tokens, i, next);
			}
		}
		
		if (fromPos < 0) 
		{
			MessageManager mm = ParseMessage.get();
			throw new RQException(mm.getMessage("syntax.lessTable"));
		}
		
		int fromEnd = pos(havePos, orderPos, limitPos, offsetPos, next);
		scanFrom(tokens, fromPos, fromEnd);
		
		int colEnd = fromPos;
		scanColumns(tokens, colPos, colEnd);
		
		if (havePos > 0) 
		{
			int haveEnd = pos(orderPos, limitPos, offsetPos, next);
			Token[] havingTokens = Arrays.copyOfRange(tokens, havePos + 1, haveEnd);
			havingTokens = optimizeWhere(havingTokens, this.parameterList);
			this.havingNode = scanExp(havingTokens, 0, havingTokens.length);
		}

		if (orderPos > 0) 
		{
			int orderEnd = pos(limitPos, offsetPos, next);
			scanOrders(tokens, orderPos, orderEnd);
		}
		
		if (limitPos > 0) 
		{
			int limitEnd = pos(offsetPos, next);
			scanLimit(tokens, limitPos, limitEnd);
		}
		
		if (offsetPos > 0) 
		{
			scanOffset(tokens, offsetPos, next);
		}
	}
	
	private int scanQuantifies(Token []tokens, int start, int next) 
	{
		Token t = tokens[start];
		if(t.isKeyWord()) 
		{
			int c = start;
			if (t.getString().equalsIgnoreCase("DISTINCT")) 
			{
				c++;
				if (c >= next) 
				{
					MessageManager mm = ParseMessage.get();
					throw new RQException(mm.getMessage("syntax.error") + ":scanQuantifies, ??ʼλ?ó???????λ??");
				}
				
				this.hasDistinct = true;
				
				t = tokens[c];
			}

			if(t.isKeyWord() && t.getString().equalsIgnoreCase("TOP")) 
			{
				c++;
				try
				{
					this.topNumber = Integer.parseInt(tokens[c].getString());
					if(this.topNumber < 0)
					{
						throw new NumberFormatException();
					}
				}
				catch(NumberFormatException nfe)
				{
					MessageManager mm = ParseMessage.get();
					throw new RQException(mm.getMessage("syntax.error") + ":scanQuantifies, TOP?ؼ??ֺ??????ӷǸ?????", nfe);
				}
				
				c++;
				if (c >= next) 
				{
					MessageManager mm = ParseMessage.get();
					throw new RQException(mm.getMessage("syntax.error") + ":scanQuantifies, ??ʼλ?ó???????λ??");
				}
			}
			
			return c;
		} 
		else 
		{
			return start;
		}
	}
	
	private void scanLimit(Token []tokens, int start, int next) 
	{
		Token t = tokens[start];
		if(t.isKeyWord("LIMIT")) 
		{
			int c = start + 1;
			if (c >= next) 
			{
				MessageManager mm = ParseMessage.get();
				throw new RQException(mm.getMessage("syntax.error") + ":scanLimit, ??ʼλ?ó???????λ??");
			}
			try
			{
				if(tokens[c].isKeyWord("ALL"))
				{
					this.limitNumber = -1;
				}
				else
				{
					this.limitNumber = Integer.parseInt(tokens[c].getString());
					if(this.limitNumber < 0)
					{
						throw new NumberFormatException();
					}
				}
			}
			catch(NumberFormatException nfe)
			{
				MessageManager mm = ParseMessage.get();
				throw new RQException(mm.getMessage("syntax.error") + ":scanLimit, Limit?ؼ??ֺ??????ӷǸ?????", nfe);
			}
		}
	}
	
	private void scanOffset(Token []tokens, int start, int next) 
	{
		Token t = tokens[start];
		if(t.isKeyWord("OFFSET"))
		{
			int c = start + 1;
			if (c >= next) 
			{
				MessageManager mm = ParseMessage.get();
				throw new RQException(mm.getMessage("syntax.error") + ":scanOffset, ??ʼλ?ó???????λ??");
			}
			try
			{
				this.offsetNumber = Integer.parseInt(tokens[c].getString());
				if(this.offsetNumber < 0)
				{
					throw new NumberFormatException();
				}
			}
			catch(NumberFormatException nfe)
			{
				MessageManager mm = ParseMessage.get();
				throw new RQException(mm.getMessage("syntax.error") + ":scanOffset, Offset?ؼ??ֺ??????ӷǸ?????", nfe);
			}
		}
	}
	
	private void scanFrom(Token[] tokens, int start, int next) 
	{
		start++; // skip over "from"
		
		if (start < next) 
		{
			int wherePos = Tokenizer.scanKeyWord("WHERE", tokens, start, next);
			int byPos = Tokenizer.scanKeyWord("BY", tokens, pos(wherePos, start), next);
			int groupPos = Tokenizer.scanKeyWord("GROUP", tokens, pos(wherePos, start), pos(byPos, next));
			int tableNext = pos(wherePos, pos(groupPos, byPos), next);
			if (start >= tableNext) 
			{
				MessageManager mm = ParseMessage.get();
				throw new RQException(mm.getMessage("syntax.error") + ":scanFrom, ??ʼλ?ó???????λ??");
			}

			if(tokens[start].getString().equals("{"))
			{
				int pos = start + 1;
				if(pos == tableNext)
				{
					MessageManager mm = ParseMessage.get();
					throw new RQException(mm.getMessage("syntax.error") + ":scanFrom, ??????????ʽ??ʼλ?ó???????λ??");
				}
				
				int end = Tokenizer.scanBrace(tokens, start, tableNext);
				
				String tableName = null;
				String aliasName = null;
				
				if(end + 3 == tableNext && tokens[end + 1].isKeyWord("AS"))
				{
					tableName = "";
					aliasName = tokens[end + 2].getString();
				}
				else if(end + 2 == tableNext)
				{
					tableName = "";
					aliasName = tokens[end + 1].getString();
				}
				else if(end + 1 == tableNext)
				{
					tableName = "";
				}
				else
				{
					MessageManager mm = ParseMessage.get();
					throw new RQException(mm.getMessage("syntax.error") + ":scanFrom, ??????????ʽ?Ľ?β??????");
				}
				
				if(aliasName == null)
				{
					aliasName = "";
				}
				
				Token[] expTokens = Arrays.copyOfRange(tokens, pos, end);
				StringBuffer expBuf = new StringBuffer();
				for(int i = 0; i < expTokens.length; i++)
				{
					expBuf.append(expTokens[i].getOriginString());
					expBuf.append(expTokens[i].getSpaces());
				}
				String expStr = expBuf.toString().trim();
				
				Object obj = null;
				try
				{
					//20240731 xingjl
					Sequence seq = new Sequence();
					seq.add(this.fromSeq);
					this.ctx.getComputeStack().pushArg(seq);

					obj = new Expression(this.ics, this.ctx, expStr).calculate(this.ctx);
				}
				catch(Exception ex)
				{
					MessageManager mm = ParseMessage.get();
					throw new RQException(mm.getMessage("syntax.error") + ":scanFrom, ?쳣?ı???(ע?????????Ϊ?ؼ??ֻ??????ֿ?ͷ):"+expStr);
				}

				if(obj instanceof ICursor)
				{
					ICursor cursor = (ICursor)obj;
					DataStruct struct = cursor.getDataStruct();
					if(struct == null)
					{
						Sequence sq = cursor.peek(1);
						if(sq != null)
						{
							struct = sq.dataStruct();
						}
						//cursor.reset();
					}
					this.tableNode = new TableNode(tableName, aliasName, cursor, struct);
				}
				else if(obj instanceof Table)
				{
					ICursor cursor = new MemoryCursor((Table)obj);
					DataStruct struct = ((Table)obj).dataStruct();
					this.tableNode = new TableNode(tableName, aliasName, cursor, struct);
				}
				else if(obj instanceof PhyTable)
				{
					this.tableNode = new TableNode(tableName, aliasName, (PhyTable)obj);
				}
				else
				{
					MessageManager mm = ParseMessage.get();
					throw new RQException(mm.getMessage("syntax.error") + ":scanFrom, ??֧?ֵı?????????");
				}
			}
			else if(tokens[start].getType() == Tokenizer.LPAREN)
			{
				int pos = start + 1;
				if(pos == tableNext)
				{
					MessageManager mm = ParseMessage.get();
					throw new RQException(mm.getMessage("syntax.error") + ":scanFrom, ??ʱ???Ӿ???ʼλ?ó???????λ??");
				}
				
				int end = Tokenizer.scanParen(tokens, start, tableNext);
				
				String tableName = null;
				String aliasName = null;
				
				if(end + 2 == tableNext)
				{
					tableName = "";
					aliasName = tokens[end + 1].getString();
				}
				else if(end + 1 == tableNext)
				{
					tableName = "";
				}
				else
				{
					MessageManager mm = ParseMessage.get();
					throw new RQException(mm.getMessage("syntax.error") + ":scanFrom, ??ʱ???Ӿ?Ľ?β??????");
				}
				
				if(aliasName == null)
				{
					aliasName = "";
				}
				
				if(tokens[pos].getType() == Tokenizer.PARAMMARK)
				{
					if(pos + 1 != end)
					{
						MessageManager mm = ParseMessage.get();
						throw new RQException(mm.getMessage("syntax.error") + ":scanFrom, ??ʱ??ռλ????ʽ????");
					}
					if(this.ds != null)
					{
						if(this.icur == null)
						{
							this.icur = new MemoryCursor(new Table(this.ds));
						}
						this.tableNode = new TableNode(tableName, aliasName, this.icur, this.ds);
						this.icur = null;
						this.ds = null;
					}
					else if(this.tmd != null)
					{
						this.tableNode = new TableNode(tableName, aliasName, this.tmd);
						this.tmd = null;
					}
				}
				else
				{
					SimpleSQL lq = new SimpleSQL(this.ics, tokens, pos, end, parameterList, this.ctx, false);
					lq.setMemory(this.isMemory);
					ICursor cursor = lq.query();
					DataStruct struct = lq.getDataStruct();
					this.tableNode = new TableNode(tableName, aliasName, cursor, struct);
				}
			}
			else
			{
				String tableName = "";
				String aliasName = null;
				int pos = start;
				while(pos < tableNext)
				{
					tableName = tableName + tokens[pos].getOriginString();
					//xingjl 20230323 from D://test/1??????/emps.txt??ȥ??1????ո? 
					//       20231106 ȥ??Ӱ?????????????֧?ֱ????????????ֿ?ͷ???ļ????ݲ?֧?֡?
					tableName = tableName + tokens[pos].getSpaces();
					pos++;
				}
				tableName = tableName.trim();
				if (tableNext - 2 >= start && tokens[tableNext - 1].getType() == Tokenizer.IDENT)
				{
					int splitPos = tableName.lastIndexOf(" ");
					if(splitPos != -1)
					{
						aliasName = tableName.substring(splitPos + 1);
						if(aliasName.equals(tokens[tableNext - 1].getOriginString()))
						{
							tableName = tableName.substring(0, splitPos).trim();
						}
						else
						{
							aliasName = null;
						}
					}
					if(tableNext - 3 >= start && tokens[tableNext - 2].isKeyWord("AS"))
					{
						splitPos = tableName.lastIndexOf(" ");
						if(splitPos != -1)
						{
							String asKeyWord = tableName.substring(splitPos + 1);
							if(asKeyWord.equals(tokens[tableNext - 2].getOriginString()))
							{
								tableName = tableName.substring(0, splitPos).trim();
							}
						}
					}
				}
				if(tableName.startsWith("\"") && tableName.endsWith("\"") 
				&& tableName.substring(1, tableName.length()-1).indexOf("\"") == -1)
				{
					tableName = tableName.substring(1, tableName.length() - 1);
				}
				
				String paramStr = null;
				if(tableName.endsWith(")"))
				{
					int lParenPos = tableName.lastIndexOf("(");
					if(lParenPos != -1)
					{
						paramStr = tableName.substring(lParenPos + 1, tableName.length() - 1).trim();
						tableName = tableName.substring(0, lParenPos).trim()+".dfx";
					}
				}
				
				boolean fileExists = false;
				//System.out.println("tableName " + tableName);
				File[] fs = FileUtil.getFiles(tableName);
				if (fs == null) {
					fs = FileUtil.getFiles(Env.getMainPath()+"/"+tableName);
					if (fs == null && Env.getPaths() != null) {
						for (int i=0; i objs = new ArrayList();
				for (int i=0; i 0) 
			{
				int end = pos(groupPos, byPos, next);
				Token[] whereTokens = Arrays.copyOfRange(tokens, wherePos + 1, end);
				whereTokens = optimizeWhere(whereTokens, this.parameterList);
				ExpressionNode expNode = scanExp(whereTokens, 0, whereTokens.length);
				this.whereNode = expNode;
			}
			
			if (byPos > 0) 
			{
				scanBy(tokens, byPos, next);
			}
		}
		else
		{
			MessageManager mm = ParseMessage.get();
			String n = ":";
			try {n += tokens[start].getString();}catch(Exception e){}
			throw new RQException(mm.getMessage("syntax.error") + ":scanFrom, ?쳣?ı???(ע?????????Ϊ?ؼ??ֻ??????ֿ?ͷ):"+n);
		}
	}
	
	private void scanColumns(Token []tokens, int start, int next) 
	{
		while (start < next) 
		{
			int comma = Tokenizer.scanComma(tokens, start, next);

			if (comma < 0) 
			{
				scanColumn(tokens, start, next);
				break;
			} 
			else 
			{
				scanColumn(tokens, start, comma);
				start = comma + 1;
				if (start >= next) 
				{
					MessageManager mm = ParseMessage.get();
					throw new RQException(mm.getMessage("syntax.error") + ":scanColumns, ??ʼλ?ó???????λ??");
				}
			}
		}
	}
	
	private void scanColumn(Token []tokens, int start, int next) 
	{
		if (start >= next) 
		{
			MessageManager mm = ParseMessage.get();
			throw new RQException(mm.getMessage("syntax.error") + ":scanColumn, ??ʼλ?ó???????λ??");
		}
		
		if (start + 1 == next && tokens[start].equals("*")) 
		{//select *
			String columnName = null;
			String aliasName = null;
			DataStruct ds = this.tableNode.dataStruct();
			if(ds != null)
			{
				String[] fieldNames = ds.getFieldNames();
				for(int i=0, len = fieldNames.length; i=0) continue;
					ArrayList expList = new ArrayList();
					expList.add(new FieldNode(name));
					ExpressionNode expNode = new ExpressionNode(expList);
					columnName = name;
					aliasName = columnName;
					this.finalList.add(aliasName);
					this.aliasList.add(aliasName.toLowerCase());
					this.columnList.add(expNode);
				}
			}
		} 
		else if (start + 3 == next 
				&& this.tableNode.isIdentic(tokens[start].getString())
				&& tokens[start + 1].getType() == Tokenizer.DOT 
				&& tokens[start + 2].equals("*"))
		{//select T.*
			String columnName = null;
			String aliasName = null;
			DataStruct ds = this.tableNode.dataStruct();
			if(ds != null)
			{
				String[] fieldNames = ds.getFieldNames();
				for(int i=0, len = fieldNames.length; i expList = new ArrayList();
					expList.add(new FieldNode(name));
					ExpressionNode expNode = new ExpressionNode(expList);
					columnName = name;
					aliasName = columnName;
					this.finalList.add(aliasName);
					this.aliasList.add(aliasName.toLowerCase());
					this.columnList.add(expNode);
				}
			}
		}
		else if(start + 3 < next
				&& tokens[start].getType() == Tokenizer.LPAREN
				&& tokens[start + 1].isKeyWord("SELECT"))
		{//select (select ...from...)
			int end = Tokenizer.scanParen(tokens, start, next);
			Token[] subQueryTokens = Arrays.copyOfRange(tokens, start + 1, end);
			boolean needDelayed = false;
			for(int n = 0, len = subQueryTokens.length; n < len; n++)
			{
				if(n < len - 2 
				&& subQueryTokens[n].getString().equalsIgnoreCase(this.tableNode.getAlias())
				&& subQueryTokens[n + 1].getType() == Tokenizer.DOT
				&& subQueryTokens[n + 2].getType() == Tokenizer.IDENT)
				{
					String theFieldName = subQueryTokens[n + 2].getString();
					if(theFieldName.startsWith("\"") && theFieldName.endsWith("\"")
					&& theFieldName.substring(1, theFieldName.length() - 1).indexOf("\"") == -1)
					{
						theFieldName = theFieldName.substring(1, theFieldName.length() - 1);
					}
					new FieldNode(theFieldName).optimize();
					n += 2;
					
					needDelayed = true;
				}
			}
			
			String aliasName = null;
			if(end == next - 1)
			{
				aliasName = "_" + this.columnIndex;
			}
			else
			{
				int begin = end + 1;
				if(tokens[end + 1].isKeyWord("AS"))
				{
					if(end + 2 == next)
					{
						MessageManager mm = ParseMessage.get();
						throw new RQException(mm.getMessage("syntax.error") + ":scanColumn, As?ؼ??ֺ???ȱ???б???");
					}
					begin = end + 2;
				}
				aliasName = "";
				for(int p = begin; p < next; p++)
				{
					aliasName += tokens[p].getOriginString();
				}
			}
			
			this.finalList.add(aliasName);
			this.aliasList.add(aliasName.toLowerCase());
			
			if(needDelayed)
			{
				List checkList = new ArrayList();
				for(Token subQueryToken : subQueryTokens)
				{
					checkList.add(subQueryToken.getString().toUpperCase());
				}
				
				if(!this.subQueryOfSelectMap.containsKey(checkList.toString()))
				{
					String uuid = UUID.randomUUID().toString().replace("-", "_");
					
					ArrayList expList = new ArrayList();
					expList.add(new NormalNode("$" + uuid));
					ExpressionNode expNode = new ExpressionNode(expList);
					this.columnList.add(expNode);
					
					Map subQueryMap = new HashMap();
					subQueryMap.put("$" + uuid, subQueryTokens);
					this.subQueryOfSelectEntryList.add(subQueryMap.entrySet().iterator().next());
					
					this.subQueryOfSelectMap.put(checkList.toString(), "$" + uuid);
				}
				else
				{
					String dollar_uuid = this.subQueryOfSelectMap.get(checkList.toString());
					
					ArrayList expList = new ArrayList();
					expList.add(new NormalNode(dollar_uuid));
					ExpressionNode expNode = new ExpressionNode(expList);
					this.columnList.add(expNode);
				}
			}
			else
			{
				SimpleSQL lq = new SimpleSQL(this.ics, subQueryTokens, 0, subQueryTokens.length, this.parameterList, this.ctx, true);
				lq.setMemory(true);
				ICursor cursor = lq.query();
				DataStruct ds = lq.getDataStruct();
				if(ds.getFieldCount() == 1)
				{
					Sequence seq = null;
					if(cursor != null)
					{
						seq = cursor.fetch(2);
					}
					if(seq == null || seq.length() != 1 || seq.dataStruct() == null || seq.dataStruct().getFieldCount() != 1)
					{
						MessageManager mm = ParseMessage.get();
						throw new RQException(mm.getMessage("syntax.error") + ":scanColumn, ??SELECT?Ӿ??з??س???ֵ???Ӳ?ѯֻ??Ϊ???е???");
					}
					Object val = seq.get(1);
					if(val instanceof BaseRecord)
					{
						val = ((BaseRecord)val).getFieldValue(0);
					}
					Token[] valTokens = Tokenizer.parse(getSQLValue(val));
					ExpressionNode expNode = scanExp(valTokens, 0, valTokens.length);
					this.columnList.add(expNode);
				}
				else
				{
					MessageManager mm = ParseMessage.get();
					throw new RQException(mm.getMessage("syntax.error") + ":scanColumn, ???س???ֵ???Ӳ?ѯֻ??Ϊ????");
				}
			}
			
			this.columnIndex++;
		}
		else
		{
			String aliasName = null;
			int expNext = next;
			if(next - 1 > start) 
			{
				Token alias = tokens[next - 1];
				Token prevToken = tokens[next - 2];
				
				if (prevToken.isKeyWord("AS")) 
				{
					if (alias.getType() == Tokenizer.IDENT)
					{
						expNext = next - 2;
						aliasName = alias.getString();
					}
					else
					{
						MessageManager mm = ParseMessage.get();
						throw new RQException(mm.getMessage("syntax.error") + ":scanColumn, ?????б?????ӦΪ?????ֻ??????ַ?");
					}
				} 
				else if (!prevToken.canHaveRightExp()) 
				{
					if (alias.getType() == Tokenizer.IDENT)
					{
						expNext = next - 1;
						aliasName = alias.getString();
					}
					else if (alias.getType() != Tokenizer.KEYWORD && alias.getType() != Tokenizer.RPAREN && alias.getType() != Tokenizer.LEVELMARK && alias.getType() != Tokenizer.TABLEMARK)
					{
						MessageManager mm = ParseMessage.get();
						throw new RQException(mm.getMessage("syntax.error") + ":scanColumn, ij??????ѯ?еı???ʽ?﷨????");
					}
				}
			}
			
			ExpressionNode expNode = scanExp(tokens, start, expNext);
			if(expNode.getNodeList() == null || expNode.getNodeList().size() == 0)
			{
				MessageManager mm = ParseMessage.get();
				throw new RQException(mm.getMessage("syntax.error") + ":scanColumn, ij??????ѯ?еı???ʽΪ??ֵ");
			}
			
			if(aliasName != null)
			{
				if(aliasName.startsWith("\"") && aliasName.endsWith("\"")
				&& aliasName.substring(1, aliasName.length() - 1).indexOf("\"") == -1)
				{
					aliasName = aliasName.substring(1, aliasName.length() - 1);
				}
			}
			else
			{
				String columnName = null;
				if(expNode.getNodeList().size() == 1 && expNode.getNodeList().get(0) instanceof FieldNode)
				{
					columnName = ((FieldNode)expNode.getNodeList().get(0)).getOriginal();
				}
				else
				{
					columnName = "_" + this.columnIndex;
				}
				aliasName = columnName;	
			}
			this.columnIndex++;
			
			this.finalList.add(aliasName);
			this.aliasList.add(aliasName.toLowerCase());
			this.columnList.add(expNode);
		}
	}
	
	public static String scanExp(Token []tokens, List paramList)
	{
		SimpleSelect sdql = new SimpleSelect(null, null);//?????ڽ?????????ȡ?α꣬????Ҫ?????Ķ???
		sdql.setSQLParameters(paramList);
		SimpleSelect.ExpressionNode expNode = sdql.scanExp(tokens, 0, tokens.length);
		expNode.setFromWhere();
		return expNode.toExpression();
	}
	
	private ExpressionNode scanExp(Token []tokens, int start, int next)
	{
		ArrayList expList = new ArrayList();
		boolean hasNot = false;
		for (int i = start; i < next; i++) 
		{
			//if (expList.size()>0) System.out.println(expList.get(expList.size()-1).toExpression());
			//System.out.println(new ExpressionNode(expList).toExpression());
			Token token = tokens[i];
			char type = token.getType();
			if (type == Tokenizer.IDENT) // F, D, A, T.F, T.fun()
			{
				int pos = i + 1;
				if (pos == next) // F, A 
				{
					int begin = i;
					String name = tokens[begin].getString();
					
					if(name.startsWith("\"") && name.endsWith("\"")
					&& name.substring(1, name.length() - 1).indexOf("\"") == -1)
					{
						name = name.substring(1, name.length() - 1);
					}
					
					if(aliasList != null && aliasList.size() != 0)
					{
						if(aliasList.contains(name.toLowerCase()))
						{
							//System.out.println("4----"+name);
							expList.add(new NormalNode("'"+name.toLowerCase()+"'"));
							continue;
						}
					}
					
					expList.add(new FieldNode(name));
				} 
				else if (tokens[pos].getType() == Tokenizer.DOT) //T.F
				{
					pos++;
					if (pos == next) 
					{
						MessageManager mm = ParseMessage.get();
						throw new RQException(mm.getMessage("syntax.error") + ":scanExp, ??ʼλ?ó???????λ??");
					}
					else if (pos + 1 < next && tokens[pos + 1].getType() == Tokenizer.LPAREN) // T.sum(exp)
					{
						MessageManager mm = ParseMessage.get();
						throw new RQException(mm.getMessage("syntax.error") + ":scanExp, ????????ʽ??֧??????д??");
					}
					else // T.F
					{
						int begin = i;
						
						if (tokens[begin + 2].getType() != Tokenizer.IDENT) 
						{
							MessageManager mm = ParseMessage.get();
							throw new RQException(mm.getMessage("syntax.error") + ":scanExp, ij????ѯ?б?????ӷ??ֶ?????");
						}
						
						int fieldNext = begin + 3;
						
						if(begin + 3 < next)
						{
							if (tokens[begin + 3].getType() == Tokenizer.LEVELMARK) 
							{
								fieldNext = begin + 4;
							}
						}

						String tableName = tokens[begin].getString();
						if (this.tableNode != null && !this.tableNode.isIdentic(tableName))
						{
							MessageManager mm = ParseMessage.get();
							throw new RQException(tokens[i].getString() + mm.getMessage("syntax.unknownTable") + ":scanExp");
						}
						
						String fieldName = tokens[begin + 2].getString();
						
						if(fieldName.startsWith("\"") && fieldName.endsWith("\"")
						&& fieldName.substring(1, fieldName.length() - 1).indexOf("\"") == -1)
						{
							fieldName = fieldName.substring(1, fieldName.length() - 1);
						}
						
						expList.add(new FieldNode(fieldName));
						
						i = fieldNext - 1;
					}
				} 
				else if(tokens[pos].getType() == Tokenizer.LPAREN) //sum(exp), year(exp)
				{
					int end = Tokenizer.scanParen(tokens, pos, next);
					String functionName = token.getString();
					
					if(Tokenizer.isGatherFunction(functionName))
					{
						boolean isCountIf = false;
						boolean isFirst = false;
						boolean isLast = false;
						if(functionName.equalsIgnoreCase("COUNTIF"))
						{
							isCountIf = true;
							functionName = "count";
						}
						else if(functionName.equalsIgnoreCase("FIRST"))
						{
							isFirst = true;
							functionName = "top@1";
						}
						else if(functionName.equalsIgnoreCase("LAST"))
						{
							isLast = true;
							functionName = "top@1";
						}
						
						ExpressionNode paramNode = null;
						int begin = i + 2;
						ArrayList tempList = new ArrayList();
						if(isFirst || isLast)
						{
							if(isFirst)
							{
								tempList.add(new NormalNode("1"));
							}
							else if(isLast)
							{
								tempList.add(new NormalNode("-1"));
							}
							tempList.add(new NormalNode(","));
							
							ExpressionNode expNode = scanExp(tokens, begin, end);
							List nodeList = expNode.getNodeList();
							
							List tailList = new ArrayList();
							for(int n = nodeList.size() - 1; n >= 0; n--)
							{
								Node node = nodeList.get(n);
								tailList.add(0, node);
								nodeList.remove(n);
								if(node instanceof NormalNode && ((NormalNode)node).getValue().equals(","))
								{
									break;
								}
							}
							
							Node headNode = nodeList.get(0);
							Node tailNode = nodeList.get(nodeList.size() - 1);
							if(headNode instanceof NormalNode && ((NormalNode)headNode).getValue().equals("[") 
							&& tailNode instanceof NormalNode && ((NormalNode)tailNode).getValue().equals("]"))
							{
								tempList.add(headNode);
								nodeList.remove(headNode);
								tailList.add(0, tailNode);
								nodeList.remove(tailNode);
							}
							
							ArrayList subNodeList = new ArrayList();
							boolean desc = false;
							for(int n = 0; n < nodeList.size(); n++)
							{
								Node node = nodeList.get(n);
								if(node instanceof NormalNode && ((NormalNode)node).getValue().equals("desc"))
								{
									desc = true;
									node = new NormalNode("");
								}
								
								if(node instanceof NormalNode && ((NormalNode)node).getValue().equals(","))
								{
									if(desc)
									{
										tempList.add(new NormalNode("-"));
										tempList.add(new ParenNode(new ExpressionNode(subNodeList)));
									}
									else
									{
										tempList.addAll(subNodeList);
									}
									
									tempList.add(node);
									
									subNodeList = new ArrayList();
									desc = false;
								}
								else
								{
									subNodeList.add(node);
								}
								
								if(n == nodeList.size() - 1)
								{
									if(desc)
									{
										tempList.add(new NormalNode("-"));
										tempList.add(new ParenNode(new ExpressionNode(subNodeList)));
									}
									else
									{
										tempList.addAll(subNodeList);
									}
									
									subNodeList = null;
									desc = false;
								}
							}
							tempList.addAll(tailList);
						}
						else
						{
							while (begin < end) 
							{
								int comma = Tokenizer.scanComma(tokens, begin, end);
								if(comma == -1) 
								{
									if(tempList.size() == 0)
									{
										if(tokens[begin].getString().equals("*") && begin + 1 == end)
										{
											tokens[begin].setString("1");
											tokens[begin].setType(Tokenizer.NUMBER);
										}
										paramNode = scanExp(tokens, begin, end);
									}
									else if(isCountIf && tempList.size() > 0)
									{
										tempList.add(new NormalNode("||"));
										tempList.add(new NormalNode("("));
										tempList.add(scanExp(tokens, begin, end));
										tempList.add(new NormalNode(")"));
									}
									
									if(this.distinctGatherField != null)
									{
										if(isCountIf || !functionName.equalsIgnoreCase("COUNT"))
										{
											MessageManager mm = ParseMessage.get();
											throw new RQException(mm.getMessage("syntax.error") + ":scanExp, ??COUNT?ۺϺ????IJ?????֧??DISTINCT");
										}
										
										String fieldName = paramNode.toExpression();
										if(fieldName == null)
										{
											MessageManager mm = ParseMessage.get();
											throw new RQException(mm.getMessage("syntax.error") + ":scanExp, COUNT(DISTINCT)?IJ?????ʽ????");
										}
										
										functionName = "icount";
										
										this.distinctGatherField = null;
									}
									break;
								} 
								else 
								{
									if(isCountIf)
									{
										if(tempList.size() > 0)
										{
											tempList.add(new NormalNode("||"));
										}
										tempList.add(new NormalNode("("));
										tempList.add(scanExp(tokens, begin, comma));
										tempList.add(new NormalNode(")"));
										begin = comma + 1;
									}
									else
									{
										MessageManager mm = ParseMessage.get();
										throw new RQException(mm.getMessage("syntax.error") + ":scanExp, ij?ۺϺ????IJ???????????");
									}
								}
							}
						}
						if((isCountIf || isFirst || isLast) && paramNode == null && tempList.size() != 0)
						{
							paramNode = new ExpressionNode(tempList);
						}
						
						int size = paramNode.getNodeList().size();
						if (size == 0) 
						{
							MessageManager mm = ParseMessage.get();
							throw new RQException(mm.getMessage("function.paramError") + ":scanExp, ?ۺϺ????IJ????ڵ???????Ϊ??");
						}
						
						expList.add(new GatherNode(functionName, paramNode));
					}
					else
					{
						ExpressionNode paramNode = null;
						int begin = i + 2;
						
						paramNode = scanExp(tokens, begin, end);
					
						expList.add(new FunctionNode(functionName, paramNode));
					}

					i = end;
				}
				else if (tokens[pos].getType() == Tokenizer.LEVELMARK) //F#L
				{
					String fieldName = tokens[i].getString();
					String levelName = tokens[pos].getLevelName();
					
					DimNode dimNode = new DimNode(levelName);
					dimNode.setField(fieldName);
					expList.add(dimNode);
					
					i = pos;
				}
				else if (tokens[pos].getType() == Tokenizer.OPERATOR) //F+G
				{
					int begin = i;
					String fieldName = tokens[begin].getString();
					
					if(fieldName.startsWith("\"") && fieldName.endsWith("\"")
					&& fieldName.substring(1, fieldName.length() - 1).indexOf("\"") == -1)
					{
						fieldName = fieldName.substring(1, fieldName.length() - 1);
					}
					
					if(aliasList != null && aliasList.size() != 0)
					{
						if(aliasList.contains(fieldName.toLowerCase()))
						{
							//System.out.println("1----"+fieldName);
							expList.add(new NormalNode("'"+fieldName.toLowerCase()+"'"));
							continue;
						}
					}
					
					expList.add(new FieldNode(fieldName));
				}
				else if (tokens[pos].getType() == Tokenizer.COMMA) //F,
				{
					int begin = i;
					String fieldName = tokens[begin].getString();
					
					if(fieldName.startsWith("\"") && fieldName.endsWith("\"")
					&& fieldName.substring(1, fieldName.length() - 1).indexOf("\"") == -1)
					{
						fieldName = fieldName.substring(1, fieldName.length() - 1);
					}
					
					if(aliasList != null && aliasList.size() != 0)
					{
						if(aliasList.contains(fieldName.toLowerCase()))
						{
							//System.out.println("2----"+fieldName);
							expList.add(new NormalNode("'"+fieldName.toLowerCase()+"'"));
							continue;
						}
					}
					//System.out.println("7----"+fieldName+",,,"+new FieldNode(fieldName).toExpression());
					
					expList.add(new FieldNode(fieldName));
				}
				else if (tokens[pos].getType() == Tokenizer.KEYWORD)//F asc/desc, F order by
				{
					int begin = i;
					String fieldName = tokens[begin].getString();
					
					if(fieldName.startsWith("\"") && fieldName.endsWith("\"")
					&& fieldName.substring(1, fieldName.length() - 1).indexOf("\"") == -1)
					{
						fieldName = fieldName.substring(1, fieldName.length() - 1);
					}
					
					if(aliasList != null && aliasList.size() != 0)
					{
						if(aliasList.contains(fieldName.toLowerCase()))
						{
							//System.out.println("3----"+fieldName);
							expList.add(new NormalNode("'"+fieldName.toLowerCase()+"'"));
							continue;
						}
					}
					
					expList.add(new FieldNode(fieldName));
				}
				else
				{
					MessageManager mm = ParseMessage.get();
					throw new RQException(mm.getMessage("syntax.error") + ":scanExp, ?ֶ???????˷Ƿ????ַ?");
				}
			} 
			else if (type == Tokenizer.LPAREN) 
			{
				int end = Tokenizer.scanParen(tokens, i, next);
				Token[] subQueryTokens = Arrays.copyOfRange(tokens, i + 1, end);
				boolean isSubQuery = false;
				if(Tokenizer.scanKeyWords(new String[]{"SELECT","UNION","INTERSECT","EXCEPT","MINUS"}, subQueryTokens, 0, subQueryTokens.length - 1) != -1)
				{
					isSubQuery = true;
				}
				
				if(isSubQuery)
				{
					boolean needDelayed = false;
					for(int n = 0, len = subQueryTokens.length; n < len; n++)
					{
						if(n < len - 2 
						&& subQueryTokens[n].getString().equalsIgnoreCase(this.tableNode.getAlias())
						&& subQueryTokens[n + 1].getType() == Tokenizer.DOT
						&& subQueryTokens[n + 2].getType() == Tokenizer.IDENT)
						{
							String theFieldName = subQueryTokens[n + 2].getString();
							if(theFieldName.startsWith("\"") && theFieldName.endsWith("\"")
							&& theFieldName.substring(1, theFieldName.length() - 1).indexOf("\"") == -1)
							{
								theFieldName = theFieldName.substring(1, theFieldName.length() - 1);
							}
							new FieldNode(theFieldName).optimize();
							n += 2;
							
							needDelayed = true;
						}
					}
					
					if(needDelayed)
					{
						List checkList = new ArrayList();
						for(Token subQueryToken : subQueryTokens)
						{
							checkList.add(subQueryToken.getString().toUpperCase());
						}
						
						if(i > 0 && tokens[i - 1].isKeyWord("IN"))
						{
							if(!this.subQueryOfInMap.containsKey(checkList.toString()))
							{
								String uuid = UUID.randomUUID().toString().replace("-", "_");
								
								ArrayList list = new ArrayList();
								list.add(new NormalNode("$" + uuid)); //??join??????Ӳ?ѯ?ֶ???Ϊ?Ǻ????ӵIJ?????ѡ???ֶ?
								ExpressionNode expNode = new ExpressionNode(list);
								expList.add(expNode);
								
								Map subQueryMap = new HashMap();
								subQueryMap.put("$" + uuid, subQueryTokens);
								this.subQueryOfInEntryList.add(subQueryMap.entrySet().iterator().next());
								
								this.subQueryOfInMap.put(checkList.toString(), "$" + uuid);
							}
							else
							{
								String dollar_uuid = this.subQueryOfInMap.get(checkList.toString());
								
								ArrayList list = new ArrayList();
								list.add(new NormalNode(dollar_uuid));//??join??????Ӳ?ѯ?ֶ???Ϊ?Ǻ????ӵIJ?????ѡ???ֶ?
								ExpressionNode expNode = new ExpressionNode(list);
								expList.add(expNode);
							}
						}
						else
						{
							if(!this.subQueryOfWhereMap.containsKey(checkList.toString()))
							{
								String uuid = UUID.randomUUID().toString().replace("-", "_");
								
								ArrayList list = new ArrayList();
								list.add(new NormalNode("$" + uuid));//??join??????Ӳ?ѯ?ֶ???Ϊ?Ǻ????ӵIJ?????ѡ???ֶ?
								ExpressionNode expNode = new ExpressionNode(list);
								expList.add(expNode);
								
								Map subQueryMap = new HashMap();
								subQueryMap.put("$" + uuid, subQueryTokens);
								this.subQueryOfWhereEntryList.add(subQueryMap.entrySet().iterator().next());
								
								this.subQueryOfWhereMap.put(checkList.toString(), "$" + uuid);
							}
							else
							{
								String dollar_uuid = this.subQueryOfWhereMap.get(checkList.toString());
								
								ArrayList list = new ArrayList();
								list.add(new NormalNode(dollar_uuid));//??join??????Ӳ?ѯ?ֶ???Ϊ?Ǻ????ӵIJ?????ѡ???ֶ?
								ExpressionNode expNode = new ExpressionNode(list);
								expList.add(expNode);
							}
						}
					}
					else
					{
						SimpleSQL lq = new SimpleSQL(this.ics, subQueryTokens, 0, subQueryTokens.length, this.parameterList, this.ctx, true);
						lq.setMemory(true);
						ICursor cursor = lq.query();
						DataStruct ds = lq.getDataStruct();
						if(ds.getFieldCount() == 1)
						{
							expList.add(new TableNode("", "", cursor, ds));
						}
						else
						{
							MessageManager mm = ParseMessage.get();
							throw new RQException(mm.getMessage("syntax.error") + ":scanExp, ???س???ֵ???Ӳ?ѯֻ??Ϊ????");
						}
					}
				}
				else
				{
					expList.add(new ParenNode(scanExp(subQueryTokens, 0, subQueryTokens.length)));//ʵ???ϲ????Ӳ?ѯ
				}
				
				i = end;
			}
			else if (token.isKeyWord("LEFT") && i+1 != next && tokens[i+1].getType() == Tokenizer.LPAREN) 
			{
				token.setType(Tokenizer.IDENT);
				i = i - 1;
			}
			else if (token.isKeyWord("RIGHT") && i+1 != next && tokens[i+1].getType() == Tokenizer.LPAREN) 
			{
				token.setType(Tokenizer.IDENT);
				i = i - 1;
			}
			else if (token.isKeyWord("FIRST") && i+1 != next && tokens[i+1].getType() == Tokenizer.LPAREN) 
			{
				token.setType(Tokenizer.IDENT);
				i = i - 1;
			}
			else if (token.isKeyWord("ORDER") && i+1 != next && tokens[i+1].isKeyWord("BY"))
			{
				expList.add(0, new NormalNode(","));
				int comma = Tokenizer.scanComma(tokens, i+2, next);
				if(comma != -1)
				{
					expList.add(0, new NormalNode("]"));
				}
				expList.addAll(0, scanExp(tokens, i+2, next).getNodeList());
				if(comma != -1)
				{
					expList.add(0, new NormalNode("["));
				}
				i = next;
			}
			else if (token.isKeyWord("IN")) 
			{
				int pos = i + 1;
				if (pos == next || tokens[pos].getType() != Tokenizer.LPAREN && tokens[pos].getType() != Tokenizer.IDENT) 
				{
					MessageManager mm = ParseMessage.get();
					throw new RQException(mm.getMessage("syntax.error") + ":scanExp, IN?Ӿ?Ӿ?ĸ?ʽ????");
				}
				
				ArrayList tempList = new ArrayList();
				for(int x = expList.size() - 1; x >= 0; x--)
				{
					if(expList.get(x) instanceof NormalNode)
					{
						NormalNode normal = (NormalNode)expList.get(x);
						if(normal.getValue().equalsIgnoreCase("AND") || normal.getValue().equalsIgnoreCase("&&") 
								|| normal.getValue().equalsIgnoreCase("OR") || normal.getValue().equalsIgnoreCase("||"))
						{
							break;
						}
					}
					tempList.add(0, expList.get(x));
					expList.remove(x);
				}
				ExpressionNode expNode = new ExpressionNode(tempList);

				if(tokens[pos].getType() == Tokenizer.LPAREN)
				{
					int end = Tokenizer.scanParen(tokens, pos, next);
					ExpressionNode paramNode = scanExp(tokens, pos, end + 1);//????????????????Խ????Ӳ?ѯ????
					expList.add(new InNode(expNode, paramNode, hasNot));
					i = end;
				}
				else if(tokens[pos].getType() == Tokenizer.IDENT)
				{
					ArrayList paramList = new ArrayList();
					String theFieldName = tokens[pos].getOriginString();
					if(theFieldName.startsWith("\"") && theFieldName.endsWith("\"")
					&& theFieldName.substring(1, theFieldName.length() - 1).indexOf("\"") == -1)
					{
						theFieldName = theFieldName.substring(1, theFieldName.length() - 1);
					}
					paramList.add(new FieldNode(theFieldName));//join??????Ӳ?ѯ?ֶ???Ϊ?Ѿ?????????????ѡ???ֶ?
					ExpressionNode paramNode = new ExpressionNode(paramList);
					expList.add(new InNode(expNode, paramNode, hasNot));
					i = pos;
				}
				
				if(hasNot)
				{
					hasNot = false;
				}
			}
			else if (token.isKeyWord("LIKE")) 
			{
				int pos = i + 1;
				if (pos == next) 
				{
					MessageManager mm = ParseMessage.get();
					throw new RQException(mm.getMessage("syntax.error") + ":scanExp, Like?Ӿ?ĸ?ʽ????");
				}
				else 
				{
//					if(tokens[pos].getType() != Tokenizer.STRING)
//					{
//						if(!tokens[pos].getString().startsWith("\"") || !tokens[pos].getString().endsWith("\"") 
//							|| tokens[pos].getString().substring(1, tokens[pos].getString().length()-1).indexOf("\"") != -1)
//						{
//							MessageManager mm = ParseMessage.get();
//							throw new RQException(mm.getMessage("syntax.error") + ":scanExp, Like?Ӿ????ʽ???ʹ???");
//						}
//					}
				}
				
//				String pattern = tokens[pos].getString().substring(1, tokens[pos].getString().length() - 1);//??""??''?Ա??ڲ???,????ټ???
				
				ArrayList tempList = new ArrayList();
				for(int x = expList.size() - 1; x >= 0; x--)
				{
					if(expList.get(x) instanceof NormalNode)
					{
						NormalNode normal = (NormalNode)expList.get(x);
						if(normal.getValue().equalsIgnoreCase("AND") || normal.getValue().equalsIgnoreCase("&&") 
								|| normal.getValue().equalsIgnoreCase("OR") || normal.getValue().equalsIgnoreCase("||"))
						{
							break;
						}
					}
					tempList.add(0, expList.get(x));
					expList.remove(x);
				}
				ExpressionNode expNode = new ExpressionNode(tempList);
				
				expList.add(new LikeNode(expNode, tokens[pos], hasNot,this));
				if(hasNot)
				{
					hasNot = false;
				}
				
				i = pos;
			}
			else if (token.isKeyWord("CASE")) 
			{
				int endPos = Tokenizer.scanCaseEnd(tokens, i, next);
				
				int elsePos = Tokenizer.scanCaseElse(tokens, i, endPos);
				
				List nodeList = new ArrayList();

				int pos = i + 1;
				boolean needOptimizeFilter = false;
				if(!tokens[pos].isKeyWord("WHEN"))
				{
					int whenPos = Tokenizer.scanCaseWhen(tokens, pos, elsePos == -1 ? endPos : elsePos);
					if(whenPos == -1)
					{
						throw new RQException("CASE???ȱ??WHEN?ؼ???");
					}
					ExpressionNode caseNode = scanExp(tokens, pos, whenPos);
					nodeList.add(caseNode);
					pos = whenPos;
				}
				else
				{
					nodeList.add(new NormalNode("true"));
					needOptimizeFilter = true;
				}
				
				while(pos < (elsePos == -1 ? endPos : elsePos))
				{
					int whenPos = Tokenizer.scanCaseWhen(tokens, pos, elsePos == -1 ? endPos : elsePos);
					if(whenPos == -1)
					{
						whenPos = elsePos == -1 ? endPos : elsePos;
					}
					
					int thenPos = Tokenizer.scanCaseThen(tokens, pos, whenPos);
					
					if(needOptimizeFilter)
					{
						Token[] whenTokens = Arrays.copyOfRange(tokens, pos + 1, thenPos);
						PerfectWhere pw = new PerfectWhere(whenTokens, this.parameterList);
						whenTokens = pw.getTokens(true);
						
						ExpressionNode whenNode = scanExp(whenTokens, 0, whenTokens.length);
						nodeList.add(whenNode);
					}
					else
					{
						ExpressionNode whenNode = scanExp(tokens, pos + 1, thenPos);
						nodeList.add(whenNode);
					}
					
					ExpressionNode thenNode = scanExp(tokens, thenPos+1, whenPos);
					nodeList.add(thenNode);
					
					pos = whenPos;
				}
				
				if(elsePos != -1)
				{
					ExpressionNode elseNode = scanExp(tokens, elsePos + 1, endPos);
					nodeList.add(elseNode);
				}
				
				expList.add(new CaseNode(nodeList));
				
				i = endPos;
			}
			else if (token.isKeyWord("BETWEEN")) 
			{
				ArrayList tempList = new ArrayList();
				for(int x = expList.size() - 1; x >= 0; x--)
				{
					if(expList.get(x) instanceof NormalNode)
					{
						NormalNode normal = (NormalNode)expList.get(x);
						if(normal.getValue().equalsIgnoreCase("AND") || normal.getValue().equalsIgnoreCase("&&") 
								|| normal.getValue().equalsIgnoreCase("OR") || normal.getValue().equalsIgnoreCase("||"))
						{
							break;
						}
					}
					tempList.add(0, expList.get(x));
					expList.remove(x);
				}
				ExpressionNode expNode = new ExpressionNode(tempList);
				
				int andPos = Tokenizer.scanKeyWord("AND", tokens, i + 1, next);
				if(andPos == -1)
				{
					MessageManager mm = ParseMessage.get();
					throw new RQException(mm.getMessage("syntax.error") + ":scanExp, Between????ȱ?ٹؼ???and");
				}
				ExpressionNode floorValue = scanExp(tokens, i + 1, andPos);
				
				int endAnd = Tokenizer.scanKeyWord("AND", tokens, andPos + 1, next);
				int endOr = Tokenizer.scanKeyWord("OR", tokens, andPos + 1, next);
				int end = -1;
				if(endAnd == -1 || endOr == -1)
				{
					end = pos(endAnd, endOr, next);
				}
				else
				{
					end = endAnd < endOr ? endAnd : endOr;
				}
				ExpressionNode ceilValue = scanExp(tokens, andPos + 1, end);
				
				expList.add(new BetweenNode(expNode, floorValue, ceilValue, hasNot));
				if(hasNot)
				{
					hasNot = false;
				}
				
				i = end - 1;
			}
			else if (token.isKeyWord("EXISTS")) 
			{
				int pos = i + 1;
				if (pos + 1 >= next || tokens[pos].getType() != Tokenizer.LPAREN || !tokens[pos + 1].isKeyWord("SELECT")) 
				{
					MessageManager mm = ParseMessage.get();
					throw new RQException(mm.getMessage("syntax.error") + ":scanExp, Exists?Ӿ?Ӿ?ĸ?ʽ????");
				}
				
				int end = Tokenizer.scanParen(tokens, pos, next);
				Token[] subQueryTokens = Arrays.copyOfRange(tokens, pos + 1, end);
				boolean needDelayed = false;
				for(int n = 0, len = subQueryTokens.length; n < len; n++)
				{
					if(n < len - 2 
					&& subQueryTokens[n].getString().equalsIgnoreCase(this.tableNode.getAlias())
					&& subQueryTokens[n + 1].getType() == Tokenizer.DOT
					&& subQueryTokens[n + 2].getType() == Tokenizer.IDENT)
					{
						String theFieldName = subQueryTokens[n + 2].getString();
						if(theFieldName.startsWith("\"") && theFieldName.endsWith("\"")
						&& theFieldName.substring(1, theFieldName.length() - 1).indexOf("\"") == -1)
						{
							theFieldName = theFieldName.substring(1, theFieldName.length() - 1);
						}
						new FieldNode(theFieldName).optimize();
						n += 2;
						
						needDelayed = true;
					}
				}
				
				if(needDelayed)
				{
					List checkList = new ArrayList();
					for(Token subQueryToken : subQueryTokens)
					{
						checkList.add(subQueryToken.getString().toUpperCase());
					}
					if(!this.subQueryOfExistsMap.containsKey(checkList.toString()))
					{
						String uuid = UUID.randomUUID().toString().replace("-", "_");
						
						Map subQueryMap = new HashMap();
						subQueryMap.put("$" + uuid, subQueryTokens);
						this.subQueryOfExistsEntryList.add(subQueryMap.entrySet().iterator().next());
						
						expList.add(new NormalNode("$" + uuid));
						if(hasNot) //not exists : is null
						{
							expList.add(new NormalNode("=="));
						}
						else
						{
							expList.add(new NormalNode("!="));
						}
						expList.add(new NormalNode("null"));
						
						this.subQueryOfExistsMap.put(checkList.toString(), "$" + uuid);
					}
					else
					{
						String dollar_uuid = this.subQueryOfExistsMap.get(checkList.toString());

						expList.add(new NormalNode(dollar_uuid));
						if(hasNot) //not exists : is null
						{
							expList.add(new NormalNode("=="));
						}
						else
						{
							expList.add(new NormalNode("!="));
						}
						expList.add(new NormalNode("null"));
					}
				}
				else
				{
					SimpleSQL lq = new SimpleSQL(this.ics, subQueryTokens, 0, subQueryTokens.length, this.parameterList, this.ctx, true);
					lq.setMemory(true);
					ICursor cursor = lq.query();
					Sequence seq = null;
					if(cursor != null)
					{
						seq = cursor.peek(1);
					}
					if(seq == null)
					{
						if(hasNot)
						{
							expList.add(new NormalNode("1"));
							expList.add(new NormalNode("=="));
							expList.add(new NormalNode("1"));
						}
						else
						{
							expList.add(new NormalNode("1"));
							expList.add(new NormalNode("=="));
							expList.add(new NormalNode("0"));
						}
					}
					else
					{
						if(hasNot)
						{
							expList.add(new NormalNode("1"));
							expList.add(new NormalNode("=="));
							expList.add(new NormalNode("0"));
						}
						else
						{
							expList.add(new NormalNode("1"));
							expList.add(new NormalNode("=="));
							expList.add(new NormalNode("1"));
						}
					}
				}
				
				if(hasNot)
				{
					hasNot = false;
				}
				
				i = end;
			}
			else if (type == Tokenizer.PARAMMARK)
			{
				ParamNode paramNode = new ParamNode();
				String strIndex = tokens[i].getString().substring(1);
					
				if(strIndex.length() != 0)
				{
					int paramIndex = Integer.parseInt(strIndex);
					paramNode.setIndex(paramIndex);
				}
				else
				{
					MessageManager mm = ParseMessage.get();
					throw new RQException(mm.getMessage("syntax.error") + ":scanExp, ????ռλ??????????");
				}
				expList.add(paramNode);
			}
			else
			{
				String value = token.getString();
				if (token.getType() == Tokenizer.OPERATOR)
				{
					if(value.equalsIgnoreCase("="))
					{
						if (i == start)
						{
							MessageManager mm = ParseMessage.get();
							throw new RQException(mm.getMessage("syntax.error") + ":scanExp, ????ʽ??????'='?ſ?ͷ");
						}
						else if(tokens[i-1].getType() != Tokenizer.OPERATOR) 
						{
							if(hasNot)
							{
								value = "!=";
							}
							else
							{
								value = "==";
							}
						}
					}
					else if(value.equalsIgnoreCase(">"))
					{
						if (i + 1 == next)
						{
							MessageManager mm = ParseMessage.get();
							throw new RQException(mm.getMessage("syntax.error") + ":scanExp, ????ʽ??????'>'?Ž?β");
						}
						else if(tokens[i + 1].getType() == Tokenizer.OPERATOR) 
						{
							if(tokens[i + 1].getString().equalsIgnoreCase("=") && (i + 1 < next))
							{
								if(hasNot)
								{
									value = "<";
									i = i + 1;
								}
							}
							else
							{
								MessageManager mm = ParseMessage.get();
								throw new RQException(mm.getMessage("syntax.error") + ":scanExp, ij????ʽ??ʹ???˲?֧?ֵIJ?????");
							}
						}
						else
						{
							if(hasNot)
							{
								value = "<=";
							}
						}
					}
					else if(value.equalsIgnoreCase("<"))
					{
						if (i + 1 == next)
						{
							MessageManager mm = ParseMessage.get();
							throw new RQException(mm.getMessage("syntax.error") + ":scanExp, ????ʽ??????'<'?Ž?β");
						}
						else if(tokens[i + 1].getType() == Tokenizer.OPERATOR) 
						{
							if(tokens[i + 1].getString().equalsIgnoreCase("=") && (i + 1 < next))
							{
								if(hasNot)
								{
									value = ">";
									i = i + 1;
								}
							}
							else if(tokens[i + 1].getString().equalsIgnoreCase(">") && (i + 1 < next))
							{
								if(hasNot)
								{
									value = "=";
									i = i + 1;
								}
								else
								{
									value = "!=";
									i = i + 1;
								}
							}
							else
							{
								MessageManager mm = ParseMessage.get();
								throw new RQException(mm.getMessage("syntax.error") + ":scanExp, ij????ʽ??ʹ???˲?֧?ֵIJ?????");
							}
						}
						else
						{
							if(hasNot)
							{
								value = ">=";
							}
						}
					}
					else if(value.equalsIgnoreCase("!"))
					{
						if (i + 1 == next)
						{
							MessageManager mm = ParseMessage.get();
							throw new RQException(mm.getMessage("syntax.error") + ":scanExp, ????ʽ??????'!'?Ž?β");
						}
						else if(tokens[i + 1].getType() == Tokenizer.OPERATOR) 
						{
							if(tokens[i + 1].getString().equalsIgnoreCase("=") && (i + 1 < next))
							{
								if(hasNot)
								{
									value = "==";
									i = i + 1;
								}
							}
							else
							{
								MessageManager mm = ParseMessage.get();
								throw new RQException(mm.getMessage("syntax.error") + ":scanExp, ij????ʽ??ʹ???˲?֧?ֵIJ?????");
							}
						}
						else
						{
							MessageManager mm = ParseMessage.get();
							throw new RQException(mm.getMessage("syntax.error") + ":scanExp, ????ʽ??'!'???ܵ???ʹ??");
						}
					}
					
					if(hasNot)
					{
						hasNot = false;
					}
				}
				else if(token.getType() == Tokenizer.KEYWORD)
				{	
					if(value.equalsIgnoreCase("AND"))
					{
						value = "&&";
					}
					else if(value.equalsIgnoreCase("OR"))
					{
						value = "||";
					}
					else if(value.equalsIgnoreCase("NOT"))
					{
						hasNot = true;
						value = "";
					}
					else if(value.equalsIgnoreCase("IS"))
					{
						if (i + 1 == next)
						{
							MessageManager mm = ParseMessage.get();
							throw new RQException(mm.getMessage("syntax.error") + ":scanExp, Is?ؼ????÷?????");
						}
						else if(tokens[i + 1].getType() == Tokenizer.KEYWORD) 
						{
							if(tokens[i + 1].getString().equalsIgnoreCase("NOT"))
							{
								if (i + 2 == next)
								{
									MessageManager mm = ParseMessage.get();
									throw new RQException(mm.getMessage("syntax.error") + ":scanExp, Is Not?ؼ????÷?????");
								}
								
								if(tokens[i + 2].getType() == Tokenizer.KEYWORD)
								{
									if(tokens[i + 2].getString().equalsIgnoreCase("NULL"))
									{
										value = "!=";
									}
									else
									{
										MessageManager mm = ParseMessage.get();
										throw new RQException(mm.getMessage("syntax.error") + ":scanExp, Is Not?ؼ???ֻ?ܺ??null");
									}
								}
								else
								{
									MessageManager mm = ParseMessage.get();
									throw new RQException(mm.getMessage("syntax.error") + ":scanExp, Is Not?ؼ???ֻ?ܺ??null");
								}
								i = i + 1; //????not??ֹӰ??????????
							}
							else if(tokens[i + 1].getString().equalsIgnoreCase("NULL"))
							{
								value = "==";
							}
							else
							{
								MessageManager mm = ParseMessage.get();
								throw new RQException(mm.getMessage("syntax.error") + ":scanExp, Is?ؼ???ֻ?ܺ??null");
							}
						}
						else
						{
							MessageManager mm = ParseMessage.get();
							throw new RQException(mm.getMessage("syntax.error") + ":scanExp, Is?ؼ????÷?????");
						}
					}
					else if(value.equalsIgnoreCase("NULL"))
					{
						value = "null";
					}
					else if(value.equalsIgnoreCase("DISTINCT"))
					{
						this.distinctGatherField = "";
						value = "";
					}
					else if(value.equalsIgnoreCase("ASC"))
					{
						value = "";
					}
					else if(value.equalsIgnoreCase("DESC"))
					{
						value = "desc";
					}
					else
					{
						MessageManager mm = ParseMessage.get();
						throw new RQException(mm.getMessage("syntax.error") + ":scanExp, ??֧?ֵĹؼ????÷?:" + value);
					}
				}
				else if(token.getType() == Tokenizer.STRING)
				{
					value = value.trim();
					value = value.substring(1, value.length()-1);
					value = "\"" + value + "\"";
				}
				
				expList.add(new NormalNode(value));
			}
		}

		int size = expList.size();
		if (size == 0) 
		{
			expList.add(new NormalNode(""));
		}
		
		return new ExpressionNode(expList);
	}
	
	private void scanBy(Token []tokens, int start, int next) 
	{
		while (start < next) 
		{
			start++;
			if (start == next) 
			{
				MessageManager mm = ParseMessage.get();
				throw new RQException(mm.getMessage("syntax.error") + ":scanBy, ??ʼλ?ó???????λ??");
			}
			
			int end = Tokenizer.scanComma(tokens, start, next);
			if (end < 0)
			{
				end = next;
			}
			
			int atPos = Tokenizer.scanKeyWord("AT", tokens, start, end);
			if (atPos < 0) 
			{
				ExpressionNode expNode = scanExp(tokens, start, end);
				if(expNode.getNodeList() == null || expNode.getNodeList().size() == 0)
				{
					MessageManager mm = ParseMessage.get();
					throw new RQException(mm.getMessage("syntax.error") + ":scanBy, ???????Ϊ??ֵ");
				}
				Node node = null;
				if(expNode.getNodeList().size() == 1)
				{
					if(expNode.getNodeList().get(0) instanceof NormalNode)
					{
						String value = ((NormalNode)expNode.getNodeList().get(0)).getValue();
						if(value != null && !value.trim().isEmpty() && Pattern.compile("^[\\d]+$").matcher(value).matches())
						{
							node = expNode.getNodeList().get(0);
						}
					}
				}
				if(node == null && expNode.hasField(false))
				{
					node = expNode;
				}
				if(node == null)
				{
					MessageManager mm = ParseMessage.get();
					throw new RQException(mm.getMessage("syntax.error") + ":scanBy, ??????????Ͳ???");
				}
				this.groupList.add(node);
			} 
			else //not support 'AT'
			{
				MessageManager mm = ParseMessage.get();
				throw new RQException(mm.getMessage("syntax.error") + ":scanBy, ??֧??At???");
			}
			start = end;
		}
		if(this.groupList == null || this.groupList.size() == 0)
		{
			MessageManager mm = ParseMessage.get();
			throw new RQException(mm.getMessage("syntax.error") + ":scanBy, û?????????κη?????");
		}
	}
	
	private void scanOrders(Token []tokens, int start, int next)
	{
		start++;
		if (start == next || !tokens[start].isKeyWord("BY")) 
		{
			MessageManager mm = ParseMessage.get();
			throw new RQException(mm.getMessage("syntax.error") + ":scanOrders, Order?Ӿ??ʽ????");
		}

		while (start < next) 
		{
			start++;
			if (start == next) 
			{
				MessageManager mm = ParseMessage.get();
				throw new RQException(mm.getMessage("syntax.error") + ":scanOrders, ??ʼλ?ó???????λ??");
			}
			
			int end = Tokenizer.scanComma(tokens, start, next);
			if (end < 0)
			{
				end = next;
			}
			
			ExpressionNode orderNode = scanExp(tokens, start, end);
			
			boolean desc = false;
			Node tail = orderNode.getNodeList().get(orderNode.getNodeList().size() - 1);
			if(tail instanceof NormalNode && ((NormalNode)tail).getValue().equals("desc"))
			{
				desc = true;
				orderNode.getNodeList().remove(tail);
			}
			
			Node node = null;
			if(orderNode.getNodeList().size() == 2 && orderNode.getNodeList().get(1) instanceof NormalNode
				&& ((NormalNode)orderNode.getNodeList().get(1)).getValue().isEmpty() || orderNode.getNodeList().size() == 1)
			{
				if(orderNode.getNodeList().get(0) instanceof NormalNode)
				{
					String value = ((NormalNode)orderNode.getNodeList().get(0)).getValue();
					if(value != null && !value.trim().isEmpty() && Pattern.compile("^[\\d]+$").matcher(value).matches())
					{
						node = orderNode.getNodeList().get(0);
					}
				}
			}
			if(node == null && orderNode.hasField(true))
			{
				node = orderNode;
			}
			if(node == null)
			{
				MessageManager mm = ParseMessage.get();
				throw new RQException(mm.getMessage("syntax.error") + ":scanOrders, ??????????Ͳ???");
			}
			
			if(desc)
			{
				ArrayList newNodeList = new ArrayList();
				newNodeList.add(new NormalNode("-"));
				newNodeList.add(new ParenNode(orderNode));
				node = new ExpressionNode(newNodeList);
				desc = false;
			}
			
			this.sortList.add(node);
			start = end;
		}
		
		if (this.sortList == null || this.sortList.size() == 0) 
		{
			MessageManager mm = ParseMessage.get();
			throw new RQException(mm.getMessage("syntax.error") + ":scanOrders, ?????ֶβ???Ϊ??ֵ");
		}
	}
	
	public static List fnames = Arrays.asList(new String[]{"_file","_ext","_date","_size"});
	private void execute()
	{
		if(this.tableNode != null)
		{
			if(this.columnList != null && this.columnList.size() != 0)
			{
				for(ExpressionNode expNode : this.columnList)
				{
					expNode.optimize();
				}
			}
			
			if(this.groupList != null && this.groupList.size() != 0)
			{
				List tempList = new ArrayList();
				for(int g=0, sz=this.groupList.size(); g this.columnList.size())
							{
								MessageManager mm = ParseMessage.get();
								throw new RQException(mm.getMessage("syntax.error") + ":execute, ??????ȡ???кŲ???");
							}
						}
						catch(NumberFormatException ex)
						{
							MessageManager mm = ParseMessage.get();
							throw new RQException(mm.getMessage("syntax.error") + ":execute, ??????????Ͳ???", ex);
						}
						grpNode = this.columnList.get(colNo - 1);
					}
					grpNode.optimize();
					tempList.add(grpNode);
				}
				this.groupList = tempList;
			}
			
			if(this.whereNode != null)
			{
				this.whereNode.optimize();
			}
			
			if(this.havingNode != null)
			{
				this.havingNode.optimize();
			}
			
			if(this.sortList != null && this.sortList.size() != 0)
			{
				for(int s=0, sz=this.sortList.size(); s=0) {
					qfnames += "," + fds[a];
				}
			}
			if (qfnames.length()>0) {
				//this.tableNode.setFileAttrQuery(true);
				//fds = qfnames.substring(1).split(",");
			}

			
			Map stdMap = new LinkedHashMap();
			DataStruct gds = this.tableNode.dataStruct();
			
			if(gds != null && gds.getFieldCount() > 0)
			{
				if(fds.length == 0)
				{
					fds = new String[1];
					fds[0] = gds.getFieldName(0);
					bak = new String[1];
					//System.out.println("5----"+fds[0].toLowerCase());
					bak[0] = "'" + fds[0].toLowerCase() + "'";
					fxs = new Expression[1];
					fxs[0] = new Expression(String.format("#%d", 1));
				}
				else
				{
					String[] fns = gds.getFieldNames();
					Map n2cMap = new LinkedHashMap();
					Next:
					for(int a = 0; a < fds.length; a++)
					{
						//System.out.println("6----"+bak[a]);
						bak[a] = "'" + fds[a] + "'";
						// 20220715 xingjl add
						fxs[a] = new Expression(String.format("#%d", a+1));
						
						for(int b = 0; b < fns.length; b++)
						{
							// 20220715 xingjl remove
							//fxs[a] = new Expression(String.format("#%d", b+1));
							
							if(fds[a].equalsIgnoreCase(fns[b]))
							{
								if(whereExp != null && this.tableNode.getType() == TableNode.TYPE_GTB)
								{
									n2cMap.put(bak[a], fns[b]);
								}
								stdMap.put(fds[a], fns[b]);
								fds[a] = fns[b];
								continue Next;
							}
							else if(this.tableNode.getAlias() != null && !this.tableNode.getAlias().isEmpty())
							{
								if(fds[a].toLowerCase().startsWith(this.tableNode.getAlias().toLowerCase() + ".") && SimpleJoin.getRealFieldName(fds[a]).equalsIgnoreCase(fns[b]))
								{
									stdMap.put(fds[a], fns[b]);
									fds[a] = fns[b];
									continue Next;
								}
								else if(fns[b].toLowerCase().startsWith(this.tableNode.getAlias().toLowerCase() + ".") && SimpleJoin.getRealFieldName(fns[b]).equalsIgnoreCase(fds[a]))
								{
									stdMap.put(fds[a], fns[b]);
									fds[a] = fns[b];
									continue Next;
								}
							}
						}
						MessageManager mm = ParseMessage.get();
						throw new RQException("execute:" + fds[a] + mm.getMessage("field.notExist") + " in " + Arrays.asList(fns));
					}
					whereExp = ExpressionTranslator.translateExp(whereExp, n2cMap);
				}
			}

			//xingjl  remove 20220215
//			Set fdsSet = new HashSet(Arrays.asList(fds));
//			fds = new String[fdsSet.size()];
//			fdsSet.toArray(fds);

			this.tableNode.setAccessColumn(fds);
			
			boolean hasMasterFieldfromExists = false;
			if(whereExp != null && !this.subQueryOfExistsEntryList.isEmpty())
			{
				for(int m = 0; m < this.subQueryOfExistsEntryList.size(); m++)
				{
					String subQueryOfExistsIdent = this.subQueryOfExistsEntryList.get(m).getKey();
					if(whereExp.contains(subQueryOfExistsIdent))
					{
						hasMasterFieldfromExists = true;
						break;
					}
				}
			}
			
			boolean hasMasterFieldfromIn = false;
			if(whereExp != null && !this.subQueryOfInEntryList.isEmpty())
			{
				for(int m = 0; m < this.subQueryOfInEntryList.size(); m++)
				{
					String subQueryOfInIdent = this.subQueryOfInEntryList.get(m).getKey();
					if(whereExp.contains(subQueryOfInIdent))
					{
						hasMasterFieldfromIn = true;
						break;
					}
				}
			}
			
			boolean hasMasterFieldfromWhere = false;
			if(whereExp != null && !this.subQueryOfWhereEntryList.isEmpty())
			{
				for(int m = 0; m < this.subQueryOfWhereEntryList.size(); m++)
				{
					String subQueryOfWhereIdent = this.subQueryOfWhereEntryList.get(m).getKey();
					if(whereExp.contains(subQueryOfWhereIdent))
					{
						hasMasterFieldfromWhere = true;
						break;
					}
				}
			}
			
			Map trMap = new LinkedHashMap();
			for(int i = 0; i < fds.length; i++)
			{
				trMap.put(fds[i], fxs[i].toString());
				if(fds[i].startsWith("\"") && fds[i].endsWith("\"") && fds[i].substring(1, fds[i].length() - 1).indexOf("\"") == -1)
				{
					trMap.put(SimpleJoin.getRealFieldName(fds[i]), fxs[i].toString());
				}
				trMap.put("'"+fds[i]+"'", fxs[i].toString());
			}
			
			if(whereExp != null && !whereExp.equals("false") && this.tableNode.getType() == TableNode.TYPE_GTB 
			&& !hasMasterFieldfromExists && !hasMasterFieldfromIn && !hasMasterFieldfromWhere && this.topFilter == null)
			{
				whereExp = ExpressionTranslator.translateExp(whereExp, stdMap);
				whereExp = ExpressionTranslator.translateExp(whereExp, trMap);
				this.tableNode.setWhere(whereExp);
				whereExp = null;
			}
			
			if(whereExp != null && whereExp.equals("false"))
			{
				this.icur = null;
			}
			else
			{
				this.icur = this.tableNode.getCursor();
			}
			
			this.ds = new DataStruct(fds);
			
			ICursor cur = fillSubQueryField(this.ics, this.icur, this.subQueryOfExistsEntryList, this.parameterList, this.tableNode.getAlias(), SubQueryCursor.Exist_Type, this.ds);
			if(cur != null && cur instanceof SubQueryCursor && !cur.equals(this.icur))
			{
				this.ds = ((SubQueryCursor)cur).getTableDataStruct();
			}
			else if(cur != null)
			{
				this.ds = cur.getDataStruct();
			}
			this.icur = cur;
			
			cur = fillSubQueryField(this.ics, this.icur, this.subQueryOfInEntryList, this.parameterList, this.tableNode.getAlias(), SubQueryCursor.In_Type, this.ds);
			if(cur != null && cur instanceof SubQueryCursor && !cur.equals(this.icur))
			{
				this.ds = ((SubQueryCursor)cur).getTableDataStruct();
			}
			else if(cur != null)
			{
				this.ds = cur.getDataStruct();
			}
			this.icur = cur;
			
			cur = fillSubQueryField(this.ics, this.icur, this.subQueryOfWhereEntryList, this.parameterList, this.tableNode.getAlias(), SubQueryCursor.Where_Type, this.ds);
			if(cur != null && cur instanceof SubQueryCursor && !cur.equals(this.icur))
			{
				this.ds = ((SubQueryCursor)cur).getTableDataStruct();
			}
			else if(cur != null)
			{
				this.ds = cur.getDataStruct();
			}
			this.icur = cur;
			
			if(this.topFilter != null)
			{
				this.topFilter = ExpressionTranslator.translateExp(this.topFilter, stdMap);
				this.topFilter = ExpressionTranslator.translateExp(this.topFilter, trMap);
				Expression[] topExps = new Expression[]{new Expression(this.topFilter)};
				String[] topNames = new String[]{"_1"};
				if(this.icur != null)
				{	
					Table tab = this.icur.groups(null, null, topExps, topNames, null, ctx);
					if(tab == null || tab.length() != 1 || !(tab.get(1) instanceof BaseRecord)
					|| ((BaseRecord)tab.get(1)).getFieldCount() != 1 || !(((BaseRecord)tab.get(1)).getFieldValue(0) instanceof Sequence))
					{
						MessageManager mm = ParseMessage.get();
						throw new RQException(mm.getMessage("syntax.error") + ":execute, top?Ż?????쳣");
					}
					
					Table res = null;
					
					Sequence seq = (Sequence)((BaseRecord)tab.get(1)).getFieldValue(0);
					for(int i = 1; i <= seq.length(); i++)
					{
						Object obj = seq.get(i);
						if(!(obj instanceof BaseRecord))
						{
							MessageManager mm = ParseMessage.get();
							throw new RQException(mm.getMessage("syntax.error") + ":execute, top?Ż?????쳣");
						}
						
						BaseRecord rec = (BaseRecord)obj;
						if(res == null)
						{
							res = new Table(rec.dataStruct());
						}
						res.add(rec);
					}
					
					this.icur = new MemoryCursor(res);
				}
			}
			
			if(whereExp != null && !whereExp.equals("false"))
			{
				whereExp = ExpressionTranslator.translateExp(whereExp, stdMap);
				whereExp = ExpressionTranslator.translateExp(whereExp, trMap);
				Expression flt = new Expression(whereExp);
				if(this.icur != null)
				{
					this.icur.addOperation(new Select(flt, null), ctx);
				}
				whereExp = null;
			}
			
			boolean gatherSign = false;
			boolean fieldNotGroupSign = false;
			ArrayList nameList = new ArrayList();
			ArrayList functionList = new ArrayList();
			ArrayList gatherList = new ArrayList();
			ArrayList expressList = new ArrayList();
			ArrayList paramList = new ArrayList();
			ArrayList classifyList = new ArrayList();
			ArrayList numberList = new ArrayList();
			
			if(this.groupList != null && this.groupList.size() != 0)
			{
				for(int g = 0, len = this.groupList.size(); g n2cMap = new LinkedHashMap();
					for(int c = 0, len = classifyList.size(); c < len; c++)
					{
						String grpExp = classifyList.get(c);
						n2cMap.put(grpExp, String.format("#%d", c+1));
					}
					for(int g = 0, len = gatherList.size(); g < len; g++)
					{
						String funExp = gatherList.get(g);
						n2cMap.put(funExp, String.format("#%d", sizeGroup+g+1));
					}
					havExp = ExpressionTranslator.translateExp(havExp, n2cMap);
					
					Expression flt = new Expression(havExp);
					if(this.icur != null)
					{
						this.icur.addOperation(new Select(flt, null), ctx);
					}
				}
				
				int sizeExpress = expressList.size();
				Expression[] exps = new Expression[sizeExpress];
				String[] names = new String[sizeExpress];
				this.aliasList.toArray(names);
				for(int i = 0; i < sizeExpress; i++)
				{
					String exp = expressList.get(i);
					Map n2cMap = new LinkedHashMap();
					for(int j=0, length=classifyList.size(); j= 0 || this.limitNumber >= 0)
					{
						if(this.topNumber >= 0 && this.limitNumber >= 0)
						{
							MessageManager mm = ParseMessage.get();
							throw new RQException(mm.getMessage("syntax.error") + ":execute, Top?ؼ?????Limit?ؼ??ֲ???ͬʱʹ??");
						}
						else if(this.topNumber >= 0 && this.offsetNumber >= 0)
						{
							MessageManager mm = ParseMessage.get();
							throw new RQException(mm.getMessage("syntax.error") + ":execute, Top?ؼ?????Offset?ؼ??ֲ???ͬʱʹ??");
						}
						
						limit = this.topNumber >= 0 ? this.topNumber : this.limitNumber;
						offset = this.offsetNumber > 0 ? this.offsetNumber : 0;
						limit = limit + offset;
						if(limit <= ICursor.FETCHCOUNT)
						{
							this.topNumber = -1;
							this.limitNumber = -1;
							this.offsetNumber = -1;
						}
						else
						{
							limit = -1;
							offset = -1;
						}
					}
					
					Expression[] ordExps = new Expression[this.sortList.size()];
					for(int s = 0, size = ordExps.length; s < size; s++)
					{
						String ordExp = this.sortList.get(s).toExpression();
						if(this.sortList.get(s) instanceof NormalNode)
						{
							try
							{
								int colNo = Integer.parseInt(ordExp);
								if(colNo <= 0 || colNo > this.columnList.size())
								{
									MessageManager mm = ParseMessage.get();
									throw new RQException(mm.getMessage("syntax.error") + ":execute, ??????ȡ???кŲ???");
								}
								ordExp = "#" + colNo;
							}
							catch(NumberFormatException ex)
							{
								MessageManager mm = ParseMessage.get();
								throw new RQException(mm.getMessage("syntax.error") + ":execute, ??????????Ͳ???", ex);
							}
						}
						else
						{
							Map n2cMap = new LinkedHashMap();
							for(int e = 0, len = expressList.size(); e < len; e++)
							{
								n2cMap.put(expressList.get(e), "#" + (e + 1));
							}
							for(int a = 0, len = this.aliasList.size(); a < len; a++)
							{
								String aliExp = "'" + this.aliasList.get(a) + "'";
								n2cMap.put(aliExp, "#" + (a + 1));
							}
							ordExp = ExpressionTranslator.translateExp(ordExp, n2cMap);
						}
						ordExps[s] = new Expression(ordExp);
					}
					if(limit >= 0)
					{
						if(ordExps.length > 1)
						{
							StringBuffer sb = new StringBuffer();
							sb.append("[");
							for(int ox = 0; ox < ordExps.length; ox++)
							{
								if(ox > 0)
								{
									sb.append(",");
								}
								sb.append(ordExps[ox].toString());
							}
							sb.append("]");
							
							if(this.icur != null)
							{
								Sequence seq = (Sequence)CursorUtil.top(this.icur, limit, new Expression(sb.toString()), new Expression("~"), ctx);
								this.icur = new MemoryCursor(seq);
							}
						}
						else
						{
							if(this.icur != null)
							{
								Sequence seq = (Sequence)CursorUtil.top(this.icur, limit, ordExps[0], new Expression("~"), ctx);
								this.icur = new MemoryCursor(seq);
							}
						}
						if(offset > 0)
						{
							if(this.icur != null)
							{
								this.icur.skip(offset);
							}
						}
					}
					else
					{
						if(this.icur != null)
						{
							if(this.icur instanceof MemoryCursor || this.isMemory)
							{
								this.icur = new MemoryCursor(this.icur.fetch().sort(ordExps, null, null, this.ctx));
							}
							else
							{
								int capacityEx = EnvUtil.getCapacity(ordExps.length);
								this.icur = CursorUtil.sortx(this.icur, ordExps, this.ctx, capacityEx, null);
							}
						}
					}
				}
			}
			else
			{
				if(this.havingNode != null)
				{
					this.havingNode.setFromHaving();
					String havingExp = this.havingNode.toExpression();
					havingExp = ExpressionTranslator.translateExp(havingExp, stdMap);
					havingExp = ExpressionTranslator.translateExp(havingExp, trMap);
					
					Expression flt = new Expression(havingExp);
					if(this.icur != null)
					{
						this.icur.addOperation(new Select(flt, null), ctx);
					}
				}
				
				cur = fillSubQueryField(this.ics, this.icur, this.subQueryOfSelectEntryList, this.parameterList, this.tableNode.getAlias(), SubQueryCursor.Select_Type, this.ds);
				if(cur != null && cur instanceof SubQueryCursor && !cur.equals(this.icur))
				{
					this.ds = ((SubQueryCursor)cur).getTableDataStruct();
				}
				else if(cur != null)
				{
					this.ds = cur.getDataStruct();
				}
				this.icur = cur;
				
				if(this.ds != null)
				{
					for(int i = trMap.size(); i < this.ds.getFieldCount(); i++)
					{
						trMap.put("'" + this.ds.getFieldName(i) + "'", this.ds.getFieldName(i));
					}
				}
				
				if(this.hasDistinct)
				{
					int sizeExpress = expressList.size();
					Expression[] exps = new Expression[sizeExpress];
					String[] names = new String[sizeExpress];
					this.aliasList.toArray(names);
					for(int i = 0; i < sizeExpress; i++)
					{
						String exp = expressList.get(i);
						exp = ExpressionTranslator.translateExp(exp, stdMap);
						exp = ExpressionTranslator.translateExp(exp, trMap);
						exps[i] = new Expression(exp);
					}
					if(this.icur != null)
					{
						this.icur.addOperation(new New(exps, names, null), ctx);
					}
					
					Expression[] grps = new Expression[sizeExpress];
					for(int k = 0; k < sizeExpress; k++)
					{
						grps[k] = new Expression(String.format("#%d", k + 1));
					}
					if(this.icur != null)
					{
						Table tab = this.icur.groups(grps, names, null, null, null, ctx);
						this.icur = new MemoryCursor(tab);
						/*
						if(this.icur instanceof MemoryCursor || this.isMemory)
						{
							Table tab = CursorUtil.groups(this.icur, grps, names, cnts, nms, null, ctx);
							this.icur = new MemoryCursor(tab);
						}
						else
						{
							int capacity = EnvUtil.getCapacity(grps.length + cnts.length);
							this.icur = CursorUtil.hashGroupx(this.icur, grps, names, cnts, nms, null, ctx, capacity);
						}
						*/
					}
					
					if(this.sortList != null && this.sortList.size() != 0)
					{
						int limit = -1, offset = -1;
						if(this.topNumber >= 0 || this.limitNumber >= 0)
						{
							if(this.topNumber >= 0 && this.limitNumber >= 0)
							{
								MessageManager mm = ParseMessage.get();
								throw new RQException(mm.getMessage("syntax.error") + ":execute, Top?ؼ?????Limit?ؼ??ֲ???ͬʱʹ??");
							}
							else if(this.topNumber >= 0 && this.offsetNumber >= 0)
							{
								MessageManager mm = ParseMessage.get();
								throw new RQException(mm.getMessage("syntax.error") + ":execute, Top?ؼ?????Offset?ؼ??ֲ???ͬʱʹ??");
							}
							limit = this.topNumber >= 0 ? this.topNumber : this.limitNumber;
							offset = this.offsetNumber > 0 ? this.offsetNumber : 0;
							limit = limit + offset;
							if(limit <= ICursor.FETCHCOUNT)
							{
								this.topNumber = -1;
								this.limitNumber = -1;
								this.offsetNumber = -1;
							}
							else
							{
								limit = -1;
								offset = -1;
							}
						}
						Expression[] ordExps = new Expression[this.sortList.size()];
						for(int s = 0, size = ordExps.length; s < size; s++)
						{
							String ordExp = this.sortList.get(s).toExpression();
							if(this.sortList.get(s) instanceof NormalNode)
							{
								try
								{
									int colNo = Integer.parseInt(ordExp);
									if(colNo <= 0 || colNo > this.columnList.size())
									{
										MessageManager mm = ParseMessage.get();
										throw new RQException(mm.getMessage("syntax.error") + ":execute, ??????ȡ???кŲ???");
									}
									ordExp = "#" + colNo;
								}
								catch(NumberFormatException ex)
								{
									MessageManager mm = ParseMessage.get();
									throw new RQException(mm.getMessage("syntax.error") + ":execute, ??????????Ͳ???", ex);
								}
							}
							else
							{
								Map n2cMap = new LinkedHashMap();
								for(int e = 0, len = expressList.size(); e < len; e++)
								{
									String exp = expressList.get(e);
									exp = ExpressionTranslator.translateExp(exp, stdMap);
									n2cMap.put(exp, "#" + (e + 1));
								}
								for(int a = 0, len = this.aliasList.size(); a < len; a++)
								{
									String aliExp = "'"+this.aliasList.get(a)+"'";
									n2cMap.put(aliExp, "#" + (a + 1));
								}
								ordExp = ExpressionTranslator.translateExp(ordExp, stdMap);
								ordExp = ExpressionTranslator.translateExp(ordExp, n2cMap);
							}
							ordExps[s] = new Expression(ordExp);
						}
						if(limit >= 0)
						{
							if(ordExps.length > 1)
							{
								StringBuffer sb = new StringBuffer();
								sb.append("[");
								for(int ox = 0; ox < ordExps.length; ox++)
								{
									if(ox > 0)
									{
										sb.append(",");
									}
									sb.append(ordExps[ox].toString());
								}
								sb.append("]");
								if(this.icur != null)
								{
									Sequence seq = (Sequence)CursorUtil.top(this.icur, limit, new Expression(sb.toString()), new Expression("~"), ctx);
									this.icur = new MemoryCursor(seq);
								}
							}
							else
							{
								if(this.icur != null)
								{
									Sequence seq = (Sequence)CursorUtil.top(this.icur, limit, ordExps[0], new Expression("~"), ctx);
									this.icur = new MemoryCursor(seq);
								}
							}
							if(offset > 0)
							{
								if(this.icur != null)
								{
									this.icur.skip(offset);
								}
							}
						}
						else
						{
							if(this.icur != null)
							{
								if(this.icur instanceof MemoryCursor || this.isMemory)
								{
									this.icur = new MemoryCursor(this.icur.fetch().sort(ordExps, null, null, this.ctx));
								}
								else
								{
									int capacityEx = EnvUtil.getCapacity(ordExps.length);
									this.icur = CursorUtil.sortx(this.icur, ordExps, this.ctx, capacityEx, null);
								}
							}
						}
					}
				}
				else
				{
					if(this.sortList != null && this.sortList.size() != 0)
					{
						int limit = -1, offset = -1;
						if(this.topNumber >= 0 || this.limitNumber >= 0)
						{
							if(this.topNumber >= 0 && this.limitNumber >= 0)
							{
								MessageManager mm = ParseMessage.get();
								throw new RQException(mm.getMessage("syntax.error") + ":execute, Top?ؼ?????Limit?ؼ??ֲ???ͬʱʹ??");
							}
							else if(this.topNumber >= 0 && this.offsetNumber >= 0)
							{
								MessageManager mm = ParseMessage.get();
								throw new RQException(mm.getMessage("syntax.error") + ":execute, Top?ؼ?????Offset?ؼ??ֲ???ͬʱʹ??");
							}
							limit = this.topNumber >= 0 ? this.topNumber : this.limitNumber;
							offset = this.offsetNumber > 0 ? this.offsetNumber : 0;
							limit = limit + offset;
							if(limit <= ICursor.FETCHCOUNT)
							{
								this.topNumber = -1;
								this.limitNumber = -1;
								this.offsetNumber = -1;
							}
							else
							{
								limit = -1;
								offset = -1;
							}
						}
						
						Expression[] ordExps = new Expression[this.sortList.size()];
						for(int s = 0, size = ordExps.length; s < size; s++)
						{
							String ordExp = this.sortList.get(s).toExpression();
							if(this.sortList.get(s) instanceof NormalNode)
							{
								try
								{
									int colNo = Integer.parseInt(ordExp);
									if(colNo <= 0 || colNo > this.columnList.size())
									{
										MessageManager mm = ParseMessage.get();
										throw new RQException(mm.getMessage("syntax.error") + ":execute, ??????ȡ???кŲ???");
									}
									ordExp = "#" + colNo;
								}
								catch(NumberFormatException ex)
								{
									MessageManager mm = ParseMessage.get();
									throw new RQException(mm.getMessage("syntax.error") + ":execute, ??????????Ͳ???", ex);
								}
							}
							else
							{
								Map n2cMap = new LinkedHashMap();
								for(int a = 0, len = this.aliasList.size(); a < len; a++)
								{
									String aliExp = "'" + this.aliasList.get(a) + "'";
									String exp = expressList.get(a);
									exp = ExpressionTranslator.translateExp(exp, stdMap);
									String colExp = "(" + exp + ")";
									n2cMap.put(aliExp, colExp);
								}
								ordExp = ExpressionTranslator.translateExp(ordExp, stdMap);
								ordExp = ExpressionTranslator.translateExp(ordExp, n2cMap);
								ordExp = ExpressionTranslator.translateExp(ordExp, trMap);
							}
							ordExps[s] = new Expression(ordExp);
						}
						
						if(limit >= 0)
						{
							if(ordExps.length > 1)
							{
								StringBuffer sb = new StringBuffer();
								sb.append("[");
								for(int ox = 0; ox < ordExps.length; ox++)
								{
									if(ox > 0)
									{
										sb.append(",");
									}
									sb.append(ordExps[ox].toString());
								}
								sb.append("]");
								
								if(this.icur != null)
								{
									Sequence seq = (Sequence)CursorUtil.top(this.icur, limit, new Expression(sb.toString()), new Expression("~"), ctx);
									this.icur = new MemoryCursor(seq);
								}
							}
							else
							{
								if(this.icur != null)
								{
									Sequence seq = (Sequence)CursorUtil.top(this.icur, limit, ordExps[0], new Expression("~"), ctx);
									this.icur = new MemoryCursor(seq);
								}
							}
							if(offset > 0)
							{
								if(this.icur != null)
								{
									this.icur.skip(offset);
								}
							}
						}
						else
						{
							if(this.icur != null)
							{
								if(this.icur instanceof MemoryCursor || this.isMemory)
								{
									this.icur = new MemoryCursor(this.icur.fetch().sort(ordExps, null, null, this.ctx));
								}
								else
								{
									int capacityEx = EnvUtil.getCapacity(ordExps.length);
									this.icur = CursorUtil.sortx(this.icur, ordExps, this.ctx, capacityEx, null);
								}
							}
						}
					}

					int sizeExpress = expressList.size();
					Expression[] exps = new Expression[sizeExpress];
					String[] names = new String[sizeExpress];
					this.aliasList.toArray(names);
					for(int i = 0; i < sizeExpress; i++)
					{
						String exp = expressList.get(i);
						exp = ExpressionTranslator.translateExp(exp, stdMap);
						exp = ExpressionTranslator.translateExp(exp, trMap);
						exps[i] = new Expression(exp);
					}
					if(this.icur != null)
					{
						this.icur.addOperation(new New(exps, names, null), ctx);
					}
				}
			}
			
			if(this.topNumber >= 0 && this.limitNumber >= 0)
			{
				MessageManager mm = ParseMessage.get();
				throw new RQException(mm.getMessage("syntax.error") + ":execute, Top?ؼ?????Limit?ؼ??ֲ???ͬʱʹ??");
			}
			else if(this.topNumber >= 0 && this.offsetNumber >= 0)
			{
				MessageManager mm = ParseMessage.get();
				throw new RQException(mm.getMessage("syntax.error") + ":execute, Top?ؼ?????Offset?ؼ??ֲ???ͬʱʹ??");
			}
			else if(this.topNumber >= 0)
			{	
				if(this.icur != null)
				{
					this.icur = new SubCursor(this.icur, this.topNumber);
				}
			}
			else if(this.limitNumber >= 0)
			{
				if(this.offsetNumber > 0)
				{
					if(this.icur != null)
					{
						this.icur.skip(this.offsetNumber);
					}
				}
				if(this.icur != null)
				{
					this.icur = new SubCursor(this.icur, this.limitNumber);
				}
			}
			else if(this.offsetNumber > 0)
			{
				if(this.icur != null)
				{
					this.icur.skip(this.offsetNumber);
				}
			}
			
			Expression[] colExps = new Expression[this.finalList.size()];
			for(int i=0, len=colExps.length; i paramList = new ArrayList();
		while(true)
		{
			StringBuffer sb = new StringBuffer();
			int comma = Tokenizer.scanComma(tokens, start, next);
			if(comma < 0)
			{
				for(int i = start; i < next; i++)
				{
					sb.append(tokens[i].getOriginString());
					sb.append(tokens[i].getSpaces());
				}
				if(sb.length() > 0)
				{
					paramList.add(sb.toString().trim());
				}
				break;
			}
			else
			{
				for(int i = start; i < comma; i++)
				{
					sb.append(tokens[i].getOriginString());
					sb.append(tokens[i].getSpaces());
				}
				if(sb.length() > 0)
				{
					paramList.add(sb.toString());
				}
				else
				{
					throw new RQException("????????????Ϊ??");
				}
				start = comma + 1;
				if(start >= next)
				{
					MessageManager mm = ParseMessage.get();
					throw new RQException(mm.getMessage("function.paramError") + ":getParams, ??????ʽ????");
				}
			}
		}
		String[] params = new String[paramList.size()];
		paramList.toArray(params);
		return params;
	}
	
	private Token[] optimizeWhere(Token[] whereTokens, List paramList)
	{
		PerfectWhere pw = new PerfectWhere(whereTokens, paramList);
		String topFilter = pw.getTopFromTokens(null, null, this.tableNode.getName(), this.tableNode.getAlias());
		if(this.topFilter == null)
		{
			this.topFilter = topFilter;
		}
		else if(topFilter != null)
		{
			MessageManager mm = ParseMessage.get();
			throw new RQException(mm.getMessage("syntax.error") + ":optimizeWhere, WHERE?Ӿ䱻?ظ?????");
		}
		return pw.getTokens(true);
	}
	
	private String getSQLValue(Object value)
	{
		if(value == null)
		{
			return "null";
		}
		else if(value instanceof String)
		{
			return "'" + value + "'";
		}
		else if(value instanceof Boolean)
		{
			return value.toString();
		}
		else if(value instanceof Number)
		{
			return value.toString();
		}
		else if(value instanceof java.sql.Date)
		{
			return String.format("date(\"%s\",\"yyyy-MM-dd\")", new SimpleDateFormat("yyyy-MM-dd").format((java.sql.Date)value));
		}
		else if(value instanceof java.sql.Time)
		{
			return String.format("time(\"%s\",\"HH:mm:ss.SSS\")", new SimpleDateFormat("HH:mm:ss.SSS").format((java.sql.Time)value));
		}
		else if(value instanceof java.sql.Timestamp)
		{
			return String.format("timestamp(\"%s\",\"yyyy-MM-dd HH:mm:ss.SSS\")", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format((java.sql.Timestamp)value));
		}
		else if(value instanceof Date)
		{
			return String.format("timestamp(\"%s\",\"yyyy-MM-dd HH:mm:ss.SSS\")", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format((Date)value));
		}
		else
		{
			MessageManager mm = ParseMessage.get();
			throw new RQException(mm.getMessage("function.paramError") + ":getSQLValue, ??֧?ֵ?????????");
		}
	}
	
	public String getProcValue(Object param)
	{
		if(param == null)
		{
			return "null";
		}
		else if(param instanceof String)
		{
			return String.format("\"%s\"", param.toString());
		}
		else if(param instanceof Boolean)
		{
			return param.toString();
		}
		else if(param instanceof Number)
		{
			return param.toString();
		}
		else if(param instanceof java.sql.Date)
		{
			return String.format("date(\"%s\",\"yyyy-MM-dd\")", new SimpleDateFormat("yyyy-MM-dd").format((java.sql.Date)param));
		}
		else if(param instanceof java.sql.Time)
		{
			return String.format("time(\"%s\",\"HH:mm:ss.SSS\")", new SimpleDateFormat("HH:mm:ss.SSS").format((java.sql.Time)param));
		}
		else if(param instanceof java.sql.Timestamp)
		{
			return String.format("datetime(\"%s\",\"yyyy-MM-dd HH:mm:ss.SSS\")", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format((java.sql.Timestamp)param));
		}
		else if(param instanceof Date)
		{
			return String.format("datetime(\"%s\",\"yyyy-MM-dd HH:mm:ss.SSS\")", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format((Date)param));
		}
		else
		{
			MessageManager mm = ParseMessage.get();
			throw new RQException(mm.getMessage("function.paramError") + ":getProcValue, ??֧?ֵ?????????");
		}
	}
	
	private ICursor fillSubQueryField(ICellSet ics, ICursor icur, List> subQueryEntryList, List paramList, String tableName, int type, DataStruct ds)
	{
		if(icur == null)
		{
			return null;
		}
		
		if(ds == null)
		{
			MessageManager mm = ParseMessage.get();
			throw new RQException(mm.getMessage("syntax.error") + ":fillSubQueryField, ??ѯ???????ȱ?????ݽṹ");
		}
		
		if(subQueryEntryList.isEmpty())
		{
			icur.setDataStruct(ds);
			return icur;
		}
		
		String[] fieldNames = ds.getFieldNames();
		List>> subQueryListListList = new ArrayList>>();
		List> fieldNameListList = new ArrayList>();
		List colNameList = new ArrayList();
		
		for(Map.Entry subQueryEntry : subQueryEntryList)
		{
			Token[] subQueryTokens = subQueryEntry.getValue();
			boolean canUseJoin = false;
			if(type != SubQueryCursor.In_Type)
			{
				int fromPos = Tokenizer.scanKeyWord("FROM", subQueryTokens, 0, subQueryTokens.length);
				if(fromPos <= 0)
				{
					MessageManager mm = ParseMessage.get();
					throw new RQException(mm.getMessage("syntax.error") + ":fillSubQueryField, FROM?ؼ???ȱʧ");
				}
				int wherePos = Tokenizer.scanKeyWord("WHERE", subQueryTokens, 0, subQueryTokens.length);
				if(wherePos >= 0 && wherePos < fromPos)
				{
					MessageManager mm = ParseMessage.get();
					throw new RQException(mm.getMessage("syntax.error") + ":fillSubQueryField, WHERE?ؼ??ֵ?λ?ò???ȷ");
				}
				if(wherePos < 0)
				{
					break;
				}
				int minPos = wherePos;
				int groupPos = Tokenizer.scanKeyWord("GROUP", subQueryTokens, 0, subQueryTokens.length);
				if(groupPos >= 0 && groupPos < wherePos)
				{
					MessageManager mm = ParseMessage.get();
					throw new RQException(mm.getMessage("syntax.error") + ":fillSubQueryField, GROUP?ؼ??ֵ?λ?ò???ȷ");
				}
				minPos = pos(groupPos, minPos);
				int havingPos = Tokenizer.scanKeyWord("HAVING", subQueryTokens, 0, subQueryTokens.length);
				if(havingPos >= 0 && havingPos < groupPos)
				{
					MessageManager mm = ParseMessage.get();
					throw new RQException(mm.getMessage("syntax.error") + ":fillSubQueryField, HAVING?ؼ??ֵ?λ?ò???ȷ");
				}
				minPos = pos(havingPos, minPos);
				int orderPos = Tokenizer.scanKeyWord("ORDER", subQueryTokens, 0, subQueryTokens.length);
				if(orderPos >= 0 && orderPos < minPos)
				{
					MessageManager mm = ParseMessage.get();
					throw new RQException(mm.getMessage("syntax.error") + ":fillSubQueryField, ORDER?ؼ??ֵ?λ?ò???ȷ");
				}
				minPos = pos(orderPos , minPos);
				int limitPos = Tokenizer.scanKeyWord("LIMIT", subQueryTokens, 0, subQueryTokens.length);
				if(limitPos >= 0 && limitPos < minPos)
				{
					MessageManager mm = ParseMessage.get();
					throw new RQException(mm.getMessage("syntax.error") + ":fillSubQueryField, LIMIT?ؼ??ֵ?λ?ò???ȷ");
				}
				minPos = pos(limitPos , minPos);
				int offsetPos = Tokenizer.scanKeyWord("OFFSET", subQueryTokens, 0, subQueryTokens.length);
				if(offsetPos >= 0 && offsetPos < minPos)
				{
					MessageManager mm = ParseMessage.get();
					throw new RQException(mm.getMessage("syntax.error") + ":fillSubQueryField, OFFSET?ؼ??ֵ?λ?ò???ȷ");
				}
				int byStart = pos(groupPos, wherePos, fromPos);
				int byEnd = pos(havingPos, orderPos, limitPos, offsetPos, subQueryTokens.length);
				int byPos = Tokenizer.scanKeyWord("BY", subQueryTokens, byStart, byEnd);
				if(byPos < 0 && groupPos > 0)
				{
					MessageManager mm = ParseMessage.get();
					throw new RQException(mm.getMessage("syntax.error") + ":fillSubQueryField, ?ؼ???GROUP????ȱ?ٹؼ???BY");
				}
				else if(havingPos > 0 && byPos > havingPos)
				{
					MessageManager mm = ParseMessage.get();
					throw new RQException(mm.getMessage("syntax.error") + ":fillSubQueryField, ????ؼ???BYλ??Ӧ????HAVING֮ǰ");
				}
				
				int whereEnd = pos(groupPos, byPos, havingPos, orderPos, limitPos, offsetPos, subQueryTokens.length);
				int intoPos = Tokenizer.scanKeyWord("INTO", subQueryTokens, 0, subQueryTokens.length);
				if(intoPos >= fromPos)
				{
					MessageManager mm = ParseMessage.get();
					throw new RQException(mm.getMessage("syntax.error") + ":fillSubQueryField, INTO?ؼ??ֵ?λ?ò???ȷ");
				}
				int columnEnd = pos(intoPos, fromPos);
				int selectPos = Tokenizer.scanKeyWord("SELECT", subQueryTokens, 0, subQueryTokens.length);
				if(selectPos < 0)
				{
					MessageManager mm = ParseMessage.get();
					throw new RQException(mm.getMessage("syntax.error") + ":fillSubQueryField, SELECT?ؼ???ȱʧ");
				}
				int columnStart = selectPos;
				int distinctPos = Tokenizer.scanKeyWord("DISTINCT", subQueryTokens, 0, subQueryTokens.length);
				if(distinctPos >= 0 && distinctPos < selectPos)
				{
					MessageManager mm = ParseMessage.get();
					throw new RQException(mm.getMessage("syntax.error") + ":fillSubQueryField, DISTINCT?ؼ??ֵ?λ?ò???ȷ");
				}
				columnStart = pos(distinctPos, columnStart);
				int topPos = Tokenizer.scanKeyWord("TOP", subQueryTokens, 0, subQueryTokens.length);
				if(topPos >= 0 && topPos < columnStart)
				{
					MessageManager mm = ParseMessage.get();
					throw new RQException(mm.getMessage("syntax.error") + ":fillSubQueryField, TOP?ؼ??ֵ?λ?ò???ȷ");
				}
				columnStart = pos(topPos, columnStart);
				if(columnStart == topPos)
				{
					columnStart += 2;
				}
				else
				{
					columnStart++;
				}
				Token[] whereTokens = Arrays.copyOfRange(subQueryTokens, wherePos + 1, whereEnd);
				PerfectWhere pw = new PerfectWhere(whereTokens, this.parameterList);
				Set outerFieldSet = new LinkedHashSet();
				Set innerFieldSet = new LinkedHashSet();
				Set tableNames = new HashSet();
				tableNames.add(tableName);
				Token[] newOnTokens = pw.getOnFromTokens(tableNames, outerFieldSet, innerFieldSet);
				if(newOnTokens != null && newOnTokens.length != 0)
				{
					canUseJoin = true;
				}
				if(canUseJoin)
				{
					whereTokens = pw.getTokens(true);
					
					Token[] columnTokens = Arrays.copyOfRange(subQueryTokens, columnStart, columnEnd);
					if(type == SubQueryCursor.Select_Type)
					{
						if(Tokenizer.scanComma(columnTokens, 0, columnTokens.length) != -1)
						{
							MessageManager mm = ParseMessage.get();
							throw new RQException(mm.getMessage("syntax.error") + ":fillSubQueryField, ?Ӳ?ѯ??SELECT?ֶα??뵥??");
						}
						if(columnTokens[columnTokens.length - 1].getSpaces().isEmpty())
						{
							columnTokens[columnTokens.length - 1].addSpace();
						}
					}
					else if(type == SubQueryCursor.Exist_Type)
					{
						Token columnToken = new Token(Tokenizer.NUMBER, "1", -1, "1");
						columnToken.addSpace();
						columnTokens = new Token[]{columnToken};
					}
					
					String aliasName = subQueryEntry.getKey();
					Token aliasToken = new Token(Tokenizer.IDENT, aliasName, -1, aliasName);
					aliasToken.addSpace();
					
					String columnStr = "";
					for(Token columnToken : columnTokens)
					{
						columnStr += columnToken.getOriginString();
						columnStr += columnToken.getSpaces();
					}
					columnStr = columnStr.trim().toLowerCase();
					
					List innerFieldList = new ArrayList();
					int index = 2;
					Map fn2cnMap = new LinkedHashMap();
					for(String innerField : innerFieldSet)
					{
						if(!innerField.equals(columnStr))
						{
							innerFieldList.add(innerField);
							fn2cnMap.put(innerField, "#"+index);
							index++;
						}
						else
						{
							fn2cnMap.put(innerField, "#1");
						}
					}
					
					List newTokenList = new ArrayList();
					newTokenList.addAll(Arrays.asList(Arrays.copyOfRange(subQueryTokens, 0, columnStart)));
					newTokenList.addAll(Arrays.asList(columnTokens));
					newTokenList.add(aliasToken);
					
					index = 2;
					for(String innerField : innerFieldList)
					{
						Token commaToken = new Token(Tokenizer.COMMA, ",", -1, ",");
						commaToken.addSpace();
						newTokenList.add(commaToken);
						newTokenList.addAll(Arrays.asList(Tokenizer.parse(innerField + " " + "_" + index + " ")));
						index++;
					}
					
					newTokenList.addAll(Arrays.asList(Arrays.copyOfRange(subQueryTokens, columnEnd, wherePos + 1)));
					newTokenList.addAll(Arrays.asList(whereTokens));
					newTokenList.addAll(Arrays.asList(Arrays.copyOfRange(subQueryTokens, whereEnd, subQueryTokens.length)));
					Token[] newTokens = new Token[newTokenList.size()];
					newTokenList.toArray(newTokens);
					
					SimpleSQL lq = new SimpleSQL(this.ics, newTokens, 0, newTokens.length, this.parameterList, this.ctx, true);
					lq.setMemory(true);
					Object obj = lq.execute();
					Sequence subSeq = obj instanceof ICursor ? ((ICursor)obj).fetch() : (obj instanceof Sequence ? (Sequence)obj : null);
					
					String onFilter = "";
					for(Token newOnToken : newOnTokens)
					{
						onFilter += newOnToken.getOriginString();
						onFilter += newOnToken.getSpaces();
					}
					
					List outerExpsList = new ArrayList();
					List innerExpsList = new ArrayList();
					
					for(int m = 0, sz = outerFieldSet.size(); m < sz; m++)
					{
						String outerField = outerFieldSet.iterator().next();
						for(int k = 0, len = fieldNames.length; k < len; k++)
						{
							String fieldName = fieldNames[k];
							String bakOuterField = outerField;
							outerField = SimpleJoin.getRealFieldName(outerField);
							if(fieldName.equalsIgnoreCase(outerField))
							{
								fn2cnMap.put(bakOuterField, "#" + (k + 1));
							}
						}
					}
					
					String[] subFilters = onFilter.split("AND");
					for(String subFilter : subFilters)
					{
						String[] fltExps = subFilter.split("=");
						if(fltExps.length != 2)
						{
							MessageManager mm = ParseMessage.get();
							throw new RQException(mm.getMessage("syntax.error")+":fillSubQueryField, ??ֵ????????ʽ?﷨????");
						}
						
						if(outerFieldSet.contains(fltExps[0].trim().toLowerCase())) //?ⲿ?ֶ?
						{
							String numberCode = ExpressionTranslator.translateExp(fltExps[0].trim().toLowerCase(), fn2cnMap);
							outerExpsList.add(new Expression(numberCode));
						}
						else if(innerFieldSet.contains(fltExps[0].trim().toLowerCase())) //?ڲ??ֶ?
						{
							String numberCode = ExpressionTranslator.translateExp(fltExps[0].trim().toLowerCase(), fn2cnMap);
							innerExpsList.add(new Expression(numberCode));
						}
						else
						{
							MessageManager mm = ParseMessage.get();
							throw new RQException(mm.getMessage("syntax.error")+":fillSubQueryField, δ֪???ֶ?");
						}
						
						if(outerFieldSet.contains(fltExps[1].trim().toLowerCase())) //?ⲿ?ֶ?
						{
							String numberCode = ExpressionTranslator.translateExp(fltExps[1].trim().toLowerCase(), fn2cnMap);
							outerExpsList.add(new Expression(numberCode));
						}
						else if(innerFieldSet.contains(fltExps[1].trim().toLowerCase())) //?ڲ??ֶ?
						{
							String numberCode = ExpressionTranslator.translateExp(fltExps[1].trim().toLowerCase(), fn2cnMap);
							innerExpsList.add(new Expression(numberCode));
						}
						else
						{
							MessageManager mm = ParseMessage.get();
							throw new RQException(mm.getMessage("syntax.error")+":fillSubQueryField, δ֪???ֶ?");
						}
					}
					
					Expression[] outerExps = new Expression[outerExpsList.size()];
					outerExpsList.toArray(outerExps);
					Expression[] innerExps = new Expression[innerExpsList.size()];
					innerExpsList.toArray(innerExps);

					String opt = "";
					
					if(icur instanceof MemoryCursor)
					{
						Sequence res = new Join(null, new Expression[][]{outerExps}, new Sequence[]{subSeq}, new Expression[][]{innerExps}, new Expression[][]{new Expression[]{new Expression("#1")}}, new String[][]{new String[]{aliasName}}, opt).process(icur.fetch(), this.ctx);
						icur = new MemoryCursor(res);
					}
					else
					{
						icur.addOperation(new Join(null, new Expression[][]{outerExps}, new Sequence[]{subSeq}, new Expression[][]{innerExps}, new Expression[][]{new Expression[]{new Expression("#1")}}, new String[][]{new String[]{aliasName}}, opt), this.ctx);
					}
					
					String[] newFieldNames = new String[ds.getFieldCount() + 1];
					System.arraycopy(ds.getFieldNames(), 0, newFieldNames, 0, ds.getFieldCount());
					newFieldNames[ds.getFieldCount()] = aliasName;
					icur.setDataStruct(new DataStruct(newFieldNames));
				}
			}
			
			if(!canUseJoin)
			{
				List> subQueryListList = new ArrayList>();
				List fieldNameList = new ArrayList();
				List subQueryList = new ArrayList();
				for(int n = 0, len = subQueryTokens.length; n < len; n++)
				{
					String theFieldName = null;
					if(n < len - 2 
					&& subQueryTokens[n].getString().equalsIgnoreCase(tableName)
					&& subQueryTokens[n + 1].getType() == Tokenizer.DOT)
					{
						for(String fieldName : fieldNames)
						{
							if(subQueryTokens[n + 2].getString().equalsIgnoreCase(fieldName))
							{
								theFieldName = fieldName;
								break;
							}
						}
					}
					
					if(theFieldName != null)
					{
						subQueryListList.add(subQueryList);
						subQueryList  = new ArrayList();
						fieldNameList.add(theFieldName);
						n += 2;
					}
					else
					{
						subQueryList.add(subQueryTokens[n]);
					}
				}
				
				if(!subQueryList.isEmpty())
				{
					subQueryListList.add(subQueryList);
				}
				
				subQueryListListList.add(subQueryListList);
				fieldNameListList.add(fieldNameList);
				
				String aliasName = subQueryEntry.getKey();
				colNameList.add(aliasName);
			}
		}
		
		if(!colNameList.isEmpty())
		{
			icur = new SubQueryCursor(icur, type, ics, paramList, colNameList, subQueryListListList, fieldNameListList, this.ctx, ds);
		}
		
		return icur;
	}
	
	void setMemory(boolean isMemory)
	{
		this.isMemory = isMemory;
	}
	
	void setParallel(int parallelNumber)
	{
		this.parallelNumber = parallelNumber;
	}
	
	void setTopFilter(String topFilter)
	{
		this.topFilter = topFilter;
	}
}