Esempio n. 1
0
        // TODO: Is this the right approach for events and precedence constraints?  Should we have a utility method to handle them?
        public static void ProcessMerge(AstMergeTaskNode mergeNode)
        {
            var executeSqlNode = new AstExecuteSqlTaskNode(mergeNode.ParentItem)
            {
                Name = mergeNode.Name,
                ExecuteDuringDesignTime = false,
                Connection      = ((AstTableNode)mergeNode.TargetConstraint.ParentItem).Connection,
                ResultSet       = ExecuteSqlResultSet.None,
                DelayValidation = mergeNode.DelayValidation,
                IsolationLevel  = mergeNode.IsolationLevel
            };

            executeSqlNode.Query = new AstExecuteSqlQueryNode(executeSqlNode)
            {
                QueryType = QueryType.Standard, Body = new MergeTSqlEmitter(mergeNode).Emit()
            };

            executeSqlNode.PrecedenceConstraints = mergeNode.PrecedenceConstraints;
            if (executeSqlNode.PrecedenceConstraints != null)
            {
                executeSqlNode.PrecedenceConstraints.ParentItem = executeSqlNode;
            }

            foreach (var eventHandler in mergeNode.Events)
            {
                executeSqlNode.Events.Add(eventHandler);
                eventHandler.ParentItem = executeSqlNode;
            }

            var parentContainer = mergeNode.ParentItem as AstContainerTaskNode;

            if (parentContainer != null)
            {
                parentContainer.Tasks.Replace(mergeNode, executeSqlNode);
            }
        }
Esempio n. 2
0
        private static AstMergeTaskNode CreateMergeTask(AstTableNode table, AstStagingContainerTaskNode staging, AstTableCloneNode stagingCloneTable)
        {
            var merge = new AstMergeTaskNode(staging)
            {
                Name             = Utility.NameCleanerAndUniqifier(table + "_SSMerge"),
                SourceTable      = stagingCloneTable,
                TargetConstraint = stagingCloneTable.Table.PreferredKey,
                UnspecifiedColumnDefaultUsageType = MergeColumnUsage.CompareUpdateInsert
            };

            // Detect identity keys, if so add an insert- merge-column-usage for said key
            foreach (var columnRef in stagingCloneTable.Table.PreferredKey.Columns)
            {
                if (columnRef.Column.IsIdentityColumn)
                {
                    merge.Columns.Add(new AstMergeColumnNode(merge)
                    {
                        ColumnName = columnRef.Column.Name, ColumnUsage = MergeColumnUsage.Insert
                    });
                }
            }

            return(merge);
        }
Esempio n. 3
0
        private AstIR ProcessTableQuerySources(AstIR astIR)
        {
            List <AstTableNode> tables = new List <AstTableNode>();

            tables.AddRange(astIR.AstRootNode.Dimensions.Cast <AstTableNode>());
            tables.AddRange(astIR.AstRootNode.Facts.Cast <AstTableNode>());
            tables.AddRange(astIR.AstRootNode.Tables);

            foreach (AstTableNode table in tables)
            {
                foreach (AstTableQuerySourceNode querySource in table.Sources.OfType <AstTableQuerySourceNode>())
                {
                    AstPackageNode package = new AstPackageNode();
                    package.ConstraintMode  = ContainerConstraintMode.Linear;
                    package.DefaultPlatform = PlatformType.SSIS08;
                    package.Log             = false;
                    package.Name            = querySource.Name;
                    package.Type            = "ETL";

                    AstStagingContainerTaskNode staging = new AstStagingContainerTaskNode();
                    staging.ConstraintMode    = ContainerConstraintMode.Linear;
                    staging.Log               = false;
                    staging.Name              = querySource.Name;
                    staging.CreateAs          = String.Format("__Staging_{0}_{1}", table.Name, querySource.Name);
                    staging.StagingConnection = table.Connection;
                    staging.Table             = table;

                    AstETLRootNode etl = new AstETLRootNode();
                    etl.Name            = String.Format("__ETL_Staging_{0}_{1}", table.Name, querySource.Name);
                    etl.DelayValidation = true;

                    AstQuerySourceNode source = new AstQuerySourceNode();
                    source.Connection = querySource.Connection;
                    source.Name       = String.Format("__ETL_Staging_Source_{0}_{1}", table.Name, querySource.Name);
                    source.Query      = querySource.Query;
                    etl.Transformations.Add(source);

                    AstDestinationNode destination = new AstDestinationNode();
                    destination.AccessMode               = DestinationAccessModeFacet.TableFastLoad;
                    destination.CheckConstraints         = true;
                    destination.TableLock                = true;
                    destination.Connection               = table.Connection;
                    destination.Name                     = String.Format("__ETL_Staging_Destination_{0}_{1}", table.Name, querySource.Name);
                    destination.TableName                = staging.CreateAs;
                    destination.ValidateExternalMetadata = false;
                    etl.Transformations.Add(destination);

                    staging.Tasks.Add(etl);

                    AstMergeTaskNode merge = new AstMergeTaskNode();
                    merge.Connection       = table.Connection;
                    merge.Name             = String.Format("__Staging_Merge_{0}_{1}", table.Name, querySource.Name);
                    merge.SourceName       = staging.CreateAs;
                    merge.TargetConstraint = table.PreferredKey;

                    staging.Tasks.Add(merge);

                    package.Tasks.Add(staging);

                    astIR.AstRootNode.Packages.Add(package);
                }
            }
            return(astIR);
        }
Esempio n. 4
0
        public string Emit(AstMergeTaskNode mergeTask)
        {
            StringBuilder joinBuilder = new StringBuilder();

            for (int i = 0; i < mergeTask.TargetConstraint.Columns.Count; i++)
            {
                joinBuilder.AppendFormat("TARGET.{0} = SOURCE.{0}", mergeTask.TargetConstraint.Columns[i].Column.Name);
                if (i < mergeTask.TargetConstraint.Columns.Count - 1)
                {
                    joinBuilder.AppendFormat("\nAND\n");
                }
            }

            StringBuilder notEqualBuilder    = new StringBuilder();
            StringBuilder updateBuilder      = new StringBuilder();
            StringBuilder insertParamBuilder = new StringBuilder();
            StringBuilder insertValueBuilder = new StringBuilder();

            AstTableNode targetTable = AstWalker.FirstParent <AstTableNode>(mergeTask.TargetConstraint);

            Hashtable columnUsageMapping = new Hashtable();

            foreach (AstTableColumnBaseNode column in targetTable.Columns)
            {
                if (column.IsAssignable)
                {
                    foreach (AstMergeColumnNode mergeColumn in mergeTask.Columns)
                    {
                        if (mergeColumn.ColumnName.ToUpperInvariant() == column.Name.ToUpperInvariant())
                        {
                            columnUsageMapping.Add(column.Name, mergeColumn.ColumnUsage);
                            break;
                        }
                    }
                    if (!columnUsageMapping.ContainsKey(column.Name))
                    {
                        columnUsageMapping.Add(column.Name, mergeTask.UnspecifiedColumnDefaultUsageType);
                    }
                }
            }

            bool firstNotEqual = true;
            bool firstUpdate   = true;
            bool firstInsert   = true;

            foreach (AstTableColumnBaseNode column in targetTable.Columns)
            {
                if (column.IsAssignable)
                {
                    if (columnUsageMapping[column.Name].ToString().ToUpperInvariant().Contains("COMPARE"))
                    {
                        if (firstNotEqual)
                        {
                            firstNotEqual = false;
                        }
                        else
                        {
                            notEqualBuilder.AppendFormat("\nOR\n");
                        }

                        // Bug #3757, special handling for uniqueidentifier data type
                        if (column.CustomType != null && column.CustomType.ToLowerInvariant().CompareTo("uniqueidentifier") == 0)
                        {
                            notEqualBuilder.AppendFormat("COALESCE(TARGET.[{0}],CONVERT(uniqueidentifier,'00000000-0000-0000-0000-000000000000')) <> COALESCE(SOURCE.[{0}],CONVERT(uniqueidentifier,'00000000-0000-0000-0000-000000000000'))", column.Name);
                        }
                        else
                        {
                            notEqualBuilder.AppendFormat("COALESCE(TARGET.[{0}],'') <> COALESCE(SOURCE.[{0}],'')", column.Name);
                        }
                    }

                    if (columnUsageMapping[column.Name].ToString().ToUpperInvariant().Contains("UPDATE"))
                    {
                        if (firstUpdate)
                        {
                            firstUpdate = false;
                        }
                        else
                        {
                            updateBuilder.AppendFormat(",");
                        }

                        updateBuilder.AppendFormat("TARGET.[{0}] = SOURCE.[{0}]", column.Name);
                    }

                    if (firstInsert)
                    {
                        firstInsert = false;
                    }
                    else
                    {
                        insertParamBuilder.AppendFormat(",\n");
                        insertValueBuilder.AppendFormat(",\n");
                    }

                    insertParamBuilder.AppendFormat("[{0}]", column.Name);
                    insertValueBuilder.AppendFormat("SOURCE.[{0}]", column.Name);
                }
            }

            TemplatePlatformEmitter te;

            if (mergeTask.UpdateTargetTable)
            {
                te = new TemplatePlatformEmitter("Merge", mergeTask.SourceName, targetTable.Name, joinBuilder.ToString(), notEqualBuilder.ToString(), updateBuilder.ToString(), insertParamBuilder.ToString(), insertValueBuilder.ToString());
            }
            else
            {
                te = new TemplatePlatformEmitter("MergeWithoutUpdate", mergeTask.SourceName, targetTable.Name, joinBuilder.ToString(), insertParamBuilder.ToString(), insertValueBuilder.ToString());
            }
            return(te.Emit(null));

            /*
             * <Template Name="Merge">
             * <Map Source="Source" Index="0"/>
             * <Map Source="Target" Index="1"/>
             * <Map Source="Join" Index="2"/>
             * <Map Source="NotEqualCheck" Index="3"/>
             * <Map Source="Update" Index="4"/>
             * <Map Source="Insert" Index="5"/>
             * <TemplateData>
             */
        }