protected Schema.Keys KeyProduct(Schema.Keys keys, Schema.Key key) { Schema.Keys result = new Schema.Keys(); foreach (Schema.Key localKey in keys) { foreach (Schema.TableVarColumn newColumn in key.Columns) { Schema.Key newKey = new Schema.Key(); newKey.Columns.AddRange(localKey.Columns); newKey.Columns.Add(newColumn); result.Add(newKey); } } return(result); }
public override void DetermineDataType(Plan plan) { DetermineModifiers(plan); _dataType = new Schema.TableType(); _tableVar = new Schema.ResultTableVar(this); _tableVar.Owner = plan.User; _tableVar.InheritMetaData(SourceTableVar.MetaData); CopyTableVarColumns(SourceTableVar.Columns); _extendColumnOffset = TableVar.Columns.Count; // This structure will track key columns as a set of sets, and any extended columns that are equivalent to them Dictionary <string, Schema.Key> keyColumns = new Dictionary <string, Schema.Key>(); foreach (Schema.TableVarColumn tableVarColumn in TableVar.Columns) { if (SourceTableVar.Keys.IsKeyColumnName(tableVarColumn.Name) && !keyColumns.ContainsKey(tableVarColumn.Name)) { keyColumns.Add(tableVarColumn.Name, new Schema.Key(new Schema.TableVarColumn[] { tableVarColumn })); } } ApplicationTransaction transaction = null; if (plan.ApplicationTransactionID != Guid.Empty) { transaction = plan.GetApplicationTransaction(); } try { if (transaction != null) { transaction.PushLookup(); } try { plan.PushCursorContext(new CursorContext(CursorType.Dynamic, CursorCapability.Navigable, CursorIsolation.None)); try { plan.EnterRowContext(); try { plan.Symbols.Push(new Symbol(String.Empty, SourceTableType.RowType)); try { // Add a column for each expression PlanNode planNode; Schema.TableVarColumn newColumn; foreach (NamedColumnExpression column in _expressions) { newColumn = new Schema.TableVarColumn(new Schema.Column(column.ColumnAlias, plan.DataTypes.SystemScalar)); plan.PushCreationObject(newColumn); try { planNode = Compiler.CompileExpression(plan, column.Expression); } finally { plan.PopCreationObject(); } bool isChangeRemotable = true; if (newColumn.HasDependencies()) { for (int index = 0; index < newColumn.Dependencies.Count; index++) { Schema.Object objectValue = newColumn.Dependencies.ResolveObject(plan.CatalogDeviceSession, index); isChangeRemotable = isChangeRemotable && objectValue.IsRemotable; plan.AttachDependency(objectValue); } } bool isUpdatable = planNode is TableNode || planNode is ExtractRowNode; newColumn = new Schema.TableVarColumn ( new Schema.Column(column.ColumnAlias, planNode.DataType), column.MetaData, isUpdatable ? Schema.TableVarColumnType.Stored : Schema.TableVarColumnType.Virtual ); newColumn.IsNilable = planNode.IsNilable; newColumn.IsChangeRemotable = isChangeRemotable; newColumn.IsDefaultRemotable = isChangeRemotable; DataType.Columns.Add(newColumn.Column); TableVar.Columns.Add(newColumn); string columnName = String.Empty; if (IsColumnReferencing(planNode, ref columnName)) { // TODO: In theory we could allow updatability through an IsColumnReferencing add column as well Schema.TableVarColumn referencedColumn = TableVar.Columns[columnName]; if (SourceTableVar.Keys.IsKeyColumnName(referencedColumn.Name)) { Schema.Key key; if (keyColumns.TryGetValue(referencedColumn.Name, out key)) { key.Columns.Add(newColumn); } else { keyColumns.Add(referencedColumn.Name, new Schema.Key(new Schema.TableVarColumn[] { newColumn })); } } } Nodes.Add(planNode); } DetermineRemotable(plan); } finally { plan.Symbols.Pop(); } } finally { plan.ExitRowContext(); } } finally { plan.PopCursorContext(); } } finally { if (transaction != null) { transaction.PopLookup(); } } } finally { if (transaction != null) { Monitor.Exit(transaction); } } foreach (Schema.Key key in SourceTableVar.Keys) { // Seed the result key set with the empty set Schema.Keys resultKeys = new Schema.Keys(); resultKeys.Add(new Schema.Key()); foreach (Schema.TableVarColumn column in key.Columns) { resultKeys = KeyProduct(resultKeys, keyColumns[column.Name]); } foreach (Schema.Key resultKey in resultKeys) { resultKey.IsSparse = key.IsSparse; resultKey.IsInherited = true; resultKey.MergeMetaData(key.MetaData); TableVar.Keys.Add(resultKey); } } CopyOrders(SourceTableVar.Orders); if (SourceNode.Order != null) { Order = CopyOrder(SourceNode.Order); } #if UseReferenceDerivation #if UseElaborable if (plan.CursorContext.CursorCapabilities.HasFlag(CursorCapability.Elaborable)) #endif CopyReferences(plan, SourceTableVar); #endif }