Beispiel #1
0
        public static string EmitUpdateStatement(AstTableNode astTableNode, IEnumerable <TableColumnValueMapping> assignments, IEnumerable <TableColumnValueMapping> conditions)
        {
            var updateTemplate = new TemplatePlatformEmitter("SimpleUpdate");

            updateTemplate.Map("Table", astTableNode.SchemaQualifiedName);
            var assignmentStrings = new List <string>();

            foreach (var assignmentPair in assignments)
            {
                assignmentStrings.Add(String.Format(CultureInfo.InvariantCulture, "{0} {1} {2}", assignmentPair.ColumnName, assignmentPair.OperatorString, assignmentPair.ColumnValue));
            }

            updateTemplate.Map("ColumnValuePairs", FlattenStringList(assignmentStrings));

            var whereTemplate = new TemplatePlatformEmitter("SimpleWhere");
            var whereStrings  = new List <string>();

            foreach (var wherePair in conditions)
            {
                whereStrings.Add(String.Format(CultureInfo.InvariantCulture, "{0} {1} {2}", wherePair.ColumnName, wherePair.OperatorString, wherePair.ColumnValue));
            }

            whereTemplate.Map("ColumnValuePairs", FlattenStringList(whereStrings, " AND "));

            return(String.Format(CultureInfo.InvariantCulture, "{0} {1}", updateTemplate.Emit(), whereTemplate.Emit()));
        }
Beispiel #2
0
        private static List <string> EmitDefaultValueList(AstTableNode astTableNode)
        {
            var columnValues = new List <string>();

            foreach (AstTableColumnBaseNode column in astTableNode.Columns)
            {
                if (column.IsAssignable)
                {
                    if (!String.IsNullOrEmpty(column.Default))
                    {
                        columnValues.Add(column.Default);
                    }
                    else if (column.IsNullable)
                    {
                        columnValues.Add("NULL");
                    }
                    else
                    {
                        columnValues.Add(column.DefaultValue);
                    }
                }
            }

            return(columnValues);
        }
Beispiel #3
0
        public static void ValidateLateArrivingTable(AstTableNode table)
        {
            bool hasIdentity   = table.Keys.Any(item => item is AstTableIdentityNode);
            bool hasPrimaryKey = table.Keys.Any(item => item is AstTablePrimaryKeyNode);

            if (!hasIdentity ^ hasPrimaryKey)
            {
                MessageEngine.Trace(table, Severity.Error, "V0130", "To support Late Arriving, table {0} must provide either identity or primary key", table.Name);
            }

            bool foundEligibleKey = false;

            foreach (AstTableKeyBaseNode key in table.Keys)
            {
                if (key.Columns.Any(keyColumn => !keyColumn.Column.IsComputed))
                {
                    if (foundEligibleKey)
                    {
                        MessageEngine.Trace(table, Severity.Error, "V0131", "There can be at most one (primary, identity, unique) key that is based on non-computed columns for Late Arriving Table {0}", table.Name);
                    }

                    foundEligibleKey = true;
                }
            }

            foreach (AstTableColumnBaseNode column in table.Columns)
            {
                if (!column.IsNullable && String.IsNullOrEmpty(column.Default))
                {
                    MessageEngine.Trace(table, Severity.Error, "V0132", "Late Arriving Table {0} must have default values for all columns that are non-nullable.", table.Name);
                }
            }
        }
Beispiel #4
0
        public static void ValidateScdTable(AstTableNode table)
        {
            // TODO: Can we use identity or primary (or just primary)
            // TODO: Need to add check - For implicit invocation, the destination can not be an OLEDB destination.  A compile-time error will be emitted if so.
            bool hasIdentity   = table.Keys.Any(item => item is AstTableIdentityNode);
            bool hasPrimaryKey = table.Keys.Any(item => item is AstTablePrimaryKeyNode);

            if (!(hasIdentity ^ hasPrimaryKey))
            {
                MessageEngine.Trace(table, Severity.Error, "V0133", "To support Scd Columns, table {0} must provide either identity or primary key", table.Name);
            }

            // TODO: Should we be overwriting these? And do we need to recheck the table for Scd columns after rewriting?
            foreach (var keyColumn in table.PreferredKey.Columns)
            {
                keyColumn.Column.ScdType = ScdType.Key;
            }

            foreach (AstTableColumnBaseNode column in table.Columns)
            {
                if (column.IsAssignable && column.ScdType == ScdType.Update && !column.IsNullable && String.IsNullOrEmpty(column.Default))
                {
                    MessageEngine.Trace(table, Severity.Error, "V0134", "Non-nullable ScdType.Update columns in table {0} with Error or Historical columns must have default values. Provide a default value for column {1}", table.Name, column.Name);
                }
            }
        }
Beispiel #5
0
        public static string EmitSelectAllStatement(AstTableNode astTableNode, IEnumerable <string> columnNames)
        {
            var selectTemplate = new TemplatePlatformEmitter("SimpleSelect");

            selectTemplate.Map("Table", astTableNode.SchemaQualifiedName);
            selectTemplate.Map("Columns", FlattenStringList(columnNames));
            return(selectTemplate.Emit());
        }
        public StaticSourceTSqlEmitter(AstTableNode table)
        {
            _table = table;
            _defaultValueBuilder = new StringBuilder();
            _defaultValueEmitter = new TemplatePlatformEmitter("SimpleInsert");

            _columnNames   = new List <string>();
            _defaultValues = new List <string>();
        }
        private static void BuildChangePath(AstTableNode targetTable, IFrameworkItem parentItem, List <AstTransformationNode> workflowFragment, AstDataflowOutputPathNode scdChangePath)
        {
            // Change Path should only be built if we actually have a column that takes a Type-1 Update

            bool doUpdate = false;

            foreach (var column in targetTable.Columns)
            {
                if (column.IsAssignable && column.ScdType == ScdType.Update && !column.IsAutoGenerated)
                {
                    doUpdate = true;
                    break;
                }
            }
            if (doUpdate)
            {
                var changeCommand = new AstOleDBCommandNode(parentItem)
                {
                    Name       = Utility.NameCleanerAndUniqifier(targetTable.Name + "_ChangeCommand"),
                    Connection = targetTable.Connection
                };
                changeCommand.Query = new AstTransformationMappedQueryNode(changeCommand);
                int changeIndex = 0;
                var changeSetColumnValueMappings = new List <TableColumnValueMapping>();
                foreach (var column in targetTable.Columns)
                {
                    if (column.IsAssignable && column.ScdType == ScdType.Update && !column.IsAutoGenerated)
                    {
                        changeCommand.Query.Mappings.Add(new AstDataflowColumnMappingNode(changeCommand)
                        {
                            SourceName = column.Name, TargetName = String.Format(CultureInfo.InvariantCulture, "Param_{0}", changeIndex++)
                        });
                        changeSetColumnValueMappings.Add(new TableColumnValueMapping(column.Name, "?", MappingOperator.Assign));
                    }
                }

                var changeWhereColumnValueMappings = new List <TableColumnValueMapping>();
                foreach (var keyColumn in targetTable.PreferredKey.Columns)
                {
                    changeCommand.Query.Mappings.Add(new AstDataflowColumnMappingNode(changeCommand)
                    {
                        SourceName = keyColumn.Column.Name, TargetName = String.Format(CultureInfo.InvariantCulture, "Param_{0}", changeIndex++)
                    });
                    changeWhereColumnValueMappings.Add(new TableColumnValueMapping(keyColumn.Column.Name, "?", MappingOperator.CompareEqual));
                }

                changeWhereColumnValueMappings.Add(new TableColumnValueMapping("_scdTo", "NULL", MappingOperator.CompareIs));
                changeCommand.Query.Body = TableLowerer.EmitUpdateStatement(targetTable, changeSetColumnValueMappings, changeWhereColumnValueMappings);
                changeCommand.ValidateExternalMetadata = false;
                changeCommand.InputPath = new AstDataflowMappedInputPathNode(changeCommand)
                {
                    OutputPath = scdChangePath
                };

                workflowFragment.Add(changeCommand);
            }
        }
Beispiel #8
0
        public static IEnumerable <AstPackageNode> ProcessTableStaticSource(AstTableNode astTableNode)
        {
            var packageList = new List <AstPackageNode>();

            foreach (var source in astTableNode.Sources)
            {
                var staticSource = source as AstTableStaticSourceNode;
                if (staticSource != null && staticSource.Rows.Count > 0)
                {
                    var table = staticSource.ParentItem as AstTableNode;
                    if (table != null && staticSource.EmitMergePackage)
                    {
                        if (table.PreferredKey == null)
                        {
                            MessageEngine.Trace(table, Severity.Error, "L0110", "Table {0} does not contain a primary key and therefore cannot use Static Source Merging.  Add a primary key or set EmitMergePackage to false.", table.Name);
                        }

                        var package = new AstPackageNode(table.ParentItem)
                        {
                            Emit = table.Emit,
                            Log  = false,
                            Name = staticSource.Name,
                            PackageFolderSubpath = table.Name,
                            PackageType          = GetPackageType(table)
                        };

                        // Staging Container
                        var staging = new AstStagingContainerTaskNode(package)
                        {
                            Log  = false,
                            Name = Utility.NameCleanerAndUniqifier(source.Name + "_Stg"),
                        };

                        var stagingCloneTable = new AstTableCloneNode(staging)
                        {
                            Name =
                                String.Format(CultureInfo.InvariantCulture, "__{0}_Static", table.Name),
                            Connection = table.Connection,
                            Table      = table
                        };
                        staging.Tables.Add(stagingCloneTable);
                        CloneTableLowerer.LowerCloneTable(stagingCloneTable);

                        staging.Tasks.Add(CreateInsertExecuteSql(staticSource, staging, stagingCloneTable));
                        staging.Tasks.Add(CreateMergeTask(table, staging, stagingCloneTable));

                        package.Tasks.Add(staging);
                        packageList.Add(package);
                        staticSource.LoweredPackage = package;
                    }
                }
            }

            return(packageList);
        }
        private static void BuildLateArrivingPath(AstTableNode targetTable, IFrameworkItem parentItem, List <AstTransformationNode> workflowFragment, AstDataflowOutputPathNode scdLateArrivingPath)
        {
            var inferredCommand = new AstOleDBCommandNode(parentItem)
            {
                Name       = Utility.NameCleanerAndUniqifier(targetTable.Name + "_InferredCommand"),
                Connection = targetTable.Connection
            };

            inferredCommand.Query = new AstTransformationMappedQueryNode(inferredCommand);
            int inferredIndex = 0;
            var inferredSetColumnValueMappings = new List <TableColumnValueMapping>();

            foreach (var column in targetTable.Columns)
            {
                if (column.IsAssignable && !column.IsAutoGenerated)
                {
                    inferredCommand.Query.Mappings.Add(new AstDataflowColumnMappingNode(inferredCommand)
                    {
                        SourceName = column.Name, TargetName = String.Format(CultureInfo.InvariantCulture, "Param_{0}", inferredIndex++)
                    });
                    inferredSetColumnValueMappings.Add(new TableColumnValueMapping(column.Name, "?", MappingOperator.Assign));
                }
            }

            if (targetTable.LateArriving)
            {
                inferredSetColumnValueMappings.Add(new TableColumnValueMapping("_LateArrived", "NULL", MappingOperator.Assign));
            }

            var inferredWhereColumnValueMappings = new List <TableColumnValueMapping>();

            foreach (var keyColumn in targetTable.PreferredKey.Columns)
            {
                inferredCommand.Query.Mappings.Add(new AstDataflowColumnMappingNode(inferredCommand)
                {
                    SourceName = keyColumn.Column.Name, TargetName = String.Format(CultureInfo.InvariantCulture, "Param_{0}", inferredIndex++)
                });
                inferredWhereColumnValueMappings.Add(new TableColumnValueMapping(keyColumn.Column.Name, "?", MappingOperator.CompareEqual));
            }

            if (targetTable.LateArriving)
            {
                inferredWhereColumnValueMappings.Add(new TableColumnValueMapping("_LateArrived", "NULL", MappingOperator.CompareIsNot));
            }

            inferredCommand.Query.Body = TableLowerer.EmitUpdateStatement(targetTable, inferredSetColumnValueMappings, inferredWhereColumnValueMappings);
            inferredCommand.ValidateExternalMetadata = false;
            inferredCommand.InputPath = new AstDataflowMappedInputPathNode(inferredCommand)
            {
                OutputPath = scdLateArrivingPath
            };

            workflowFragment.Add(inferredCommand);
        }
        private static AstDataflowOutputPathNode BuildHistoricalSubpath(AstTableNode targetTable, IFrameworkItem parentItem, List <AstTransformationNode> workflowFragment, AstDataflowOutputPathNode scdHistoricalPath)
        {
            var historicalTransform = new AstDerivedColumnListNode(parentItem);

            historicalTransform.InputPath = new AstDataflowMappedInputPathNode(historicalTransform)
            {
                OutputPath = scdHistoricalPath
            };
            historicalTransform.Name = Utility.NameCleanerAndUniqifier(targetTable.Name + "_HistoricalDerivedColumns");
            historicalTransform.Columns.Add(new AstDerivedColumnNode(historicalTransform)
            {
                Name              = "_scdTo",
                Expression        = "(DT_DBTIMESTAMP2,7)(@[System::StartTime])",
                Scale             = 7,
                DerivedColumnType = ColumnType.DateTime2,
                ReplaceExisting   = false
            });
            workflowFragment.Add(historicalTransform);

            var historicalCommand = new AstOleDBCommandNode(parentItem)
            {
                Name       = Utility.NameCleanerAndUniqifier(targetTable.Name + "_HistoricalCommand"),
                Connection = targetTable.Connection
            };

            historicalCommand.Query = new AstTransformationMappedQueryNode(historicalCommand);

            var historicalSetColumnValueMappings   = new List <TableColumnValueMapping>();
            var historicalWhereColumnValueMappings = new List <TableColumnValueMapping>();

            historicalCommand.Query.Mappings.Add(new AstDataflowColumnMappingNode(historicalCommand)
            {
                SourceName = "_scdTo", TargetName = "Param_0"
            });
            historicalSetColumnValueMappings.Add(new TableColumnValueMapping("_scdTo", "?", MappingOperator.Assign));

            historicalWhereColumnValueMappings.Add(new TableColumnValueMapping("_scdTo", "NULL", MappingOperator.CompareIs));
            int historicalIndex = 1;

            foreach (var keyColumn in targetTable.PreferredKey.Columns)
            {
                historicalCommand.Query.Mappings.Add(new AstDataflowColumnMappingNode(historicalCommand)
                {
                    SourceName = keyColumn.Column.Name, TargetName = String.Format(CultureInfo.InvariantCulture, "Param_{0}", historicalIndex++)
                });
                historicalWhereColumnValueMappings.Add(new TableColumnValueMapping(keyColumn.Column.Name, "?", MappingOperator.CompareEqual));
            }

            historicalCommand.Query.Body = TableLowerer.EmitUpdateStatement(targetTable, historicalSetColumnValueMappings, historicalWhereColumnValueMappings);
            historicalCommand.ValidateExternalMetadata = false;
            workflowFragment.Add(historicalCommand);

            return(historicalCommand.OutputPath);
        }
Beispiel #11
0
    private static void TopoVisit(AstTableNode node, List <AstTableNode> outputList, List <AstTableNode> visitedList)
    {
        if (!visitedList.Contains(node))
        {
            visitedList.Add(node);
            foreach (var dependentTable in node.Columns.OfType <AstTableColumnTableReferenceNode>().Select(c => c.ForeignTable))
            {
                TopoVisit(dependentTable, outputList, visitedList);
            }

            outputList.Add(node);
        }
    }
Beispiel #12
0
        public static string GetPackageType(AstTableNode tableNode)
        {
            if (tableNode is AstDimensionNode)
            {
                return("Dimension");
            }

            if (tableNode is AstFactNode)
            {
                return("FactTable");
            }

            return("Table");
        }
Beispiel #13
0
        private static List <string> EmitColumnList(AstTableNode astTableNode, bool emitOnlyAssignable)
        {
            var columnNames = new List <string>();

            foreach (AstTableColumnBaseNode column in astTableNode.Columns)
            {
                if (!emitOnlyAssignable || column.IsAssignable)
                {
                    columnNames.Add(column.Name);
                }
            }

            return(columnNames);
        }
Beispiel #14
0
        public static void ProcessLateArrivingTable(AstTableNode astTableNode)
        {
            var lateArrivedColumn = new AstTableColumnNode(astTableNode)
            {
                Name = "_LateArrived", IsNullable = true, ColumnType = ColumnType.DateTime2, IsAutoGenerated = true
            };
            var markLateColumn = new AstTableColumnNode(astTableNode)
            {
                Name = "_IsLate", IsNullable = true, ColumnType = ColumnType.Boolean, IsAutoGenerated = true, Computed = "_LateArrived IS NOT NULL PERSISTED NOT NULL"
            };

            astTableNode.Columns.Add(lateArrivedColumn);
            astTableNode.Columns.Add(markLateColumn);
        }
Beispiel #15
0
        public AstTableNode GetFileSchema()
        {
            //default the schema to "File"
            AstSchemaNode astSchemaNode = new AstSchemaNode(null)
            {
                Name = "File",
                ForceDisableIncrementalChangeTracking = true
            };

            AstTableNode astTableNode = new AstTableNode(null)
            {
                Name   = this.Name,
                Schema = astSchemaNode,
                ForceDisableIncrementalChangeTracking = true
            };

            this.TableNode = astTableNode;

            Interrogator             i = new Interrogator();
            List <DestinationColumn> DestinationObject = i.ProcessFile(
                this.FilePath,
                this.ColumnDelimiter,
                this.FirstRowHeader,
                this.HeaderRowsToSkip,
                this.TextQualifier);

            foreach (DestinationColumn col in DestinationObject)
            {
                AstTableColumnNode currentColumn = new AstTableColumnNode(astTableNode)
                {
                    ForceDisableIncrementalChangeTracking = true
                };
                //set up the column
                currentColumn.Name = col.Name;
                if (col.MaxLength != null)
                {
                    currentColumn.Length = int.Parse(col.MaxLength.ToString());
                }
                if (col.Precision != null)
                {
                    currentColumn.Precision = int.Parse(col.Precision.ToString());
                }

                currentColumn.IsNullable = col.Nullable;
                //add the column to the table
                this.TableNode.Columns.Add(currentColumn);
            }

            return(this.TableNode);
        }
Beispiel #16
0
        public static string EmitInsertDefaultRowStatement(AstTableNode astTableNode)
        {
            string columnNames         = FlattenStringList(EmitColumnList(astTableNode, true));
            string columnDefaultValues = FlattenStringList(EmitDefaultValueList(astTableNode));

            if (columnDefaultValues.Length > 0)
            {
                var insertTemplate = new TemplatePlatformEmitter("SimpleInsert", astTableNode.SchemaQualifiedName, columnNames, columnDefaultValues);
                return(insertTemplate.Emit());
            }

            MessageEngine.Trace(astTableNode, Severity.Error, "V0142", "No assignable columns detected on table {0}", astTableNode.Name);

            throw new InvalidOperationException("No Assignable Columns Detected.");
        }
Beispiel #17
0
        private static string GetInsertStatements(AstTableNode table, AstTableStaticSourceNode staticSource)
        {
            var staticSourceEmitter = new StaticSourceTSqlEmitter(table);

            foreach (AstStaticSourceRowNode row in staticSource.Rows)
            {
                foreach (AstStaticSourceColumnValueNode columnValue in row.ColumnValues)
                {
                    staticSourceEmitter.AddDefaultValue(columnValue.Column.Name, columnValue.Value);
                }

                staticSourceEmitter.CompleteRow();
            }

            return(staticSourceEmitter.Emit());
        }
        public static void ProcessTableScdColumns(AstTableNode astTableNode)
        {
            AstLowererValidation.ValidateScdTable(astTableNode);

            bool emitScdColumns = astTableNode.Columns.Any(column => column.ScdType == ScdType.Historical);

            if (emitScdColumns)
            {
                var scdFromColumn = new AstTableColumnNode(astTableNode)
                {
                    Name = "_scdFrom", ColumnType = ColumnType.DateTime2, IsAutoGenerated = true
                };
                astTableNode.Columns.Add(scdFromColumn);

                var scdToColumn = new AstTableColumnNode(astTableNode)
                {
                    Name = "_scdTo", ColumnType = ColumnType.DateTime2, IsAutoGenerated = true
                };
                astTableNode.Columns.Add(scdToColumn);
            }
        }
Beispiel #19
0
        private static void BindTableReference(AstTableNode tableNode, string refName, AstTableNode refTable, bool nullable, ColumnsTSqlEmitter columnsEmitter)
        {
            // TODO: This is wrong in general.  We need to ensure that this is always a single column constraint
            AstTableKeyBaseNode primaryKey = refTable.PreferredKey;

            if (primaryKey == null)
            {
                MessageEngine.Trace(tableNode, Severity.Warning, "V0243", "Table {0} lacks a primary, identity, or unique key", tableNode.Name);
                return;
            }

            // TODO: We currently support only a single primary key column.  This should be fixed :)
            foreach (AstTableKeyColumnNode keyCol in primaryKey.Columns)
            {
                string type = TSqlTypeTranslator.Translate(
                    keyCol.Column.ColumnType,
                    keyCol.Column.Length,
                    keyCol.Column.Precision,
                    keyCol.Column.Scale,
                    keyCol.Column.CustomType);
                columnsEmitter.AddColumn(refName, type, false, 0, 0, nullable, keyCol.Column.Default, false, String.Empty);
            }
        }
        private static void BuildInsertPath(AstTableNode targetTable, IFrameworkItem parentItem, List <AstTransformationNode> workflowFragment, AstDataflowOutputPathNode scdInsertPath)
        {
            var insertTransform = new AstDerivedColumnListNode(parentItem)
            {
                Name = Utility.NameCleanerAndUniqifier(targetTable.Name + "_InsertDerivedColumns")
            };

            insertTransform.InputPath = new AstDataflowMappedInputPathNode(insertTransform)
            {
                OutputPath = scdInsertPath
            };
            insertTransform.Columns.Add(new AstDerivedColumnNode(insertTransform)
            {
                Name              = "_scdFrom",
                Expression        = "(DT_DBTIMESTAMP2,7)(@[System::StartTime])",
                Scale             = 7,
                DerivedColumnType = ColumnType.DateTime2,
                ReplaceExisting   = false
            });
            insertTransform.Columns.Add(new AstDerivedColumnNode(insertTransform)
            {
                Name              = "_scdTo",
                Expression        = "NULL(DT_DBTIMESTAMP2,7)",
                Scale             = 7,
                DerivedColumnType = ColumnType.DateTime2,
                ReplaceExisting   = false
            });
            workflowFragment.Add(insertTransform);

            var insertDestination = new AstDestinationNode(parentItem);

            insertDestination.Table      = targetTable;
            insertDestination.DisableScd = true;
            insertDestination.ValidateExternalMetadata = false;
            insertDestination.Name = Utility.NameCleanerAndUniqifier(targetTable.Name + "_InsertDestination");
            workflowFragment.Add(insertDestination);
        }
Beispiel #21
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);
        }
    public static AstTableNode ToAstTableNode(this DataTable dataTable)
    {
        var schema = new AstSchemaNode(null);
        var table  = new AstTableNode(null);

        schema.Name  = dataTable.Rows.OfType <DataRow>().Select(r => r["TABLE_SCHEMA"].ToString()).First();
        table.Schema = schema;
        table.Name   = dataTable.Rows.OfType <DataRow>().Select(r => r["TABLE_NAME"].ToString()).First();
        foreach (DataRow row in dataTable.Rows)
        {
            var column = new AstTableColumnNode(table)
            {
                Name       = row["COLUMN_NAME"].ToString(),
                DataType   = row["DATA_TYPE"].ToString().GetDbType(),
                IsNullable = Convert.ToBoolean(row["IS_NULLABLE"].ToString().Replace("YES", "true").Replace("NO", "false"))
            };
            if (!row.IsNull("CHARACTER_MAXIMUM_LENGTH"))
            {
                column.Length = Convert.ToInt32(row["CHARACTER_MAXIMUM_LENGTH"]);
            }

            if (!row.IsNull("NUMERIC_PRECISION"))
            {
                column.Precision = Convert.ToInt32(row["NUMERIC_PRECISION"]);
            }

            if (!row.IsNull("NUMERIC_SCALE"))
            {
                column.Precision = Convert.ToInt32(row["NUMERIC_SCALE"]);
            }

            table.Columns.Add(column);
        }

        return(table);
    }
Beispiel #23
0
        public static AstPackageNode ProcessTable(AstTableNode tableNode)
        {
            string packageTypeName = "Table";

            if (tableNode is AstDimensionNode)
            {
                packageTypeName = "Dimension";
            }
            else if (tableNode is AstFactNode)
            {
                packageTypeName = "FactTable";
            }

            // TODO: Fix this null parent node
            var packageNode = new AstPackageNode(tableNode.ParentItem);

            packageNode.Name        = tableNode.Name;
            packageNode.PackageType = packageTypeName;
            packageNode.Emit        = tableNode.Emit;

            LowerTable(packageNode, tableNode, tableNode.SchemaQualifiedName, false);

            return(packageNode);
        }
Beispiel #24
0
        public static AstExecuteSqlTaskNode CreateInsertExecuteSql(AstTableStaticSourceNode staticSource, IFrameworkItem insertParent, AstTableNode insertTargetTable)
        {
            var executeSql = new AstExecuteSqlTaskNode(insertParent)
            {
                Connection = insertTargetTable.Connection,
                ExecuteDuringDesignTime = false,
                Name = Utility.NameCleanerAndUniqifier(insertTargetTable + "_Insert"),
            };

            executeSql.Query = new AstExecuteSqlQueryNode(executeSql)
            {
                Body      = GetInsertStatements(insertTargetTable, staticSource),
                QueryType = QueryType.Standard
            };
            return(executeSql);
        }
Beispiel #25
0
        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));
                    }
                }
            }
        }
        private static List <AstTransformationNode> CreateScdWorkflowFragment(AstTableNode targetTable, IFrameworkItem parentItem, AstDataflowOutputPathNode outputPath)
        {
            var workflowFragment = new List <AstTransformationNode>();

            AstTableColumnBaseNode lateArrivingStatusColumn = targetTable.Columns.FirstOrDefault(item => item.Name == "_IsLate");

            var scd = new AstSlowlyChangingDimensionNode(parentItem);

            scd.Name                       = Utility.NameCleanerAndUniqifier(targetTable.Name + "_scd");
            scd.Connection                 = targetTable.Connection;
            scd.CurrentRowWhere            = "[_scdFrom] IS NOT NULL AND [_scdFrom] IS NULL";
            scd.EnableInferredMember       = targetTable.LateArriving;
            scd.FailOnFixedAttributeChange = true;
            scd.FailOnLookupFailure        = false;
            scd.IncomingRowChangeType      = 1;
            scd.InferredMemberIndicator    = lateArrivingStatusColumn;

            // TODO:
            foreach (var column in targetTable.Columns)
            {
                if (column.IsAssignable && !column.IsAutoGenerated)
                {
                    ScdColumnMappingType mappingType;
                    switch (column.ScdType)
                    {
                    case ScdType.Error:
                        mappingType = ScdColumnMappingType.FixedAttribute;
                        break;

                    case ScdType.Historical:
                        mappingType = ScdColumnMappingType.HistoricalAttribute;
                        break;

                    case ScdType.Key:
                        mappingType = ScdColumnMappingType.Key;
                        break;

                    case ScdType.Other:
                        mappingType = ScdColumnMappingType.Other;
                        break;

                    case ScdType.Update:
                        mappingType = ScdColumnMappingType.ChangingAttribute;
                        break;

                    default:
                        mappingType = ScdColumnMappingType.Other;
                        break;
                    }

                    scd.Mappings.Add(new AstScdTypeColumnMappingNode(scd)
                    {
                        MappingType = mappingType, QueryColumnName = column.Name
                    });
                }
            }

            scd.Query = TableLowerer.EmitSelectAllStatement(targetTable);
            if (outputPath != null)
            {
                scd.InputPath = new AstDataflowMappedInputPathNode(scd)
                {
                    OutputPath = outputPath
                };
            }

            workflowFragment.Add(scd);

            // Late Arriving Path
            if (targetTable.LateArriving)
            {
                BuildLateArrivingPath(targetTable, parentItem, workflowFragment, scd.InferredMemberPath);
            }

            // Change Path
            BuildChangePath(targetTable, parentItem, workflowFragment, scd.ChangingAttributePath);

            // Historical Path
            var historicalOutput = BuildHistoricalSubpath(targetTable, parentItem, workflowFragment, scd.HistoricalAttributePath);

            // Union Historical and New Paths
            var insertUnionAll = new AstUnionAllNode(parentItem)
            {
                Name = Utility.NameCleanerAndUniqifier(targetTable.Name + "_InsertUnionAll")
            };

            insertUnionAll.InputPaths.Add(new AstDataflowMappedInputPathNode(insertUnionAll)
            {
                OutputPath = scd.NewPath
            });
            insertUnionAll.InputPaths.Add(new AstDataflowMappedInputPathNode(insertUnionAll)
            {
                OutputPath = historicalOutput
            });
            workflowFragment.Add(insertUnionAll);

            // Insert Path
            BuildInsertPath(targetTable, parentItem, workflowFragment, insertUnionAll.OutputPath);

            return(workflowFragment);
        }
Beispiel #27
0
        public static string EmitSelectAllStatement(AstTableNode astTableNode)
        {
            var columnNames = EmitColumnList(astTableNode, false);

            return(EmitSelectAllStatement(astTableNode, columnNames));
        }
Beispiel #28
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>
             */
        }
Beispiel #29
0
        // This needs its own emitter
        private static void ProcessAstTableColumnBaseNode(AstTableNode tableNode, ColumnsTSqlEmitter columnsEmitter, AstTableColumnBaseNode columnBase)
        {
            var tableReference = columnBase as AstTableColumnTableReferenceNode;
            var dimReference   = columnBase as AstTableColumnDimensionReferenceNode;
            var hashKey        = columnBase as AstTableHashedKeyColumnNode;

            if (hashKey != null)
            {
                var hashBytesBuilder = new StringBuilder();
                foreach (AstTableKeyColumnNode keyColumn in hashKey.Constraint.Columns)
                {
                    string expression = "+ HASHBYTES('SHA1',{0})";
                    switch (keyColumn.Column.ColumnType)
                    {
                    case ColumnType.AnsiString:
                    case ColumnType.AnsiStringFixedLength:
                    case ColumnType.String:
                    case ColumnType.StringFixedLength:
                        expression = String.Format(CultureInfo.InvariantCulture, expression, String.Format(CultureInfo.InvariantCulture, "UPPER(RTRIM(LTRIM([{0}])))", keyColumn.Column.Name));
                        break;

                    case ColumnType.Int16:
                    case ColumnType.Int32:
                    case ColumnType.Int64:
                    case ColumnType.UInt16:
                    case ColumnType.UInt32:
                    case ColumnType.UInt64:
                        expression = String.Format(CultureInfo.InvariantCulture, expression, String.Format(CultureInfo.InvariantCulture, "CONVERT(binary varying(64),{0})", keyColumn.Column.Name));
                        break;

                    default:
                        expression = String.Format(CultureInfo.InvariantCulture, expression, keyColumn.Column.Name);
                        break;
                    }

                    hashBytesBuilder.Append(expression);
                }

                string hashExpression = String.Format(CultureInfo.InvariantCulture, "(CONVERT(varbinary(32),HASHBYTES('SHA1',{0})))", hashBytesBuilder.ToString().Substring(1));
                hashExpression = String.Format(CultureInfo.InvariantCulture, "{0} PERSISTED NOT NULL UNIQUE", hashExpression);
                columnsEmitter.AddColumn(hashKey.Name, null, false, 0, 0, true, string.Empty, true, hashExpression);
            }
            else if (tableReference != null)
            {
                BindTableReference(tableNode, tableReference.Name, tableReference.Table, tableReference.IsNullable, columnsEmitter);
            }
            else if (dimReference != null)
            {
                BindTableReference(tableNode, dimReference.Name, dimReference.Dimension, dimReference.IsNullable, columnsEmitter);
            }
            else if (columnBase != null)
            {
                string type      = TSqlTypeTranslator.Translate(columnBase.ColumnType, columnBase.Length, columnBase.Precision, columnBase.Scale, columnBase.CustomType);
                bool   identity  = false;
                int    seed      = 1;
                int    increment = 1;
                foreach (AstTableKeyBaseNode keyBase in tableNode.Keys)
                {
                    var identityNode = keyBase as AstTableIdentityNode;
                    if (identityNode != null)
                    {
                        foreach (AstTableKeyColumnNode keyColNode in identityNode.Columns)
                        {
                            if (keyColNode.Column.Name.Equals(columnBase.Name, StringComparison.OrdinalIgnoreCase))
                            {
                                identity  = true;
                                seed      = identityNode.Seed;
                                increment = identityNode.Increment;
                            }
                        }
                    }
                }

                columnsEmitter.AddColumn(columnBase.Name, type, identity, seed, increment, columnBase.IsNullable, columnBase.Default, columnBase.IsComputed, columnBase.Computed);
            }
        }