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

prerna.query.parsers.GenExpressionWrapper Maven / Gradle / Ivy

The newest version!
package prerna.query.parsers;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Stack;
import java.util.Vector;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import net.sf.jsqlparser.parser.CCJSqlParserUtil;
import net.sf.jsqlparser.statement.Statement;
import prerna.query.parsers.ParamStructDetails.LEVEL;
import prerna.query.parsers.ParamStructDetails.QUOTE;
import prerna.query.querystruct.FunctionExpression;
import prerna.query.querystruct.GenExpression;
import prerna.query.querystruct.OperationExpression;
import prerna.query.querystruct.SelectQueryStruct;
import prerna.sablecc2.om.PixelDataType;
import prerna.util.Constants;

public class GenExpressionWrapper {
	
	private static final Logger classLogger = LogManager.getLogger(GenExpressionWrapper.class);

	// keep table alias
	// this is {alias => table name}
	public Map tableAlias = null;
	// keep column alias
	public  Map columnAlias = null;
	// used to keep track of every table and column set used
	public  Map> schema = null;

	// keeps track of column to select
	public  Map > columnSelect = new Hashtable<>();
	// keep track of table to select
	public  Map > tableSelect = new Hashtable<>();	
	// keep a list of selects as well
	// to the columns
	public  Map > selectColumns = new Hashtable<>();
	
	// groupby hash
	public Map  groupByHash = new HashMap<>();
	public Map  joinHash = new HashMap<>();

	
	public GenExpression root = null;
	
	// this is the highest level - acctid - when I replace this it will replace this across all of the databases and operators
	// key is column, value is column tables i.e. key to the next level
	public Map> columnTableIndex = new HashMap<>(); 
	// this is the next highest level - clms.acctid, mbrshp.acctid - this will replace it only for the specified operators not all of it
	// key is column table and value is column table operator i.e. key to the next level
	public Map> columnTableOperatorIndex = new HashMap<>(); 
	// this is the next level - clms.acctid=, clms.acctid < - this now also includes the unique count
	// key is column table operator and valus is the actual parameter i.e. gen expression
	public Map  operatorTableColumnParamIndex = new HashMap<>(); 
	
	 // final level
	public Map > paramToExpressionMap = new HashMap<>();

	public Map  paramStringToParamMap = new HashMap<>();

	
	// keeping track of the current operator
	public Stack  currentOperator = new Stack();
	public Stack  contextExpression = new Stack();
	public Map  procOrder = new HashMap();
	int andCount = 0;
	int orCount = 0;
	int uniqueCounter = 0;
	
	// how many subselects are there
	public int numSubSelects = -1;
	
	// keeps function to expression list
	public Map> functionExpressionMapper = new HashMap>();
	
	public GenExpressionWrapper()
	{
		tableAlias = new Hashtable ();
		columnAlias = new Hashtable ();
		schema = new Hashtable>();

	}
	
	public String printOutput() throws Exception
	{
		String finalQuery = root.printQS(root, new StringBuffer()).toString(); 
		return finalQuery;
	}
	
	public void addGroupBy(String columnName, GenExpression expr)
	{
		groupByHash.put(columnName, expr);
	}
	
	public void addJoin(String columnName, GenExpression expr)
	{
		joinHash.put(columnName, expr);
	}
	
	//////////////////////////////// METHOD FOR MANIPULATING PARAMETERS ////////////////////////////////////////////
	
	
	// the key is the table name and the value is the GenExpression that should be used
	public void addRowFilter(Map  filterValues)
	{
		// I still need to account for if the user already comes with this
		
		Iterator  cols = filterValues.keySet().iterator();
		while(cols.hasNext())
		{
			// get the col
			String thisCol = cols.next();
			GenExpression userFilter = filterValues.get(thisCol);
			
			// see if a select with that table exists
			if(tableSelect.containsKey(thisCol))
			{
				// get the expression and see what is the where clause
				List  selects = tableSelect.get(thisCol);
				for(int selectIndex = 0;selectIndex < selects.size();selectIndex++)
				{
					SelectQueryStruct select = selects.get(selectIndex);
					GenExpression filter = select.filter;
					
					System.out.println("Filter is set to  " + filter);
					if(filter != null)
					{
						GenExpression thisFilter = new GenExpression();
						thisFilter.setOperation(" AND ");
						((GenExpression)filter).paranthesis = true;
						thisFilter.setLeftExpresion(filter);
						// forcing a random opaque one
						userFilter.paranthesis = true;
						thisFilter.setRightExpresion(userFilter);
						// replace with the new filter
						select.filter = thisFilter;
					}
					// add a new filter otherwise
					else
					{
						select.filter = userFilter;						
					}
					
				}
			}
		}
	}
	
	// get the query for a given column in the select
	public String getFilterQuery(String columnName)
	{
		String retQuery = null;
		
		
		return retQuery;
		
	}
	
	// the key is the table name and the value is the GenExpression that should be used
	// I have a query with a few parameters
	// if the parameters are not there then drop it from groupby ?
	// if there are then add it
	// I have a query with multiple groupby, if the groupby is not 
	// the parameter i.e. the column can be - drop
	// 2 blocks
	// columns to be removed
	// columns to be parameterized
	
	public void appendParameter(List  columnsToRemove, Map  paramValues)
	{
		// I still need to account for if the user already comes with this
		// get the selects for the param columns
		// add them 
		
		// this whole caching strategy is not working
		// I have to just go off every select and do it
		
		// first is the remove
		for(int colIndex = 0;colIndex < columnsToRemove.size();colIndex++)
		{
			// find the alias
			// find the column
			// remove from the select and also from the group by
			
			// this is probably coming through with the alias name
			// get all of the selects and run through it
			Iterator  allSelects = selectColumns.keySet().iterator();
			
			while(allSelects.hasNext())
			{
				
					GenExpression thisSelect = allSelects.next();	
					// remove from the selector
					thisSelect.removeSelect(columnsToRemove.get(colIndex));
					thisSelect.removeGroup(columnsToRemove.get(colIndex));
					
					StringBuffer buff = thisSelect.printQS((GenExpression)thisSelect, new StringBuffer());
				
				// go through every select and replace it 
				// there is a possibility where there are 2 different aliases refering to the same column name ?
				// and this can lead to issues
			}
		}

		// second is add
		// need a way to get to the appropriate selector
		Iterator  cols = paramValues.keySet().iterator();
		while(cols.hasNext())
		{
			// get the col
			String thisCol = cols.next();
			GenExpression userFilter = paramValues.get(thisCol);
			
			// see if a select with that table exists
			if(columnSelect.containsKey(thisCol))
			{
				// get the expression and see what is the where clause
				List  selects = columnSelect.get(thisCol);
				for(int selectIndex = 0;selectIndex < selects.size();selectIndex++)
				{
					SelectQueryStruct select = selects.get(selectIndex);
					select.parameterizeColumn(thisCol, userFilter);
				}
			}
		}
	}
	
	public void replaceColumn(String columnName, Object value)
	{
		List  tableColumn = columnTableIndex.get(columnName);
		if(tableColumn != null)
		{
			for(int index = 0;index < tableColumn.size();index++)
			{
				replaceTableColumn(tableColumn.get(index), value);
			}
		}
	}
	
	public void replaceTableColumn(String id, Object value)
	{
		List  tableColumnOperator = columnTableOperatorIndex.get(id);
		if(tableColumnOperator != null)
		{
			for(int index = 0;index < tableColumnOperator.size();index++)
			{
				replaceTableColumnOperator(tableColumnOperator.get(index), value);
			}
		}
	}
	
	public void replaceTableColumnOperator(String id, Object value)
	{
		if(operatorTableColumnParamIndex.containsKey(id))
		{
			ParamStructDetails tableColumnOperatorParam = operatorTableColumnParamIndex.get(id);
			tableColumnOperatorParam.setCurrentValue(value);
			//replaceParameter(tableColumnOperatorParam);
		}
	}
	
	// fills it with the latest list of parameters
	public void fillParameters()
	{
		Iterator  paramIterator = paramToExpressionMap.keySet().iterator();
		while(paramIterator.hasNext())
		{
			ParamStructDetails daStruct = paramIterator.next();
			// go through the pattern and fill it
			List  exprs = paramToExpressionMap.get(daStruct);
			
			if(exprs != null)
			{
				for(int exprIndex = 0;exprIndex < exprs.size();exprIndex++)
				{
					// get the current value and set it
					StringBuilder finalValue = new StringBuilder();
					String quote = "";
					if(daStruct.getType() == PixelDataType.CONST_STRING)
						quote = "";
					GenExpression thisExpression = exprs.get(exprIndex);
					finalValue.append(quote).append(daStruct.getCurrentValue()).append(quote);
					if(!thisExpression.operation.equalsIgnoreCase("opaque"))
						thisExpression.setLeftExpresion(finalValue.toString());	
					else
						thisExpression.setLeftExpr(finalValue.toString());	
						
				}
			}
		}
	}
	
	/**
	 * Fill the parameters with the user defined names
	 * @param incomingStructs
	 * @param detailsLookup
	 */
	public void fillParameters(List incomingStructs, Map detailsLookup) {
		// first replace the incoming structs with the user defined param names
		for(int paramIndex = 0; paramIndex < incomingStructs.size(); paramIndex++) {
			ParamStructDetails thisStruct = incomingStructs.get(paramIndex);
			LEVEL thisStructLevel = thisStruct.getLevel();
			if(thisStructLevel == LEVEL.DATASOURCE) {
				// not relevant for the query
				continue;
			}
			
			ParamStruct pStruct = detailsLookup.get(thisStruct);
			// normally this is for using [] vs just 
			// but here we are using it to indicate that quoting is defined by the FE
			boolean noQuote = ParamStruct.PARAM_FILL_USE_ARRAY_TYPES.contains(pStruct.getModelDisplay());
			String userDefinedParamName = pStruct.getParamName();
			
			if(thisStructLevel == LEVEL.COLUMN) {
				// loop through and find all at column level
				for(String key : operatorTableColumnParamIndex.keySet()) {
					ParamStructDetails targetStruct = operatorTableColumnParamIndex.get(key);
					if(targetStruct.getColumnName().equals(thisStruct.getColumnName())) {
						// replace the target struct with the user defined param name
						List  exprs = paramToExpressionMap.get(targetStruct);
						for(int exprIndex = 0; exprIndex < exprs.size(); exprIndex++) {
							// we will replace the existing parameter 
							// again with the parameter name
							// but this time that defined by the user
							String quote = null;
							if(noQuote || targetStruct.getQuote() == QUOTE.NO) {
								quote = "";
							} else if(targetStruct.getQuote() == QUOTE.DOUBLE) {
								quote = "\"";
							} else if(targetStruct.getQuote() == QUOTE.SINGLE) {
								quote = "'";
							}
							String finalValue = quote + "<" + userDefinedParamName + ">" + quote;
							
							GenExpression thisExpression = exprs.get(exprIndex);
							if(!thisExpression.operation.equalsIgnoreCase("opaque")) {
								thisExpression.setLeftExpresion(finalValue);	
							} else {
								thisExpression.setLeftExpr(finalValue);	
							}
						}
						
						// remove this struct from the overall so it wont fill
						paramToExpressionMap.remove(targetStruct);
					}
				}
			} else if(thisStructLevel == LEVEL.TABLE) {
				// loop through and find all at table level
				for(String key : operatorTableColumnParamIndex.keySet()) {
					ParamStructDetails targetStruct = operatorTableColumnParamIndex.get(key);
					if(targetStruct.getColumnName().equals(thisStruct.getColumnName())
							&& targetStruct.getTableName().equals(thisStruct.getTableName())
							) {
						// replace the target struct with the user defined param name
						List  exprs = paramToExpressionMap.get(targetStruct);
						for(int exprIndex = 0; exprIndex < exprs.size(); exprIndex++) {
							// we will replace the existing parameter 
							// again with the parameter name
							// but this time that defined by the user
							String quote = null;
							if(noQuote || targetStruct.getQuote() == QUOTE.NO) {
								quote = "";
							} else if(targetStruct.getQuote() == QUOTE.DOUBLE) {
								quote = "\"";
							} else if(targetStruct.getQuote() == QUOTE.SINGLE) {
								quote = "'";
							}
							String finalValue = quote + "<" + userDefinedParamName + ">" + quote;
							
							GenExpression thisExpression = exprs.get(exprIndex);
							if(!thisExpression.operation.equalsIgnoreCase("opaque")) {
								thisExpression.setLeftExpresion(finalValue);	
							} else {
								thisExpression.setLeftExpr(finalValue);	
							}
						}
						
						// remove this struct from the overall so it wont fill
						paramToExpressionMap.remove(targetStruct);
					}
				}
			} else if(thisStructLevel == LEVEL.OPERATOR) {
				// loop through and find all at operator level
				for(String key : operatorTableColumnParamIndex.keySet()) {
					ParamStructDetails targetStruct = operatorTableColumnParamIndex.get(key);
					if(targetStruct.getColumnName().equals(thisStruct.getColumnName())
							&& targetStruct.getTableName().equals(thisStruct.getTableName())
							&& targetStruct.getOperator().equals(thisStruct.getOperator())
							) {
						// replace the target struct with the user defined param name
						List  exprs = paramToExpressionMap.get(targetStruct);
						for(int exprIndex = 0; exprIndex < exprs.size(); exprIndex++) {
							// we will replace the existing parameter 
							// again with the parameter name
							// but this time that defined by the user
							String quote = null;
							if(noQuote || targetStruct.getQuote() == QUOTE.NO) {
								quote = "";
							} else if(targetStruct.getQuote() == QUOTE.DOUBLE) {
								quote = "\"";
							} else if(targetStruct.getQuote() == QUOTE.SINGLE) {
								quote = "'";
							}
							String finalValue = quote + "<" + userDefinedParamName + ">" + quote;
							
							GenExpression thisExpression = exprs.get(exprIndex);
							if(!thisExpression.operation.equalsIgnoreCase("opaque")) {
								thisExpression.setLeftExpresion(finalValue);	
							} else {
								thisExpression.setLeftExpr(finalValue);	
							}
						}
						
						// remove this struct from the overall so it wont fill
						paramToExpressionMap.remove(targetStruct);
					}
				}
			} else if(thisStructLevel == LEVEL.OPERATORU) {
				String paramStructDetailsKey = thisStruct.getParamKey();
				// compare at u operator level using the param struct details key
				if(operatorTableColumnParamIndex.containsKey(paramStructDetailsKey)){
					ParamStructDetails targetStruct = operatorTableColumnParamIndex.get(paramStructDetailsKey);
					// replace the target struct with the user defined param name
					List  exprs = paramToExpressionMap.get(targetStruct);
					for(int exprIndex = 0; exprIndex < exprs.size(); exprIndex++) {
						// we will replace the existing parameter 
						// again with the parameter name
						// but this time that defined by the user
						String quote = null;
						if(noQuote || targetStruct.getQuote() == QUOTE.NO) {
							quote = "";
						} else if(targetStruct.getQuote() == QUOTE.DOUBLE) {
							quote = "\"";
						} else if(targetStruct.getQuote() == QUOTE.SINGLE) {
							quote = "'";
						}
						String finalValue = quote + "<" + userDefinedParamName + ">" + quote;
						
						GenExpression thisExpression = exprs.get(exprIndex);
						if(!thisExpression.operation.equalsIgnoreCase("opaque")) {
							thisExpression.setLeftExpresion(finalValue);	
						} else {
							thisExpression.setLeftExpr(finalValue);	
						}
					}
					
					// remove this struct from the overall so it wont fill
					paramToExpressionMap.remove(targetStruct);
				}
			}
		}
		
		/*
		 * replace all the other structs with the default values already present in the query
		 * this does not take in inputs
		 * it goes through all the remaining structs generated THROUGH the parsing
		 * and places those back to the default values
		 */
		Iterator  paramIterator = paramToExpressionMap.keySet().iterator();
		while(paramIterator.hasNext()) {
			ParamStructDetails structDetails = paramIterator.next();
			// go through the pattern and fill it
			List  exprs = paramToExpressionMap.get(structDetails);

			if(exprs != null) {
				for(int exprIndex = 0; exprIndex < exprs.size(); exprIndex++) {
					// get the current value and set it
					StringBuilder finalValue = new StringBuilder();
					String quote = "";
					if(structDetails.getType() == PixelDataType.CONST_STRING) {
						quote = "";
					}
					GenExpression thisExpression = exprs.get(exprIndex);
					finalValue.append(quote).append(structDetails.getCurrentValue()).append(quote);
					if(!thisExpression.operation.equalsIgnoreCase("opaque")) {
						thisExpression.setLeftExpresion(finalValue.toString());	
					} else {
						thisExpression.setLeftExpr(finalValue.toString());	
					}
				}
			}
		}
	}
	
	public String makeParameters(String columnName, Object constantValue, String operationName, String actualOperationName, String constantType, GenExpression exprToTrack, String tableName, String defQuery)
	{
		//String tableAliasName = columnName.substring(0, columnName.indexOf("."));
		String tableAliasName = tableName;
		if(tableAlias.containsKey(tableAliasName)) {
			tableName = tableAlias.get(tableAliasName);
		}
		
		//columnName = columnName.replace(tableAliasName + ".", "");
		//columnName = columnName.replace(".", "");

		// add it to the column index first
		List  tableColumnList = new Vector();
		if(this.columnTableIndex.containsKey(columnName)) {
			tableColumnList = columnTableIndex.get(columnName);
		}
		
		String tableColumnComposite = tableName + "_" + columnName;

		if(!tableColumnList.contains(tableColumnComposite)) {
			tableColumnList.add(tableColumnComposite);
		}
		columnTableIndex.put(columnName, tableColumnList);

		// next add the operator
		// need to see if the operator exists
		// if so i need to pop and do the left and right magic
		List  operatorTableColumnList = new Vector();
		if(this.columnTableOperatorIndex.containsKey(tableColumnComposite)) {
			operatorTableColumnList = columnTableOperatorIndex.get(tableColumnComposite);
		}
		
		String tableColumnOperatorComposite = tableColumnComposite + operationName;
		if(!operatorTableColumnList.contains(tableColumnOperatorComposite)) {
			operatorTableColumnList.add(tableColumnOperatorComposite);
		}

		columnTableOperatorIndex.put(tableColumnComposite, operatorTableColumnList);

		ParamStructDetails daStruct = null;
		if(!operatorTableColumnParamIndex.containsKey(tableColumnOperatorComposite)) {
			String context = "";
			String contextPart = "";
			if(contextExpression.size() > 0) {
				context = contextExpression.pop();
				// get the context part
				contextPart = exprToTrack.printQS(exprToTrack, null) + "";
			}
			daStruct = new ParamStructDetails();
			daStruct.setColumnName(columnName);
			daStruct.setTableAlias(tableAliasName);
			daStruct.setTableName(tableName);
			daStruct.setCurrentValue(constantValue);
			daStruct.setOperator(actualOperationName);
			daStruct.setuOperator(operationName); // this is the unique operator so that it can be pegged
			daStruct.setContext(context);
			daStruct.setContextPart(contextPart);
			daStruct.setDefQuery(defQuery);

			// need to get the current select struct to add to this

			if(constantType.equalsIgnoreCase("string")) {
				daStruct.setType(PixelDataType.CONST_STRING);
				daStruct.setQuote(QUOTE.SINGLE);
			} else if(constantType.equalsIgnoreCase("double")) {
				daStruct.setType(PixelDataType.CONST_DECIMAL);
				daStruct.setQuote(QUOTE.NO);
			} else if(constantType.equalsIgnoreCase("long")) {
				daStruct.setType(PixelDataType.CONST_INT);
				daStruct.setQuote(QUOTE.NO);
			} else if(constantType.equalsIgnoreCase("date")) {
				daStruct.setType(PixelDataType.CONST_DATE);
				daStruct.setQuote(QUOTE.SINGLE);
			} else if(constantType.equalsIgnoreCase("timestamp")) {
				daStruct.setType(PixelDataType.CONST_TIMESTAMP);
				daStruct.setQuote(QUOTE.SINGLE);
			}

			operatorTableColumnParamIndex.put(tableColumnOperatorComposite, daStruct);						
			if(context.length() > 0) {
				contextExpression.push(context);
			}
		} else {
			daStruct = operatorTableColumnParamIndex.get(tableColumnOperatorComposite);
		}
		List  allExpressions = new Vector();
		// now add this gen expression to it
		if(paramToExpressionMap.containsKey(daStruct)) {
			allExpressions = paramToExpressionMap.get(daStruct);
		}
		allExpressions.add(exprToTrack);
		paramToExpressionMap.put(daStruct, allExpressions);
		paramStringToParamMap.put(tableColumnOperatorComposite, daStruct);
		
		uniqueCounter++;
		
		//System.err.println("Parameterizing " + columnName + " with <><> " + defQuery);

		return tableColumnOperatorComposite;
	}
	
	// get all the param structs for 
	public List  getParams()
	{
		List  allParams = new Vector();
		allParams.addAll(paramToExpressionMap.keySet());
		return allParams;
	}
	
	//////////////////////////////////////////////////////////////METHOD FOR MANIPULATING PARAMETERS /////////////////////////////////////////////////////
	//////////////////////////////////////////////////////////////METHOD FOR MANIPULATING FUNCTIONS /////////////////////////////////////////////////////

	public void addFunctionExpression(String functionName, GenExpression expr)
	{
		List  exprList = null;
		if(functionExpressionMapper.containsKey(functionName))
			exprList = functionExpressionMapper.get(functionName);
		else
			exprList = new ArrayList ();
		
		if(!exprList.contains(expr))
			exprList.add(expr);
		
		functionExpressionMapper.put(functionName, exprList);
	}
	
	
	public static Object []  getLineage(GenExpression starter, String name, Map > selectLineage, Map  columnLineage, List  allInstances, int level)
	{
		// from this point on, tries to find and print the lineage of this column i.e. which particular 
		// find the column name and table name
		// if the table name is not there then there is possibly only one table
		// go down to from
		
		//System.err.println("Processing level .. " + level);
		if(selectLineage == null)
			selectLineage = new HashMap>();
		if(columnLineage == null)
			columnLineage = new HashMap();
		
		if(allInstances == null)
			allInstances = new Vector();

		GenExpression identifiedSelector = null;
		
		List  levelLineage = null;
		if(selectLineage.containsKey(level))
			levelLineage = selectLineage.get(level);
		else
			levelLineage = new Vector();
		
		String newName = name;
		// find if this is even there as the first projection	
		if(! (starter instanceof OperationExpression)) // make sure this is not a union
		{
			for(int selectorIndex = 0;selectorIndex < starter.nselectors.size();selectorIndex++)
			{
				// check to see if the selector is here if yes, then find the from
				// if the from is not a simple from then pass to that 
				GenExpression curSelector = starter.nselectors.get(selectorIndex);
				
					
				String selectorAlias = curSelector.leftAlias;
				//System.err.println("Selector alias is set to .. " + selectorName);
				String selectorColumn = curSelector.getLeftExpr();

				// there is a possibility this is a functional expression
				if(curSelector instanceof FunctionExpression)
					selectorColumn = getColumnFromFunctionExpression((FunctionExpression)curSelector, false);
					
				// remove the quotes
				if(selectorAlias != null)
				{
					selectorAlias = selectorAlias.replace("`", "");
					selectorAlias = selectorAlias.replace("'", "");
					selectorAlias = selectorAlias.replace("\"", "");
					
					//System.err.println(selectorName + " <<>> " + name);
					
					if(name.contentEquals(selectorAlias))
					{
						allInstances.add(curSelector);
						identifiedSelector = curSelector;
						// if it is a function and the selector alias is set to null.. use the column itself
						//System.err.println("Left expression " + curSelector.getLeftExpr());
						if(curSelector instanceof FunctionExpression)
							newName = getColumnFromFunctionExpression((FunctionExpression)curSelector, false);
						else if(selectorColumn != null)
							newName = selectorColumn;
						else
							newName = selectorAlias;

						columnLineage.put(level+1, curSelector);
						
						break;
					}
				}
				// compare both
				if(name.contentEquals(selectorColumn))
				{
					allInstances.add(curSelector);
					identifiedSelector = curSelector;
					//System.err.println("Left expression " + curSelector.getLeftExpr());
					if(curSelector instanceof FunctionExpression)
						newName = getColumnFromFunctionExpression((FunctionExpression)curSelector, false);
					else if(selectorColumn != null)
						newName = selectorColumn;
					else
						newName = selectorAlias;
					
					columnLineage.put(level+1, curSelector);
					
					break;
				}
			}
		}		
		
		// groupby
		// do I care about groupby ?
		// given we are neutralizing now..
		// I think we should add the groupby as well
		// the only reason is if possibly this was not there in the selector ?
		//if(identifiedSelector == null)
		for(int groupIndex = 0;groupIndex < starter.ngroupBy.size();groupIndex++)
		{
			GenExpression curSelector = starter.ngroupBy.get(groupIndex);
			String selectorAlias = curSelector.leftAlias;
			//System.err.println("Selector alias is set to .. " + selectorName);
			String selectorColumn = curSelector.getLeftExpr();
			
			// there is a possibility this is a functional expression
			if(curSelector instanceof FunctionExpression)
				selectorColumn = getColumnFromFunctionExpression((FunctionExpression)curSelector, false);

			
			if(selectorAlias != null)
			{
				// remove the quotes
				selectorAlias = selectorAlias.replace("`", "");
				selectorAlias = selectorAlias.replace("'", "");
				selectorAlias = selectorAlias.replace("\"", "");
				
				//System.err.println(selectorName + " <<>> " + name);
				
				if(name.contentEquals(selectorAlias))
				{
					//levelLineage.add(curSelector);
					allInstances.add(curSelector);
					if(identifiedSelector == null)
					{
						identifiedSelector = curSelector;
						System.err.println("Left expression " + curSelector.getLeftExpr());
						if(curSelector instanceof FunctionExpression)
							newName = getColumnFromFunctionExpression((FunctionExpression)curSelector, false);
						else if(selectorColumn != null)
							newName = selectorColumn;
						else
							newName = selectorAlias;
						columnLineage.put(level+1, curSelector);
					}					
					break;
				}
			}
			// compare both
			if(name.contentEquals(selectorColumn) )
			{
				allInstances.add(curSelector);
				identifiedSelector = curSelector;
				//System.err.println("Left expression " + curSelector.getLeftExpr());
				if(curSelector instanceof FunctionExpression)
					newName = getColumnFromFunctionExpression((FunctionExpression)curSelector, false);
				else if(selectorColumn != null)
					newName = selectorColumn;
				else
					newName = selectorAlias;
				
				columnLineage.put(level+1, curSelector);
				
				break;
			}
			
		}

		// filters
		// add the filters
		if(starter.filter != null)
		{
			List  filterExpressions = getSelectorInComposite(name,  starter.filter, null);
			allInstances.addAll(filterExpressions);
		}		
		// process the from to see if it is a table or a full select
		// if this is not a composite we are all set
		// we need to now do this for each of the gen expressions
		//if(identifiedSelector != null)
		{
			if(starter.from != null && starter.from.composite)
			{
				//System.err.println("Comparing from " + starter.from);
				// ot sure I need this check
				//if(fromAlias.contentEquals(starter.tableName) && !levelLineage.contains(starter.from))
					levelLineage.add(starter.from);
			}
			//else if(!allInstances.contains(starter)) // found the bogey
			//	allInstances.add(starter);
		}
		
		// now come the joins
		//if(identifiedSelector == null)
		for(int joinIndex = 0;joinIndex < starter.joins.size();joinIndex++)
		{
			GenExpression curJoin = starter.joins.get(joinIndex);	
			List  allColumns = getSelectorInComposite(name, curJoin.body, null);
			// find if this join is the one
			// if the body is composite
			if(curJoin.from.composite)
				levelLineage.add(curJoin.from); // search for next level
			allInstances.addAll(allColumns);
			// the body may be composite or the body may be simple
		}
		
		// TODO: Union
		
		// also process final query
		// need to track the name at each level as well as w
		
		// add these back 
		selectLineage.put(level, levelLineage);
		//columnLineage.put(level, levelLineage);
		
		//System.out.println("--x--x--x-- >>" +  newName);
		
		// now basically run through the select lineage list
		if(levelLineage.size() > 0)
		{
			for(int nextIndex = 0;nextIndex < levelLineage.size();nextIndex++)
				return getLineage(levelLineage.get(nextIndex), newName, selectLineage, columnLineage, allInstances, (level+1));		
		}		
		
		Object [] badStruct = new Object[4];
		badStruct[0] = selectLineage;
		badStruct[1] = columnLineage;
		badStruct[2] = allInstances;
		badStruct[3] = level;
		
		return badStruct;
	}

	// known anomalies
	// #1 - When the join condition precedes the filter condition
	
	public static String getColumnFromFunctionExpression(FunctionExpression expr, boolean table)
	{
		String retString = null;
		
		if(expr.expressions.size() == 1)
		{
			GenExpression gep = expr.expressions.get(0);
			
			if(gep instanceof FunctionExpression)
				retString =  getColumnFromFunctionExpression((FunctionExpression)gep, table);

			else if(gep.operation != null && gep.operation.equalsIgnoreCase("column"))
			{
				String tableName = gep.tableName;
				retString = gep.getLeftExpr();
				if(table)
					retString = tableName + "." + retString;
			}
		}
		
		return retString;
		
	}
	
	
	public static List getSelectorInComposite(String name, GenExpression qs, List  selectorList)
	{
		if(selectorList == null)
			selectorList = new Vector();
		
		
		List  nextIterator = new Vector();
		
		boolean neutralLeft = false;
		boolean neutralRight = false;
		
		// need to accomodate for operation
		if(qs.leftItem != null)
		{
			if(qs.leftItem instanceof GenExpression && !((GenExpression)qs.leftItem).composite && ((GenExpression)qs.leftItem).getOperation().equalsIgnoreCase("Column"))
			{
				GenExpression leftItem = (GenExpression)qs.leftItem;
				// do the left alias magic
				
				// this is where we need to do the paranthesis again I think
				String selectorName = leftItem.leftAlias;
				if(selectorName == null)
					selectorName = leftItem.getLeftExpr();
				
				if(name.contentEquals(selectorName))
				{
					//levelLineage.add(curSelector);
					selectorList.add(qs);
					neutralLeft = true;
					if(selectorList.contains((GenExpression)qs.parent.rightItem))
						selectorList.add(qs.parent);
				}
			}
			else if(qs.leftItem instanceof GenExpression)
				nextIterator.add((GenExpression)qs.leftItem);
		}
		
		if(qs.rightItem != null)
		{
			if(qs.rightItem instanceof GenExpression && !((GenExpression)qs.rightItem).composite && ((GenExpression)qs.rightItem).getOperation().equalsIgnoreCase("Column"))
			{
				GenExpression rightItem = (GenExpression)qs.rightItem;
				// do the left alias magic
				
				// this is where we need to do the paranthesis again I think
				String selectorName = rightItem.leftAlias;
				if(selectorName == null)
					selectorName = rightItem.getLeftExpr();
				
				if(name.contentEquals(selectorName))
				{
					//levelLineage.add(curSelector);
					selectorList.add(qs);
					neutralRight = true;
					if(selectorList.contains((GenExpression)qs.parent.leftItem))
						selectorList.add(qs.parent);
				}
			}
			else if(qs.rightItem instanceof GenExpression)
				nextIterator.add((GenExpression)qs.rightItem);
		}
				
		if(nextIterator.size() > 0)
		{
			for(int iterIndex = 0;iterIndex < nextIterator.size();iterIndex++)
				getSelectorInComposite(name, nextIterator.get(iterIndex), selectorList);
		}
		return selectorList;
	}
	
	
	public static String getPhysicalColumnName(GenExpression starter, String projectionName)
	{
		Object [] output = getLineage(starter, projectionName, null, null, null, 0);
		
		// get the final query
		int level = (Integer)output[3] + 1;
		
		
		Map  columnLineage = (Map)output[1];
		
		GenExpression selector = null;
		
		// find the latest columnLineage
		do {
			selector = columnLineage.get(level);
			level--;
		}while(selector == null && level >= 0);
		
		
		if(selector != null)
		{
			if(selector instanceof FunctionExpression)
				return getColumnFromFunctionExpression((FunctionExpression)selector, true);
			else
				return selector.tableName + "." + selector.getLeftExpr();
		}
		return null;		
	}
	
	
	public static void neutralizeSelector(GenExpression starter, String projectionName, boolean neutralize)
	{
		// need to get the tree and neutralize the selector at every level
		Object [] output = getLineage(starter, projectionName, null, null, null, 0);
		
		// I just need to grab the first array and neutralize
		List  instanceList = (List )output[2];
		for(int instanceIndex = 0;instanceIndex < instanceList.size();instanceIndex++)
		{
			GenExpression curExpression = instanceList.get(instanceIndex);
			curExpression.neutralize = neutralize;
		}		
	}
	
	

	public List  getColumnsForFunction(String functionName)
	{
		List  retList = new ArrayList ();
		if(functionExpressionMapper.containsKey(functionName))
		{
			List  allExprs = functionExpressionMapper.get(functionName);
			for(int exprIndex = 0;exprIndex < allExprs.size();exprIndex++)
			{
				GenExpression curSelector = allExprs.get(exprIndex);
				String curName = null;
				
				//if(expr instanceof FunctionExpression)
				{
					// need to do some magic here
					if(curSelector instanceof FunctionExpression)
						curName = getColumnFromFunctionExpression((FunctionExpression)curSelector,false);
					else if(curSelector.leftAlias != null)
						curName = curSelector.leftAlias;
					else
						curName = curSelector.getLeftExpr();
				}	
				System.out.println("curName is set to " + curName);
				String physicalName = getPhysicalColumnName(root, curName);
				System.out.println("Physical name "+ physicalName);
			
				if(physicalName != null)
					retList.add(physicalName);
				else
					retList.add(curName);
			}
		}
		
		return retList;
	}
	
	public void neutralizeFunction(GenExpression starter, String functionName, boolean neutralize)
	{

		// I just need to grab the first array and neutralize
		if(functionExpressionMapper.containsKey(functionName))
		{
			List  allExprs = functionExpressionMapper.get(functionName);
			for(int exprIndex = 0;exprIndex < allExprs.size();exprIndex++)
			{
				FunctionExpression curSelector = (FunctionExpression)allExprs.get(exprIndex);
				curSelector.neutralizeFunction = neutralize;
			}
		}
			
	}

	// add function to a selector
	public void addFunctionToSelector(GenExpression select, String selectorName, String functionName)
	{
		// get the selectors parent
		// create a function expression by setting operation to function
		// add the current selector to the expression
		// get the alias and if not available, use the selector directly
		// remove this from the list of selectors
		// set the alias for function expression to be the alias
		// add this to the selectors
		
		GenExpression selector = null;
		for(int selectIndex = 0;selectIndex < select.nselectors.size();selectIndex++) 
		{
			GenExpression curSelector = select.nselectors.get(selectIndex);
			String selectorAlias = curSelector.leftAlias;
			//System.err.println("Selector alias is set to .. " + selectorName);
			String selectorColumn = curSelector.getLeftExpr();

			// there is a possibility this is a functional expression
			if(curSelector instanceof FunctionExpression)
				selectorColumn = getColumnFromFunctionExpression((FunctionExpression)curSelector, false);

			if((selectorAlias != null && selectorName.equalsIgnoreCase(selectorAlias) )|| selectorName.equalsIgnoreCase(selectorColumn))
			{
				selector = curSelector;
				break;
			}	
		}
		
		if(selector != null)
		{
			FunctionExpression funExpression = new FunctionExpression();
			funExpression.operation = "function";
			funExpression.setExpression(functionName);
			funExpression.expressions.add(selector);
			String alias = selector.leftAlias;
			if(alias == null)
				alias = selector.getLeftExpr();
			
			funExpression.leftAlias = alias;
			select.nselectors.remove(selector);
			select.nselectors.add(funExpression);
		}		
		// done
	}
		
	// get the final query 
	public static String transformQueryWithParams(String originalQuery, List  incomingStructs)
	{
		String retQuery = null;
		try {
			SqlParser2 parse2 = new SqlParser2();
			parse2.parameterize = true;
			
			GenExpressionWrapper wrapper = parse2.processQuery(originalQuery);
			//System.out.println("Before Transformation " + wrapper.root.printQS(wrapper.root, null) + "");
			for(int paramIndex = 0;paramIndex < incomingStructs.size();paramIndex++)
			{
				ParamStructDetails thisStruct = incomingStructs.get(paramIndex);
				String ParamStructDetailsKey = thisStruct.getParamKey();
				
				if(wrapper.operatorTableColumnParamIndex.containsKey(ParamStructDetailsKey))
				{
					ParamStructDetails targetStruct = wrapper.operatorTableColumnParamIndex.get(ParamStructDetailsKey);
					// remove this struct from the overall so it wont fill
					wrapper.paramToExpressionMap.remove(targetStruct);
				}
			}
			wrapper.fillParameters();
			retQuery = wrapper.root.printQS(wrapper.root, null) + "";
		} catch (Exception e) {
			// TODO Auto-generated catch block
			classLogger.error(Constants.STACKTRACE, e);
		}
		
		return retQuery;
	}
	
	/**
	 * Transform the query and replace the param struct with the user defined param names via the lookup
	 * @param originalQuery
	 * @param incomingStructs
	 * @param detailsLookup
	 * @return
	 * @throws Exception
	 */
	public static String transformQueryWithParams(String originalQuery, List incomingStructs, Map detailsLookup) throws Exception {
		String retQuery = null;
		SqlParser2 parse2 = new SqlParser2();
		parse2.parameterize = true;
		
		GenExpressionWrapper wrapper = parse2.processQuery(originalQuery);
		wrapper.fillParameters(incomingStructs, detailsLookup);
		retQuery = GenExpression.printQS(wrapper.root, null) + "";
		
		return retQuery;
	}
	
	public Map   getAllParamNames()
	{
		// gets all of the param names in a query like this
		/*
		 * SELECT  actor_name, title, gender
		  	FROM actor
		  WHERE gender  > >   AND title  IN  (
		SELECT  title
		  FROM mv
		  WHERE director  =    AND revenue_domestic  > budget  )   AND actor_name  IN  () 

		 */
		
		// here the param names would be > or   etc. 
		// may be also give default values
		Map  retList = new HashMap();
		
		// pass through param hash and add it
		Iterator  paramKeys = paramStringToParamMap.keySet().iterator();
		
		while(paramKeys.hasNext())
		{
			String param1 = paramKeys.next();
			ParamStructDetails daStruct = paramStringToParamMap.get(param1);			
			//String key = 
			Object value = daStruct.getCurrentValue();
			retList.put(param1, value);
		}
		
		return retList;
	}
	
	public Object getCurrentValueOfParam(String paramName)
	{
		// gets the current value fo the set param name
		// like >
		// the front end should be able to directly substitute this value
		// this is fairly straight forward
		ParamStructDetails daStruct = paramStringToParamMap.get(paramName);
		if(daStruct !=null)
		//String key = 
			return daStruct.getCurrentValue();
		return null;
	}

	public boolean setCurrentValueOfParam(String paramName, Object value)
	{
		// sets the current value fo the set param name
		// like >
		// the front end should be able to directly substitute this value
		ParamStructDetails daStruct = paramStringToParamMap.get(paramName);
		if(daStruct !=null)
		{
			daStruct.setCurrentValue(value);
			return true;
		}
		return false;
	}
	
	public String getQueryForParam(String paramName)
	{
		// somehow need to construct the query struct that can be used to query the possible values
		// sets the current value fo the set param name
		// like >
		// the front end should be able to directly substitute this value
		ParamStructDetails daStruct = paramStringToParamMap.get(paramName);
		if(daStruct !=null)
			return daStruct.getDefQuery();
		return null;
	}
	
	public String generateQuery(boolean validate) throws Exception
	{
		String finalQuery = ((GenExpression)root).printQS(((GenExpression)root), new StringBuffer()).toString(); 
		
		System.err.println(finalQuery);
		
		// the real test is can I parse it back :)
		if(validate)
		{
			Statement stmt = CCJSqlParserUtil.parse(finalQuery);
		}
		System.err.println("Success ");
		return finalQuery;
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy