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

prerna.query.interpreters.sql.TeradataSqlInterpreter Maven / Gradle / Ivy

The newest version!
package prerna.query.interpreters.sql;

import java.util.List;
import java.util.Vector;

import prerna.algorithm.api.ITableDataFrame;
import prerna.engine.api.IDatabaseEngine;
import prerna.query.querystruct.HardSelectQueryStruct;
import prerna.query.querystruct.SelectQueryStruct;
import prerna.query.querystruct.selectors.IQuerySelector;
import prerna.query.querystruct.selectors.IQuerySort;
import prerna.query.querystruct.selectors.QueryColumnOrderBySelector;
import prerna.query.querystruct.selectors.QueryColumnOrderBySelector.ORDER_BY_DIRECTION;
import prerna.query.querystruct.selectors.QueryColumnSelector;
import prerna.util.Constants;
import prerna.util.Utility;
import prerna.util.sql.TeradataQueryUtil;

public class TeradataSqlInterpreter  extends SqlInterpreter {


	public TeradataSqlInterpreter() {

	}

	public TeradataSqlInterpreter(IDatabaseEngine engine) {
		super(engine);
	}

	public TeradataSqlInterpreter(ITableDataFrame frame) {
		super(frame);
	}

	//overriden since i need limit before the order by
	@Override
	public String composeQuery()
	{
		if(this.qs instanceof HardSelectQueryStruct) {
			return ((HardSelectQueryStruct)this.qs).getQuery();
		}

		//If the smss says this app is part of a big data engine, then some changes happen.
		// 1) grid does not display distinct values
		// 2) anything with no task options 
		//		Boolean bigDataEngine = false;
		//		Object bigDataProp = this.engine.getProp().get(Constants.BIG_DATA_ENGINE);
		//		if(bigDataProp!= null){
		//			bigDataEngine = Boolean.parseBoolean(this.engine.getProp().get(Constants.BIG_DATA_ENGINE).toString());
		//		}

		/*
		 * Need to create the query... 
		 * This to consider:
		 * 1) the user is going to be using the conceptual names as defined by the OWL (if present
		 * and OWL is the improved version). This has a few consequences:
		 * 1.a) when a user enters a table name, we need to determine what the primary key is
		 * 		for that table
		 * 1.b) need to consider what tables are used within joins and which are not. this will
		 * 		determine when we add it to the from clause or if the table will be defined via 
		 * 		the join 
		 */

		String customFrom = this.qs.getCustomFrom();
		this.customFromAliasName = this.qs.getCustomFromAliasName();
		// we do the joins since when we get to adding the from portion of the query
		// we want to make sure that table is not used within the joins
		addJoins();
		addSelectors();
		addFilters();
		addHavingFilters();
		addOrderBys();
		addOrderBySelector();
		
		//if there it is a big data engine, dont put distinct onto qs's with task options
		//other wise us the standard logic
		if(this.qs.getBigDataEngine()){
			//big data engine is never distinct
			((SelectQueryStruct) this.qs).setDistinct(false);

			Boolean taskOptionsExist = false;
			Object isTaskProp = this.qs.getPragmap().get(Constants.TASK_OPTIONS_EXIST);
			if(isTaskProp != null){
				taskOptionsExist= Boolean.parseBoolean(isTaskProp.toString());
			}

			// if task options exists, it likely a vis
			if(!taskOptionsExist){
				// if there is 1 selector, group by it instead
				if (((SelectQueryStruct) this.qs).getSelectors().size() == 1){
					IQuerySelector selector = ((SelectQueryStruct) this.qs).getSelectors().get(0);
					if(selector.getSelectorType()==IQuerySelector.SELECTOR_TYPE.COLUMN){
						((SelectQueryStruct) this.qs).addGroupBy((QueryColumnSelector)selector);
					}
				}
			}
		}

		StringBuilder query = new StringBuilder("SELECT ");
		String distinct = "";
		if(((SelectQueryStruct) this.qs).isDistinct()) {
			distinct = "DISTINCT ";
		}

		// do we have a custom from?
		if(customFrom != null && !customFrom.isEmpty()) {
			// at the moment
			// no join logic with custom from
			query.append(distinct).append(selectors).append(" FROM (").append(customFrom).append(" ) AS " + this.customFromAliasName);
		} else {
			// logic for adding the selectors + the from statement + the joins

			if(this.engine != null && !engine.isBasic() && joinStructList.isEmpty()) {
				// if there are no joins, we know we are querying from a single table
				// the vast majority of the time, there shouldn't be any duplicates if
				// we are selecting all the columns
				String table = froms.get(0)[0];
				if(engine != null && !engine.isBasic()) {
					String physicalUri = engine.getPhysicalUriFromPixelSelector(table);
					if( (engine.getPhysicalConcepts().size() == 1) && (engine.getPropertyUris4PhysicalUri(physicalUri).size() + 1) == selectorList.size()) {
						// plus one is for the concept itself
						// no distinct needed
						query.append(selectors);
					} else {
						query.append(distinct).append(selectors);
					}
				} else {
					// need a distinct
					query.append(distinct).append(selectors).append(" FROM ");
				}
			} else {
				// default is to use a distinct
				query.append(distinct).append(selectors);
			}

			// if there is a join
			// can only have one table in from in general sql case 
			// thus, the order matters 
			// so get a good starting from table
			// we can use any of the froms that is not part of the join
			boolean appendStartingFrom = true;
			if(this.joinStructList.isEmpty()) {
				appendStartingFrom = false;
				query.append(" FROM ");
				if(this.froms.isEmpty() && this.frame != null) {
					query.append(frame.getName());
				} else {
					String[] startPoint = this.froms.get(0);
					query.append(startPoint[0]).append(" ").append(startPoint[1]).append(" ");
				}
			} else {
				query.append(" ").append(joinStructList.getJoinSyntax(appendStartingFrom));
			}
		}

		// add where clause filters
		int numFilters = this.filterStatements.size();
		for(int i = 0; i < numFilters; i++) {
			if(i == 0) {
				query.append(" WHERE ");
			} else {
				query.append(" AND ");
			}
			query.append(this.filterStatements.get(i).toString());
		}

		//grab the order by and get the corresponding display name for that order by column
		query = appendGroupBy(query);
		// add having filters
		numFilters = this.havingFilterStatements.size();
		for(int i = 0; i < numFilters; i++) {
			if(i == 0) {
				query.append(" HAVING ");
			} else {
				query.append(" AND ");
			}
			query.append(this.havingFilterStatements.get(i).toString());
		}


		long limit = ((SelectQueryStruct) this.qs).getLimit();
		long offset = ((SelectQueryStruct) this.qs).getOffset();

		if(((SelectQueryStruct) this.qs).isDistinct()) {
			String tempTable = Utility.getRandomString(6);
			query = ((TeradataQueryUtil) this.queryUtil).addLimitOffsetToQuery(query, limit, offset, tempTable);
			query = appendOrderBy(query, tempTable);

		} else {
			query = ((TeradataQueryUtil) this.queryUtil).addLimitOffsetToQuery(query, limit, offset);
			query = appendOrderBy(query);
		}

		if(logger.isDebugEnabled()) {		
			if(query.length() > 500) {	
				logger.debug("TERADATA QUERY....  " + query.substring(0,  500) + "...");
			} else {
				logger.debug("TERADATA QUERY....  " + query);
			}
		}
		return query.toString();
	}

	private StringBuilder appendOrderBy(StringBuilder query, String tempTable) {
		//grab the order by and get the corresponding display name for that order by column
		List orderByList = ((SelectQueryStruct) this.qs).getCombinedOrderBy();
		List validOrderBys = new Vector<>();
		for(IQuerySort orderBy : orderByList) {
			if(orderBy.getQuerySortType() == IQuerySort.QUERY_SORT_TYPE.COLUMN) {
				QueryColumnOrderBySelector orderBySelector = (QueryColumnOrderBySelector) orderBy;
				String tableConceptualName = orderBySelector.getTable();
				String columnConceptualName = orderBySelector.getColumn();
				ORDER_BY_DIRECTION orderByDir = orderBySelector.getSortDir();
	
				boolean origPrim = false;
				if(columnConceptualName.equals(SelectQueryStruct.PRIM_KEY_PLACEHOLDER)){
					origPrim = true;
					columnConceptualName = getPrimKey4Table(tableConceptualName);
				} else {
					columnConceptualName = getPhysicalPropertyNameFromConceptualName(tableConceptualName, columnConceptualName);
				}
	
				StringBuilder thisOrderBy = new StringBuilder();
	
				// might want to order by a derived column being returned
				if(origPrim && this.selectorAliases.contains(tableConceptualName)) {
					// either instantiate the string builder or add a comma for multi sort
					if(queryUtil.isSelectorKeyword(tableConceptualName)) {
						thisOrderBy.append(queryUtil.getEscapeKeyword(tempTable));
					} else {
						thisOrderBy.append(tempTable);
					}
				}
				// we need to make sure the sort is a valid one!
				// if it is not already processed, there is no way to sort it...
				else if(this.retTableToCols.containsKey(tableConceptualName)){
					if(this.retTableToCols.get(tableConceptualName).contains(columnConceptualName)) {
						String orderByColumn = columnConceptualName;
						if(queryUtil.isSelectorKeyword(orderByColumn)) {
							orderByColumn = queryUtil.getEscapeKeyword(orderByColumn);
						}
						thisOrderBy.append(tempTable).append(".").append(orderByColumn);
					} else {
						continue;
					}
				} 
	
				// well, this is not a valid order by to add
				else {
					continue;
				}
	
				if(orderByDir == ORDER_BY_DIRECTION.ASC) {
					thisOrderBy.append(" ASC ");
				} else {
					thisOrderBy.append(" DESC ");
				}
				validOrderBys.add(thisOrderBy);
			}
		}

		int size = validOrderBys.size();
		for(int i = 0; i < size; i++) {
			if(i == 0) {
				query.append(" ORDER BY ");
			} else {
				query.append(", ");
			}
			query.append(validOrderBys.get(i).toString());
		}
		return query;
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy