private static void ComputeRootsAndSuccessors(AstTask.AstContainerTaskNode container, IEnumerable <AstTaskNode> unsortedTransformations, HashSet <AstTaskNode> roots, Dictionary <AstTaskNode, ICollection <AstTaskNode> > successors) { AstTaskNode previousTransformation = null; foreach (var transformation in unsortedTransformations) { HashSet <AstTaskNode> predecessors = FindPredecessors(container, transformation, previousTransformation, successors); if (predecessors.Count == 0) { roots.Add(transformation); } foreach (var predecessor in predecessors) { if (!successors.ContainsKey(predecessor)) { successors.Add(predecessor, new HashSet <AstTaskNode>()); } successors[predecessor].Add(transformation); } previousTransformation = transformation; } }
private static List <AstTaskNode> SortTasks(AstTask.AstContainerTaskNode container, IEnumerable <AstTaskNode> unsortedTasks) { var roots = new HashSet <AstTaskNode>(); var successors = new Dictionary <AstTaskNode, ICollection <AstTaskNode> >(); ComputeRootsAndSuccessors(container, unsortedTasks, roots, successors); return(FlowSorter.TopologicalSort(roots, successors)); }
// TODO: We've made the call to just use the staging node as the lowered container rather than creating a new one and copying everything over public static void ProcessContainers(SymbolTable symbolTable) { var snapshotSymbolTable = new List<IReferenceableItem>(symbolTable); foreach (var astNamedNode in snapshotSymbolTable) { var stagingNode = astNamedNode as AstStagingContainerTaskNode; if (stagingNode != null && astNamedNode.FirstThisOrParent<ITemplate>() == null) { var stagingCreateContainer = new AstContainerTaskNode(stagingNode) { Name = String.Format(CultureInfo.InvariantCulture, Properties.Resources.CreateStaging, stagingNode.Name), Log = false, }; var stagingDropContainer = new AstContainerTaskNode(stagingNode) { Name = String.Format(CultureInfo.InvariantCulture, Properties.Resources.DropStaging, stagingNode.Name), Log = false, }; stagingNode.Tasks.Insert(0, stagingCreateContainer); stagingNode.Tasks.Add(stagingDropContainer); foreach (var baseTable in stagingNode.Tables) { var table = baseTable as AstTableNode; if (table != null) { TableLowerer.LowerTable( stagingCreateContainer, table, String.Format(CultureInfo.InvariantCulture, Properties.Resources.CreateStagingTable, table.Name), stagingNode.ExecuteDuringDesignTime); var dropStagingTemplate = new TemplatePlatformEmitter("DropStagingTable", table.SchemaQualifiedName); var dropTableExecuteSqlTask = new AstExecuteSqlTaskNode(stagingNode) { Name = StringManipulation.NameCleanerAndUniqifier(String.Format(CultureInfo.InvariantCulture, Properties.Resources.DropStagingTable, table.Name)), Connection = table.Connection, ExecuteDuringDesignTime = stagingNode.ExecuteDuringDesignTime, }; dropTableExecuteSqlTask.Query = new AstExecuteSqlQueryNode(dropTableExecuteSqlTask) { QueryType = QueryType.Standard, Body = dropStagingTemplate.Emit() }; stagingDropContainer.Tasks.Add(dropTableExecuteSqlTask); } else { throw new System.NotSupportedException("AstLowering - StagingContainer - a Table Template node was found when lowering staging containers and I don't know what to do with it."); } } } } }
private static void LowerChildren(AstTask.AstContainerTaskNode container, LoweringContext context) { foreach (AstTask.AstVariableNode variable in container.Variables) { PhysicalLoweringProcessor.Lower(variable, context); } var sortedTasks = SortTasks(container, container.Tasks); foreach (AstTask.AstTaskNode task in sortedTasks) { PhysicalLoweringProcessor.Lower(task, context); } }
private static void _packageBuildOnEndEvent(AstPackageBaseNode package) { var packageEvent = ContainerFindEvent(package.Events, EventType.OnPostExecute); if (packageEvent == null) { packageEvent = new AstTaskEventHandlerNode(package) { EventType = EventType.OnPostExecute }; package.Events.Add(packageEvent); } var postExecContainer = new AstContainerTaskNode(packageEvent) { Name = "OnPostExec", ConstraintMode = ContainerConstraintMode.Linear }; packageEvent.Tasks.Insert(0, postExecContainer); var constrainedCont = new AstContainerTaskNode(packageEvent) { Name = "ConstrainedContainer", ConstraintMode = ContainerConstraintMode.Parallel }; postExecContainer.Tasks.Add(constrainedCont); var executeSql = new AstExecuteSqlTaskNode(postExecContainer) { Name = "Exec usp_PackageEnd", ExecuteDuringDesignTime = false, Connection = package.LogConnection }; executeSql.PrecedenceConstraints = new AstTaskflowPrecedenceConstraintsNode(executeSql); executeSql.PrecedenceConstraints.Inputs.Add( new AstTaskflowInputPathNode(executeSql.PrecedenceConstraints) { Expression = "@[System::PackageID] == @[System::SourceID]", EvaluationOperation = TaskEvaluationOperationType.Expression, OutputPath = constrainedCont.OutputPath }); executeSql.Query = new AstExecuteSqlQueryNode(executeSql) { Body = "\"EXEC usp_PackageEnd \" + (@[System::PackageName] == \"\" ? \"NULL\" : \"'\"+@[System::PackageName]+\"'\") +\",\"+(@[System::PackageID] == \"\" ? \"NULL\" : \"'\"+@[System::PackageID]+\"'\") +\",\"+(@[User::_parentPackageGuid] == \"\" ? \"NULL\" : \"'\"+@[User::_parentPackageGuid]+\"'\") +\",\"+(@[System::SourceName] == \"\" ? \"NULL\" : \"'\"+@[System::SourceName]+\"'\") +\",\"+(@[System::SourceID] == \"\" ? \"NULL\" : \"'\"+@[System::SourceID]+\"'\") +\",\"+(@[System::SourceParentGUID] == \"\" ? \"NULL\" : \"'\"+@[System::SourceParentGUID]+\"'\") +\",\"+ (@[System::MachineName] == \"\" ? \"NULL\" : \"'\"+@[System::MachineName]+\"'\") +\",\"+(@[System::UserName] == \"\" ? \"NULL\" : \"'\"+@[System::UserName]+\"'\") +\",\"+(@[User::_patchedExecutionGuid] == \"\" ? \"NULL\" : \"'\"+@[User::_patchedExecutionGuid])+\"'\"", QueryType = QueryType.Expression }; postExecContainer.Tasks.Add(executeSql); }
private static HashSet <AstTaskNode> FindPredecessors(AstTask.AstContainerTaskNode container, AstTaskNode task, AstTaskNode previousTask, Dictionary <AstTaskNode, ICollection <AstTaskNode> > successors) { var predecessors = new HashSet <AstTaskNode>(); if (task.PrecedenceConstraints != null) { foreach (var input in task.PrecedenceConstraints.Inputs) { if (input.OutputPath != null) { var predecessorNode = input.OutputPath.ParentItem as AstTaskNode; predecessors.Add(predecessorNode); } } } //if (containerTask != null && containerTask.ConstraintMode == ContainerConstraintMode.Linear && predecessors.Count == 0 && previousTask != null) if (container.ConstraintMode == ContainerConstraintMode.Linear && predecessors.Count == 0 && previousTask != null) { predecessors.Add(previousTask); } return(predecessors); }
protected Container(AstContainerTaskNode astNode) : base(astNode) { DelayValidation = astNode.DelayValidation; switch (astNode.IsolationLevel) { case IsolationLevel.Chaos: ContainerIsolationLevel = System.Data.IsolationLevel.Chaos; break; case IsolationLevel.ReadCommitted: ContainerIsolationLevel = System.Data.IsolationLevel.ReadCommitted; break; case IsolationLevel.ReadUncommitted: ContainerIsolationLevel = System.Data.IsolationLevel.ReadUncommitted; break; case IsolationLevel.RepeatableRead: ContainerIsolationLevel = System.Data.IsolationLevel.RepeatableRead; break; case IsolationLevel.Serializable: ContainerIsolationLevel = System.Data.IsolationLevel.Serializable; break; case IsolationLevel.Snapshot: ContainerIsolationLevel = System.Data.IsolationLevel.Snapshot; break; case IsolationLevel.Unspecified: ContainerIsolationLevel = System.Data.IsolationLevel.Unspecified; break; default: ContainerIsolationLevel = System.Data.IsolationLevel.Serializable; break; } switch (astNode.ConstraintMode) { case VulcanEngine.IR.Ast.Task.ContainerConstraintMode.Linear: ConstraintMode = ContainerConstraintMode.Linear; break; case VulcanEngine.IR.Ast.Task.ContainerConstraintMode.Parallel: ConstraintMode = ContainerConstraintMode.Parallel; break; default: ConstraintMode = ContainerConstraintMode.Linear; break; } switch (astNode.TransactionMode) { case ContainerTransactionMode.StartOrJoin: TransactionMode = "Required"; if (astNode.ConstraintMode == VulcanEngine.IR.Ast.Task.ContainerConstraintMode.Parallel) { VulcanEngine.Common.MessageEngine.Trace( astNode, Severity.Alert, "CT001", "Container {0} has ConstraintMode of {1} and TransactionOption of {2}. SSIS does not support transactions when the package flow is not linear. Please configure precedence constraints appropriately for this scenario.", astNode.Name, astNode.ConstraintMode, astNode.TransactionMode); } break; case ContainerTransactionMode.Join: TransactionMode = "Supported"; break; case ContainerTransactionMode.NoTransaction: TransactionMode = "NotSupported"; break; default: TransactionMode = "Supported"; break; } }
internal static void LowerTable(AstContainerTaskNode containerNode, AstTableNode tableNode, string executeSqlTaskName, bool executeDuringDesignTime) { var tableEmitter = new TableTSqlEmitter(tableNode.SchemaQualifiedName, tableNode.CompressionType.ToString().ToUpper(CultureInfo.InvariantCulture)); foreach (AstTableColumnBaseNode columnBase in tableNode.Columns) { ProcessAstTableColumnBaseNode(tableNode, tableEmitter.ColumnsEmitter, columnBase); var tableReference = columnBase as AstTableColumnTableReferenceNode; var dimReference = columnBase as AstTableColumnDimensionReferenceNode; if (tableReference != null && tableReference.EnforceForeignKeyConstraint) { tableEmitter.ConstraintsEmitter.AppendForeignKeyConstraintFromReference(tableNode, tableReference.ForeignKeyNameOverride, tableReference.Name, tableReference.Table); } if (dimReference != null && dimReference.EnforceForeignKeyConstraint) { tableEmitter.ConstraintsEmitter.AppendForeignKeyConstraintFromReference(tableNode, dimReference.ForeignKeyNameOverride, dimReference.Name, dimReference.Dimension); } } foreach (AstTableKeyBaseNode keyBase in tableNode.Keys) { tableEmitter.ConstraintsEmitter.AppendConstraint(keyBase); } foreach (AstTableIndexNode index in tableNode.Indexes) { tableEmitter.ConstraintsEmitter.AppendIndex(tableNode.SchemaQualifiedName, index); } // TODO: Fix this null parent node var createTableExecuteSqlTaskNode = new AstExecuteSqlTaskNode(containerNode) { Name = StringManipulation.NameCleanerAndUniqifier(executeSqlTaskName), ResultSet = ExecuteSqlResultSet.None, Connection = tableNode.Connection, ExecuteDuringDesignTime = executeDuringDesignTime }; createTableExecuteSqlTaskNode.Query = new AstExecuteSqlQueryNode(createTableExecuteSqlTaskNode) { QueryType = QueryType.Standard, Body = tableEmitter.Emit() }; containerNode.Tasks.Add(createTableExecuteSqlTaskNode); bool hasPermissions = false; var permissionBuilder = new StringBuilder(); foreach (var permission in tableNode.Permissions) { hasPermissions = true; permissionBuilder.AppendLine(PermissionsLowerer.ProcessPermission(tableNode, permission)); } foreach (var column in tableNode.Columns) { foreach (var permission in column.Permissions) { hasPermissions = true; permissionBuilder.AppendLine(PermissionsLowerer.ProcessPermission(column, permission)); } } if (hasPermissions) { var permissionsExecuteSqlTask = new AstExecuteSqlTaskNode(containerNode) { Name = "__SetPermissions", Connection = tableNode.Connection, }; permissionsExecuteSqlTask.Query = new AstExecuteSqlQueryNode(permissionsExecuteSqlTask) { Body = permissionBuilder.ToString(), QueryType = QueryType.Standard }; containerNode.Tasks.Add(permissionsExecuteSqlTask); } if (tableNode.CustomExtensions != null) { containerNode.Tasks.Add(tableNode.CustomExtensions); } foreach (var source in tableNode.Sources) { var staticSource = source as AstTableStaticSourceNode; if (staticSource != null && staticSource.Rows.Count > 0) { if (staticSource.EmitMergePackage) { // TODO: This is nasty - we need a way to reference packages and emit paths at lowering time var executeMergePackage = new AstExecutePackageTaskNode(containerNode); executeMergePackage.Name = "__ExecuteMergePackage"; executeMergePackage.Package = staticSource.LoweredPackage; containerNode.Tasks.Add(executeMergePackage); } else { containerNode.Tasks.Add(StaticSourcesLowerer.CreateInsertExecuteSql(staticSource, containerNode, tableNode)); } } } }