private ObjectName ResolveGroupMax(SqlQueryExpression queryExpression, QueryExpressionFrom queryFrom) { var groupMax = queryExpression.GroupMax; if (groupMax != null) { var variable = queryFrom.ResolveReference(groupMax); if (variable == null) { throw new InvalidOperationException(String.Format("The GROUP MAX column '{0}' was not found.", groupMax)); } groupMax = variable; } return(groupMax); }
private static IQueryPlanNode PlanForOrderBy(IQueryPlanNode plan, IList<SortColumn> orderBy, QueryExpressionFrom queryFrom, IList<SelectColumn> selectedColumns) { // Sort on the ORDER BY clause if (orderBy.Count > 0) { int sz = orderBy.Count; var orderList = new ObjectName[sz]; var ascendingList = new bool[sz]; var functionOrders = new List<SqlExpression>(); for (int i = 0; i < sz; ++i) { var column = orderBy[i]; SqlExpression exp = column.Expression; ascendingList[i] = column.Ascending; var v = exp.AsReferenceName(); if (v != null) { var newV = queryFrom.ResolveReference(v); if (newV == null) throw new InvalidOperationException(String.Format("Could not resolve ORDER BY column '{0}' in expression", v)); newV = ReplaceAliasedVariable(newV, selectedColumns); orderList[i] = newV; } else { // Otherwise we must be ordering by an expression such as // '0 - a'. // Resolve the expression, exp = exp.Prepare(queryFrom.ExpressionPreparer); // Make sure we substitute any aliased columns in the order by // columns. exp = ReplaceAliasedVariables(exp, selectedColumns); // The new ordering functions are called 'FUNCTIONTABLE.#ORDER-n' // where n is the number of the ordering expression. orderList[i] = new ObjectName(FunctionTableName, "#ORDER-" + functionOrders.Count); functionOrders.Add(exp); } } // If there are functional orderings, // For this we must define a new FunctionTable with the expressions, // then order by those columns, and then use another SubsetNode // command node. int fsz = functionOrders.Count; if (fsz > 0) { var funs = new SqlExpression[fsz]; var fnames = new String[fsz]; for (int n = 0; n < fsz; ++n) { funs[n] = functionOrders[n]; fnames[n] = "#ORDER-" + n; } if (plan is SubsetNode) { // If the top plan is a SubsetNode then we use the // information from it to create a new SubsetNode that // doesn't include the functional orders we have attached here. var topSubsetNode = (SubsetNode)plan; var mappedNames = topSubsetNode.AliasColumnNames; // Defines the sort functions plan = new CreateFunctionsNode(plan, funs, fnames); // Then plan the sort plan = new SortNode(plan, orderList, ascendingList); // Then plan the subset plan = new SubsetNode(plan, mappedNames, mappedNames); } else { // Defines the sort functions plan = new CreateFunctionsNode(plan, funs, fnames); // Plan the sort plan = new SortNode(plan, orderList, ascendingList); } } else { // No functional orders so we only need to sort by the columns // defined. plan = new SortNode(plan, orderList, ascendingList); } } return plan; }
private ObjectName ResolveGroupMax(SqlQueryExpression queryExpression, QueryExpressionFrom queryFrom) { var groupMax = queryExpression.GroupMax; if (groupMax != null) { var variable = queryFrom.ResolveReference(groupMax); if (variable == null) throw new InvalidOperationException(String.Format("The GROUP MAX column '{0}' was not found.", groupMax)); groupMax = variable; } return groupMax; }
private static IQueryPlanNode PlanForOrderBy(IQueryPlanNode plan, IList <SortColumn> orderBy, QueryExpressionFrom queryFrom, IList <SelectColumn> selectedColumns) { // Sort on the ORDER BY clause if (orderBy.Count > 0) { int sz = orderBy.Count; var orderList = new ObjectName[sz]; var ascendingList = new bool[sz]; var functionOrders = new List <SqlExpression>(); for (int i = 0; i < sz; ++i) { var column = orderBy[i]; SqlExpression exp = column.Expression; ascendingList[i] = column.Ascending; var v = exp.AsReferenceName(); if (v != null) { var newV = queryFrom.ResolveReference(v); if (newV == null) { throw new InvalidOperationException(String.Format("Could not resolve ORDER BY column '{0}' in expression", v)); } newV = ReplaceAliasedVariable(newV, selectedColumns); orderList[i] = newV; } else { // Otherwise we must be ordering by an expression such as // '0 - a'. // Resolve the expression, exp = exp.Prepare(queryFrom.ExpressionPreparer); // Make sure we substitute any aliased columns in the order by // columns. exp = ReplaceAliasedVariables(exp, selectedColumns); // The new ordering functions are called 'FUNCTIONTABLE.#ORDER-n' // where n is the number of the ordering expression. orderList[i] = new ObjectName(FunctionTableName, "#ORDER-" + functionOrders.Count); functionOrders.Add(exp); } } // If there are functional orderings, // For this we must define a new FunctionTable with the expressions, // then order by those columns, and then use another SubsetNode // command node. int fsz = functionOrders.Count; if (fsz > 0) { var funs = new SqlExpression[fsz]; var fnames = new String[fsz]; for (int n = 0; n < fsz; ++n) { funs[n] = functionOrders[n]; fnames[n] = "#ORDER-" + n; } if (plan is SubsetNode) { // If the top plan is a SubsetNode then we use the // information from it to create a new SubsetNode that // doesn't include the functional orders we have attached here. var topSubsetNode = (SubsetNode)plan; var mappedNames = topSubsetNode.AliasColumnNames; // Defines the sort functions plan = new CreateFunctionsNode(plan, funs, fnames); // Then plan the sort plan = new SortNode(plan, orderList, ascendingList); // Then plan the subset plan = new SubsetNode(plan, mappedNames, mappedNames); } else { // Defines the sort functions plan = new CreateFunctionsNode(plan, funs, fnames); // Plan the sort plan = new SortNode(plan, orderList, ascendingList); } } else { // No functional orders so we only need to sort by the columns // defined. plan = new SortNode(plan, orderList, ascendingList); } } return(plan); }
public static QueryExpressionFrom Create(IRequest context, SqlQueryExpression expression) { // Get the 'from_clause' from the table expression var fromClause = expression.FromClause; var ignoreCase = context.Query.IgnoreIdentifiersCase(); var queryFrom = new QueryExpressionFrom(ignoreCase); foreach (var fromTable in fromClause.AllTables) { var uniqueKey = fromTable.UniqueKey; var alias = fromTable.Alias; if (fromTable.IsSubQuery) { // eg. FROM ( SELECT id FROM Part ) var subQuery = fromTable.SubQuery; var subQueryFrom = Create(context, subQuery); // The aliased name of the table ObjectName aliasTableName = null; if (alias != null) aliasTableName = new ObjectName(alias); // Add to list of sub-query tables to add to command, queryFrom.AddTable(new FromTableSubQuerySource(ignoreCase, uniqueKey, subQuery, subQueryFrom, aliasTableName)); } else { // Else must be a standard command table, string name = fromTable.Name; // Resolve to full table name var tableName = context.Query.ResolveTableName(name); if (!context.Query.TableExists(tableName)) throw new InvalidOperationException(String.Format("Table '{0}' was not found.", tableName)); ObjectName givenName = null; if (alias != null) givenName = new ObjectName(alias); // Get the ITableQueryInfo object for this table name (aliased). ITableQueryInfo tableQueryInfo = context.Query.GetTableQueryInfo(tableName, givenName); queryFrom.AddTable(new FromTableDirectSource(ignoreCase, tableQueryInfo, uniqueKey, givenName, tableName)); } } // Set up functions, aliases and exposed variables for this from set, foreach (var selectColumn in expression.SelectColumns) { // Is this a glob? (eg. Part.* ) if (selectColumn.IsGlob) { // Find the columns globbed and add to the 'selectedColumns' result. if (selectColumn.IsAll) { queryFrom.ExposeAllColumns(); } else { // Otherwise the glob must be of the form '[table name].*' queryFrom.ExposeColumns(selectColumn.TableName); } } else { // Otherwise must be a standard column reference. Note that at this // time we aren't sure if a column expression is correlated and is // referencing an outer source. This means we can't verify if the // column expression is valid or not at this point. // If this column is aliased, add it as a function reference to the // select expression string alias = selectColumn.Alias; var v = selectColumn.Expression.AsReferenceName(); bool aliasMatchV = (v != null && alias != null && queryFrom.CompareStrings(v.Name, alias)); if (alias != null && !aliasMatchV) { queryFrom.AddExpression(new ExpressionReference(selectColumn.Expression, alias)); queryFrom.ExposeColumn(new ObjectName(alias)); } else if (v != null) { var resolved = queryFrom.ResolveReference(v); queryFrom.ExposeColumn(resolved ?? v); } else { string funName = selectColumn.Expression.ToString(); queryFrom.AddExpression(new ExpressionReference(selectColumn.Expression, funName)); queryFrom.ExposeColumn(new ObjectName(funName)); } } } return queryFrom; }
public static QueryExpressionFrom Create(IRequest context, SqlQueryExpression expression) { // Get the 'from_clause' from the table expression var fromClause = expression.FromClause; var ignoreCase = context.Query.IgnoreIdentifiersCase(); var queryFrom = new QueryExpressionFrom(ignoreCase); foreach (var fromTable in fromClause.AllTables) { var uniqueKey = fromTable.UniqueKey; var alias = fromTable.Alias; if (fromTable.IsSubQuery) { // eg. FROM ( SELECT id FROM Part ) var subQuery = fromTable.SubQuery; var subQueryFrom = Create(context, subQuery); // The aliased name of the table ObjectName aliasTableName = null; if (alias != null) { aliasTableName = new ObjectName(alias); } // Add to list of sub-query tables to add to command, queryFrom.AddTable(new FromTableSubQuerySource(ignoreCase, uniqueKey, subQuery, subQueryFrom, aliasTableName)); } else { // Else must be a standard command table, string name = fromTable.Name; // Resolve to full table name var tableName = context.Query.ResolveTableName(name); if (!context.Query.TableExists(tableName)) { throw new InvalidOperationException(String.Format("Table '{0}' was not found.", tableName)); } ObjectName givenName = null; if (alias != null) { givenName = new ObjectName(alias); } // Get the ITableQueryInfo object for this table name (aliased). ITableQueryInfo tableQueryInfo = context.Query.GetTableQueryInfo(tableName, givenName); queryFrom.AddTable(new FromTableDirectSource(ignoreCase, tableQueryInfo, uniqueKey, givenName, tableName)); } } // Set up functions, aliases and exposed variables for this from set, foreach (var selectColumn in expression.SelectColumns) { // Is this a glob? (eg. Part.* ) if (selectColumn.IsGlob) { // Find the columns globbed and add to the 'selectedColumns' result. if (selectColumn.IsAll) { queryFrom.ExposeAllColumns(); } else { // Otherwise the glob must be of the form '[table name].*' queryFrom.ExposeColumns(selectColumn.TableName); } } else { // Otherwise must be a standard column reference. Note that at this // time we aren't sure if a column expression is correlated and is // referencing an outer source. This means we can't verify if the // column expression is valid or not at this point. // If this column is aliased, add it as a function reference to the // select expression string alias = selectColumn.Alias; var v = selectColumn.Expression.AsReferenceName(); bool aliasMatchV = (v != null && alias != null && queryFrom.CompareStrings(v.Name, alias)); if (alias != null && !aliasMatchV) { queryFrom.AddExpression(new ExpressionReference(selectColumn.Expression, alias)); queryFrom.ExposeColumn(new ObjectName(alias)); } else if (v != null) { var resolved = queryFrom.ResolveReference(v); queryFrom.ExposeColumn(resolved ?? v); } else { string funName = selectColumn.Expression.ToString(); queryFrom.AddExpression(new ExpressionReference(selectColumn.Expression, funName)); queryFrom.ExposeColumn(new ObjectName(funName)); } } } return(queryFrom); }