public GroupNode(IQueryPlanNode child, ObjectName[] columnNames, ObjectName groupMaxColumn, SqlExpression[] functions, string[] names) : base(child) { ColumnNames = columnNames; GroupMaxColumn = groupMaxColumn; Functions = functions; Names = names; }
public JoinNode(IQueryPlanNode left, IQueryPlanNode right, ObjectName leftVar, Operator joinOp, Expression rightExpression) : base(left, right) { this.leftVar = leftVar; this.joinOp = joinOp; this.rightExpression = rightExpression; }
public SortNode(IQueryPlanNode child, ObjectName[] columnNames, bool[] ascending) : base(child) { // How we handle ascending/descending order // ---------------------------------------- // Internally to the database, all columns are naturally ordered in // ascending order (start at lowest and end on highest). When a column // is ordered in descending order, a fast way to achieve this is to take // the ascending set and reverse it. This works for single columns, // however some thought is required for handling multiple column. We // order columns from RHS to LHS. If LHS is descending then this will // order the RHS incorrectly if we leave as is. Therefore, we must do // some pre-processing that looks ahead on any descending orders and // reverses the order of the columns to the right. This pre-processing // is done in the first pass. int sz = ascending.Length; for (int n = 0; n < sz - 1; ++n) { if (!ascending[n]) { // if descending... // Reverse order of all columns to the right... for (int p = n + 1; p < sz; ++p) { ascending[p] = !ascending[p]; } } } ColumnNames = columnNames; Ascending = ascending; }
internal Prepared(ObjectName tableName, IQueryPlanNode queryPlan, SqlAssignExpression[] columns, int limit) { TableName = tableName; QueryPlan = queryPlan; Columns = columns; Limit = limit; }
public JoinNode(IQueryPlanNode left, IQueryPlanNode right, ObjectName leftColumnName, SqlExpressionType @operator, SqlExpression rightExpression) : base(left, right) { LeftColumnName = leftColumnName; Operator = @operator; RightExpression = rightExpression; }
internal Prepared(ObjectName tableName, ObjectName[] columnNames, int[] columnIndices, IQueryPlanNode queryPlan) { TableName = tableName; ColumnNames = columnNames; QueryPlan = queryPlan; ColumnIndices = columnIndices; }
public static int UpdateTable(this IQuery context, ObjectName tableName, IQueryPlanNode queryPlan, IEnumerable <SqlAssignExpression> assignments, int limit) { var columnNames = assignments.Select(x => x.ReferenceExpression) .Cast <SqlReferenceExpression>() .Select(x => x.ReferenceName.Name).ToArray(); if (!context.UserCanUpdateTable(tableName, columnNames)) { throw new MissingPrivilegesException(context.UserName(), tableName, Privileges.Update); } if (!context.UserCanSelectFromPlan(queryPlan)) { throw new InvalidOperationException(); } var table = context.GetMutableTable(tableName); if (table == null) { throw new ObjectNotFoundException(tableName); } var updateSet = queryPlan.Evaluate(context); return(table.Update(context, updateSet, assignments, limit)); }
public SimpleSelectNode(IQueryPlanNode child, ObjectName columnName, SqlExpressionType op, SqlExpression expression) : base(child) { ColumnName = columnName; OperatorType = op; Expression = expression; }
public void AddPlan(IQueryPlanNode plan, IFromTableSource tableSource) { var columns = tableSource.ColumnNames; var uniqueNames = new[] { tableSource.UniqueName }; AddPlan(new TablePlan(plan, columns, uniqueNames)); }
public ITable Evaluate(IRequest context) { IQueryPlanNode node = CreateChildNode(context); var t = node.Evaluate(context); return(AliasName != null ? new ReferenceTable(t, AliasName) : t); }
public SimpleSelectNode(IQueryPlanNode child, ObjectName columnName, SqlExpressionType op, SqlExpression expression) : base(child) { ColumnName = columnName; OperatorType = op; Expression = expression; }
public SortNode(IQueryPlanNode child, ObjectName[] columnNames, bool[] ascending) : base(child) { // How we handle ascending/descending order // ---------------------------------------- // Internally to the database, all columns are naturally ordered in // ascending order (start at lowest and end on highest). When a column // is ordered in descending order, a fast way to achieve this is to take // the ascending set and reverse it. This works for single columns, // however some thought is required for handling multiple column. We // order columns from RHS to LHS. If LHS is descending then this will // order the RHS incorrectly if we leave as is. Therefore, we must do // some pre-processing that looks ahead on any descending orders and // reverses the order of the columns to the right. This pre-processing // is done in the first pass. int sz = ascending.Length; for (int n = 0; n < sz - 1; ++n) { if (!ascending[n]) // if descending... // Reverse order of all columns to the right... { for (int p = n + 1; p < sz; ++p) { ascending[p] = !ascending[p]; } } } ColumnNames = columnNames; Ascending = ascending; }
public SimpleSelectNode(IQueryPlanNode child, ObjectName leftVar, Operator op, Expression rightExpression) : base(child) { this.leftVar = leftVar; this.op = op; this.rightExpression = rightExpression; }
public NonCorrelatedAnyAllNode(IQueryPlanNode left, IQueryPlanNode right, ObjectName[] leftColumnNames, SqlExpressionType subQueryType, bool isAll) : base(left, right) { LeftColumnNames = leftColumnNames; SubQueryType = subQueryType; IsAll = isAll; }
protected virtual IQueryPlanNode VisitNode(IQueryPlanNode node) { if (node is SingleQueryPlanNode) { return(VisitSingle((SingleQueryPlanNode)node)); } if (node is BranchQueryPlanNode) { return(VisitBranch((BranchQueryPlanNode)node)); } if (node is FetchTableNode) { return(VisitFetchTable((FetchTableNode)node)); } if (node is FetchViewNode) { return(VisitFetchView((FetchViewNode)node)); } if (node is SingleRowTableNode) { return(VisitSingleRowTable((SingleRowTableNode)node)); } throw new NotSupportedException(); }
public JoinNode(IQueryPlanNode left, IQueryPlanNode right, ObjectName leftVar, Operator joinOp, Expression rightExpression) : base(left, right) { this.leftVar = leftVar; this.joinOp = joinOp; this.rightExpression = rightExpression; }
public JoinNode(IQueryPlanNode left, IQueryPlanNode right, ObjectName leftColumnName, SqlExpressionType @operator, SqlExpression rightExpression) : base(left, right) { LeftColumnName = leftColumnName; Operator = @operator; RightExpression = rightExpression; }
public NonCorrelatedAnyAllNode(IQueryPlanNode left, IQueryPlanNode right, ObjectName[] leftColumnNames, SqlExpressionType subQueryType, bool isAll) : base(left, right) { LeftColumnNames = leftColumnNames; SubQueryType = subQueryType; IsAll = isAll; }
public SimpleSelectNode(IQueryPlanNode child, ObjectName leftVar, Operator op, Expression rightExpression) : base(child) { this.leftVar = leftVar; this.op = op; this.rightExpression = rightExpression; }
internal Prepared(ObjectName viewName, SqlQueryExpression queryExpression, IQueryPlanNode queryPlan, bool replaceIfExists) { ViewName = viewName; QueryPlan = queryPlan; ReplaceIfExists = replaceIfExists; QueryExpression = queryExpression; }
/// <summary> /// Groups over the given columns from the child. /// </summary> /// <param name="child"></param> /// <param name="columns"></param> /// <param name="groupMaxColumn"></param> /// <param name="functionList"></param> /// <param name="nameList"></param> public GroupNode(IQueryPlanNode child, ObjectName[] columns, ObjectName groupMaxColumn, Expression[] functionList, string[] nameList) : base(child) { this.columns = columns; this.groupMaxColumn = groupMaxColumn; this.functionList = functionList; this.nameList = nameList; }
public CachePointNode(IQueryPlanNode child) : base(child) { lock (GlobLock) { id = ((int)DateTime.Now.Ticks << 16) | (GlobId & 0x0FFFF); ++GlobId; } }
public CachePointNode(IQueryPlanNode child) : base(child) { lock (GlobLock) { id = ((int) DateTime.Now.Ticks << 16) | (GlobId & 0x0FFFF); ++GlobId; } }
public GroupNode(IQueryPlanNode child, ObjectName[] columnNames, ObjectName groupMaxColumn, SqlExpression[] functions, string[] names) : base(child) { ColumnNames = columnNames; GroupMaxColumn = groupMaxColumn; Functions = functions; Names = names; }
public static SqlBinary AsBinary(this IQueryPlanNode planNode, ISystemContext context) { using (var memoryStream = new MemoryStream()) { context.SerializeQueryPlan(planNode, memoryStream); memoryStream.Flush(); return(new SqlBinary(memoryStream.ToArray())); } }
/// <summary> /// Groups over the given columns from the child. /// </summary> /// <param name="child"></param> /// <param name="columns"></param> /// <param name="groupMaxColumn"></param> /// <param name="functionList"></param> /// <param name="nameList"></param> public GroupNode(IQueryPlanNode child, ObjectName[] columns, ObjectName groupMaxColumn, Expression[] functionList, string[] nameList) : base(child) { this.columns = columns; this.groupMaxColumn = groupMaxColumn; this.functionList = functionList; this.nameList = nameList; }
// How this plan is naturally joined to other plans in the source. A // plan either has no dependance, a left or a right dependance, or a left // and right dependance. public PlanTableSource(IQueryPlanNode plan, ObjectName[] variables, string[] uniqueNames) { Plan = plan; VariableNames = variables; UniqueNames = uniqueNames; LeftJoinType = JoinType.None; RightJoinType = JoinType.None; IsUpdated = false; }
// How this plan is naturally joined to other plans in the source. A // plan either has no dependance, a left or a right dependance, or a left // and right dependance. public PlanTableSource(IQueryPlanNode plan, ObjectName[] variables, string[] uniqueNames) { Plan = plan; VariableNames = variables; UniqueNames = uniqueNames; LeftJoinType = JoinType.None; RightJoinType = JoinType.None; IsUpdated = false; }
public static SqlBinary AsBinary(this IQueryPlanNode planNode) { using (var memoryStream = new MemoryStream()) { var serializaer = new BinarySerializer(); serializaer.Serialize(memoryStream, planNode); memoryStream.Flush(); return(new SqlBinary(memoryStream.ToArray())); } }
/// <inheritdoc/> public virtual ITable Evaluate(IQueryContext context) { // Create the view child node IQueryPlanNode node = CreateViewChildNode(context); // Evaluate the plan ITable t = node.Evaluate(context); return(aliasName != null ? new ReferenceTable((Table)t, aliasName) : t); }
public void AddSelect(IQueryPlanNode queryPlan) { // TODO: the current implementation returns table names and view names with no distinction var accessedResources = queryPlan.DiscoverAccessedResources(); foreach (var resource in accessedResources) { AddSelect(resource.ResourceName, resource.ResourceType); } }
public static void DefineView(this IQuery context, ObjectName viewName, IQueryPlanNode queryPlan, bool replaceIfExists) { // We have to execute the plan to get the TableInfo that represents the // result of the view execution. var table = queryPlan.Evaluate(context); var tableInfo = table.TableInfo.Alias(viewName); var viewInfo = new ViewInfo(tableInfo, null, queryPlan); context.DefineView(viewInfo, replaceIfExists); }
protected override DataObject OnEvaluate(IExpressionEvaluator evaluator) { // Generate the TableExpressionFromSet hierarchy for the expression, TableExpressionFromSet fromSet = Planner.GenerateFromSet(SelectExpression, evaluator.Context.QueryContext.Connection); // Form the plan IQueryPlanNode plan = Planner.FormQueryPlan(evaluator.Context.QueryContext.Connection, SelectExpression, fromSet, new List <ByColumn>()); return(new DataObject(PrimitiveTypes.Query(), plan)); }
public static void DefineView(this IQuery context, ObjectName viewName, IQueryPlanNode queryPlan, bool replaceIfExists) { // We have to execute the plan to get the TableInfo that represents the // result of the view execution. var table = queryPlan.Evaluate(context); var tableInfo = table.TableInfo.Alias(viewName); var viewInfo = new ViewInfo(tableInfo, null, queryPlan); context.DefineView(viewInfo, replaceIfExists); }
public ViewInfo(TableInfo tableInfo, SqlQueryExpression queryExpression, IQueryPlanNode queryPlan) { if (tableInfo == null) throw new ArgumentNullException("tableInfo"); if (queryExpression == null) throw new ArgumentNullException("queryExpression"); TableInfo = tableInfo; QueryExpression = queryExpression; QueryPlan = queryPlan; }
public Expression Prepare(Expression expression) { TableSelectExpression sqlExpr = ((QueryExpression)expression).SelectExpression; TableExpressionFromSet sqlFromSet = GenerateFromSet(sqlExpr, db); sqlFromSet.Parent = fromSet; IQueryPlanNode sqlPlan = FormQueryPlan(db, sqlExpr, sqlFromSet, null); // Form this into a command plan type return(Expression.Constant(new DataObject(PrimitiveTypes.Query(), new CachePointNode(sqlPlan)))); }
public static void Serialize(IQueryPlanNode queryPlan, BinaryWriter writer) { var nodeType = queryPlan.GetType(); var seriializer = Resolver.ResolveSerializer(nodeType) as IObjectBinarySerializer; if (seriializer == null) { throw new InvalidOperationException(String.Format("Could not find any serializer for type '{0}'.", nodeType)); } seriializer.Serialize(queryPlan, writer); }
private static IQueryPlanNode PlanGroup(IQueryPlanNode node, QuerySelectColumnSet columnSet, ObjectName groupmaxColumn, int gsz, ObjectName[] groupByList, IList <Expression> groupByFunctions, int fsz, string[] defFunNames, Expression[] defFunList) { // If there is more than 1 aggregate function or there is a group by // clause, then we must add a grouping plan. if (columnSet.AggregateCount > 0 || gsz > 0) { // If there is no GROUP BY clause then assume the entire result is the // group. if (gsz == 0) { node = new GroupNode(node, groupmaxColumn, defFunList, defFunNames); } else { // Do we have any group by functions that need to be planned first? int gfsz = groupByFunctions.Count; if (gfsz > 0) { var groupFunList = new Expression[gfsz]; var groupFunName = new String[gfsz]; for (int i = 0; i < gfsz; ++i) { groupFunList[i] = groupByFunctions[i]; groupFunName[i] = "#GROUPBY-" + i; } node = new CreateFunctionsNode(node, groupFunList, groupFunName); } // Otherwise we provide the 'group_by_list' argument node = new GroupNode(node, groupByList, groupmaxColumn, defFunList, defFunNames); } } else { // Otherwise no grouping is occuring. We simply need create a function // node with any functions defined in the SELECT. // Plan a FunctionsNode with the functions defined in the SELECT. if (fsz > 0) { node = new CreateFunctionsNode(node, defFunList, defFunNames); } } return(node); }
public TablePlan(IQueryPlanNode plan, ObjectName[] columnNames, string[] uniqueNames) { if (plan == null) throw new ArgumentNullException("plan"); if (columnNames == null) throw new ArgumentNullException("columnNames"); Plan = plan; ColumnNames = columnNames; UniqueNames = uniqueNames; LeftJoinType = JoinType.None; RightJoinType = JoinType.None; IsUpdated = false; }
public static void SerializeQueryPlan(this ISystemContext context, IQueryPlanNode node, BinaryWriter writer) { var nodeType = node.GetType(); var serializers = context.ResolveAllServices<IQueryPlanNodeSerializer>(); foreach (var serializer in serializers) { if (serializer.CanSerialize(nodeType)) { serializer.Serialize(node, writer); return; } } throw new InvalidOperationException(string.Format("Could not find any serializer for node type '{0}'.", nodeType)); }
private static QueryTableSetPlanner SetupPlanners(IDatabaseConnection db, TableExpressionFromSet fromSet) { // Set up plans for each table in the from clause of the command. For // sub-queries, we recurse. var tablePlanner = new QueryTableSetPlanner(); for (int i = 0; i < fromSet.SetCount; ++i) { IFromTableSource table = fromSet.GetTable(i); if (table is FromTableSubQuerySource) { // This represents a sub-command in the FROM clause var sqlTable = (FromTableSubQuerySource)table; TableSelectExpression sqlExpr = sqlTable.TableExpression; TableExpressionFromSet sqlFromSet = sqlTable.FromSet; // Form a plan for evaluating the sub-command FROM IQueryPlanNode sqlPlan = FormQueryPlan(db, sqlExpr, sqlFromSet, null); // The top should always be a SubsetNode, if (sqlPlan is SubsetNode) { var subsetNode = (SubsetNode)sqlPlan; subsetNode.SetGivenName(sqlTable.AliasedName); } else { throw new Exception("Top plan is not a SubsetNode!"); } tablePlanner.AddTableSource(sqlPlan, sqlTable); } else if (table is FromTableDirectSource) { // This represents a direct referencable table in the FROM clause var dsTable = (FromTableDirectSource)table; IQueryPlanNode dsPlan = dsTable.CreateFetchQueryPlanNode(); tablePlanner.AddTableSource(dsPlan, dsTable); } else { throw new Exception("Unknown table source instance: " + table.GetType()); } } return(tablePlanner); }
private static void WriteChildNode(BinaryWriter writer, IQueryPlanNode node) { if (node == null) { writer.Write((byte)0); } else { var nodeTypeString = node.GetType().FullName; writer.Write((byte)1); writer.Write(nodeTypeString); Serialize(node, writer); } }
public ViewInfo(TableInfo tableInfo, SqlQueryExpression queryExpression, IQueryPlanNode queryPlan) { if (tableInfo == null) { throw new ArgumentNullException("tableInfo"); } if (queryExpression == null) { throw new ArgumentNullException("queryExpression"); } TableInfo = tableInfo; QueryExpression = queryExpression; QueryPlan = queryPlan; }
private void CheckUserSelectPermissions(IQueryContext context, IQueryPlanNode plan) { // Discover the list of TableName objects this command touches, IList <ObjectName> touchedTables = plan.DiscoverTableNames(new List <ObjectName>()); IDatabase dbase = context.Connection.Database; /* * TODO: * // Check that the user is allowed to select from these tables. * foreach (ObjectName table in touchedTables) { * if (!dbase.CanUserSelectFromTableObject(context, table, null)) * throw new UserAccessException("User not permitted to select from table: " + table); * } */ }
public static int UpdateTable(this IQuery context, ObjectName tableName, IQueryPlanNode queryPlan, IEnumerable<SqlAssignExpression> assignments, int limit) { var columnNames = assignments.Select(x => x.ReferenceExpression) .Cast<SqlReferenceExpression>() .Select(x => x.ReferenceName.Name).ToArray(); if (!context.UserCanUpdateTable(tableName, columnNames)) throw new MissingPrivilegesException(context.UserName(), tableName, Privileges.Update); if (!context.UserCanSelectFromPlan(queryPlan)) throw new InvalidOperationException(); var table = context.GetMutableTable(tableName); if (table == null) throw new ObjectNotFoundException(tableName); var updateSet = queryPlan.Evaluate(context); return table.Update(context, updateSet, assignments, limit); }
protected SingleQueryPlanNode(IQueryPlanNode child) { Child = child; }
public CachePointNode(IQueryPlanNode child, long id) : base(child) { Id = id; }
public CachePointNode(IQueryPlanNode child) : this(child,NewId()) { }
public SimplePatternSelectNode(IQueryPlanNode child, SqlExpression expression) : base(child) { Expression = expression; }
private TablePlan MergePlans(TablePlan left, TablePlan right, IQueryPlanNode mergePlan) { // Remove the sources from the table list. tablePlans.Remove(left); tablePlans.Remove(right); // Add the concatenation of the left and right tables. var newPlan = ConcatPlans(left, right, mergePlan); newPlan.MergeJoin(left, right); newPlan.SetUpdated(); AddPlan(newPlan); return newPlan; }
public SubsetNode(IQueryPlanNode child, ObjectName[] originalColumns, ObjectName[] newColumnNames) : base(child) { this.originalColumns = originalColumns; this.newColumnNames = newColumnNames; }
public GroupNode(IQueryPlanNode child, ObjectName groupMaxColumn, SqlExpression[] functions, string[] names) : this(child, new ObjectName[0], groupMaxColumn, functions, names) { }
public CompositeNode(IQueryPlanNode left, IQueryPlanNode right, CompositeFunction compositeOp, bool allOp) : base(left, right) { CompositeFunction = compositeOp; All = allOp; }
public void AddPlan(IQueryPlanNode plan, IFromTableSource tableSource) { var columns = tableSource.ColumnNames; var uniqueNames = new[] {tableSource.UniqueName}; AddPlan(new TablePlan(plan, columns, uniqueNames)); }
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 IQueryPlanNode PlanGroup(IQueryPlanNode node, GroupInfo groupInfo) { // If there is more than 1 aggregate function or there is a group by // clause, then we must add a grouping plan. if (groupInfo.Columns.AggregateCount > 0 || groupInfo.GroupByCount > 0) { // If there is no GROUP BY clause then assume the entire result is the // group. if (groupInfo.GroupByCount == 0) { node = new GroupNode(node, groupInfo.GroupMax, groupInfo.FunctionExpressions, groupInfo.FunctionNames); } else { // Do we have any group by functions that need to be planned first? int gfsz = groupInfo.GroupByExpressions.Length; if (gfsz > 0) { var groupFunList = new SqlExpression[gfsz]; var groupFunName = new string[gfsz]; for (int i = 0; i < gfsz; ++i) { groupFunList[i] = groupInfo.GroupByExpressions[i]; groupFunName[i] = "#GROUPBY-" + i; } node = new CreateFunctionsNode(node, groupFunList, groupFunName); } // Otherwise we provide the 'group_by_list' argument node = new GroupNode(node, groupInfo.GroupByNames, groupInfo.GroupMax, groupInfo.FunctionExpressions, groupInfo.FunctionNames); } } else { // Otherwise no grouping is occurring. We simply need create a function // node with any functions defined in the SELECT. // Plan a FunctionsNode with the functions defined in the SELECT. if (groupInfo.FunctionCount > 0) node = new CreateFunctionsNode(node, groupInfo.FunctionExpressions, groupInfo.FunctionNames); } return node; }
public DistinctNode(IQueryPlanNode child, ObjectName[] columnNames) : base(child) { ColumnNames = columnNames; }
public CreateFunctionsNode(IQueryPlanNode child, SqlExpression[] functionList, string[] nameList) : base(child) { Functions = functionList; Names = nameList; }
public ExhaustiveSelectNode(IQueryPlanNode child, SqlExpression exp) : base(child) { Expression = exp; }
public LeftOuterJoinNode(IQueryPlanNode child, string markerName) : base(child) { MarkerName = markerName; }