Exemple #1
0
        public void NowTestDataInsertion(DatabaseType dbType)
        {
            AlterTest_InvalidThenRecreateItAndItsValidAgain(dbType);

            _table.Insert(new Dictionary <string, object>
            {
                { "name", "Franky" },
                { "bubbles", 3 },
                { "hic_validFrom", new DateTime(2001, 1, 2) },
                { "hic_dataLoadRunID", 7 }
            });


            RunSQL("UPDATE {0} set bubbles =99", _table.GetFullyQualifiedName());

            //new value is 99
            Assert.AreEqual(99, ExecuteScalar("Select bubbles FROM {0} where name = 'Franky'", _table.GetFullyQualifiedName()));
            //archived value is 3
            Assert.AreEqual(3, ExecuteScalar("Select bubbles FROM {0} where name = 'Franky'", _archiveTable.GetFullyQualifiedName()));

            //Legacy table valued function only works for MicrosoftSQLServer
            if (dbType == DatabaseType.MicrosoftSQLServer)
            {
                //legacy in 2001-01-01 it didn't exist
                Assert.IsNull(ExecuteScalar("Select bubbles FROM TriggerTests_Legacy('2001-01-01') where name = 'Franky'"));
                //legacy in 2001-01-03 it did exist and was 3
                Assert.AreEqual(3, ExecuteScalar("Select bubbles FROM TriggerTests_Legacy('2001-01-03') where name = 'Franky'"));
                //legacy boundary case?
                Assert.AreEqual(3, ExecuteScalar("Select bubbles FROM TriggerTests_Legacy('2001-01-02') where name = 'Franky'"));

                //legacy today it is 99
                Assert.AreEqual(99, ExecuteScalar("Select bubbles FROM TriggerTests_Legacy(GETDATE()) where name = 'Franky'"));
            }
        }
        public override void DropTable(DbConnection connection, DiscoveredTable tableToDrop)
        {
            SqlCommand cmd;

            switch (tableToDrop.TableType)
            {
            case TableType.View:
                if (connection.Database != tableToDrop.Database.GetRuntimeName())
                {
                    connection.ChangeDatabase(tableToDrop.GetRuntimeName());
                }

                if (!connection.Database.ToLower().Equals(tableToDrop.Database.GetRuntimeName().ToLower()))
                {
                    throw new NotSupportedException("Cannot drop view " + tableToDrop + " because it exists in database " + tableToDrop.Database.GetRuntimeName() + " while the current current database connection is pointed at database:" + connection.Database + " (use .ChangeDatabase on the connection first) - SQL Server does not support cross database view dropping");
                }

                cmd = new SqlCommand("DROP VIEW " + tableToDrop.GetRuntimeName(), (SqlConnection)connection);
                break;

            case TableType.Table:
                cmd = new SqlCommand("DROP TABLE " + tableToDrop.GetFullyQualifiedName(), (SqlConnection)connection);
                break;

            case TableType.TableValuedFunction:
                DropFunction(connection, (DiscoveredTableValuedFunction)tableToDrop);
                return;

            default:
                throw new ArgumentOutOfRangeException();
            }

            using (cmd)
                cmd.ExecuteNonQuery();
        }
        protected override string GetRenameTableSql(DiscoveredTable discoveredTable, string newName)
        {
            var syntax = new PostgreSqlSyntaxHelper();

            return(@"ALTER TABLE " + discoveredTable.GetFullyQualifiedName() + @"
                RENAME TO " + syntax.EnsureWrapped(newName));
        }
        private string[] ListPrimaryKeys(IManagedConnection con, DiscoveredTable table)
        {
            string query = $@"SELECT               
            pg_attribute.attname, 
            format_type(pg_attribute.atttypid, pg_attribute.atttypmod) 
            FROM pg_index, pg_class, pg_attribute 
            WHERE 
            pg_class.oid = '{table.GetFullyQualifiedName()}'::regclass AND 
                indrelid = pg_class.oid AND  
            pg_attribute.attrelid = pg_class.oid AND 
            pg_attribute.attnum = any(pg_index.indkey)
            AND indisprimary";

            List <string> toReturn = new List <string>();

            using (DbCommand cmd = table.GetCommand(query, con.Connection))
            {
                cmd.Transaction = con.Transaction;

                using (DbDataReader r = cmd.ExecuteReader())
                {
                    while (r.Read())
                    {
                        toReturn.Add((string)r["attname"]);
                    }

                    r.Close();
                }
            }

            return(toReturn.ToArray());
        }
Exemple #5
0
        protected override string BuildUpdateImpl(DiscoveredTable table1, DiscoveredTable table2, List <CustomLine> lines)
        {
            // This implementation is based on:
            // https://stackoverflow.com/a/32748797/4824531

            /*MERGE INTO table1 t1
             * USING
             * (
             * -- For more complicated queries you can use WITH clause here
             * SELECT * FROM table2
             * )t2
             * ON(t1.id = t2.id)
             * WHEN MATCHED THEN UPDATE SET
             * t1.name = t2.name,
             * t1.desc = t2.desc;*/


            return(string.Format(
                       @"MERGE INTO {1} t1
USING
( 
    SELECT * FROM {2}
)t2
on ({3})
WHEN MATCHED THEN UPDATE SET
    {0}
WHERE
{4}",
                       string.Join(", " + Environment.NewLine, lines.Where(l => l.LocationToInsert == QueryComponent.SET).Select(c => c.Text)),
                       table1.GetFullyQualifiedName(),
                       table2.GetFullyQualifiedName(),
                       string.Join(" AND ", lines.Where(l => l.LocationToInsert == QueryComponent.JoinInfoJoin).Select(c => c.Text)),
                       string.Join(" AND ", lines.Where(l => l.LocationToInsert == QueryComponent.WHERE).Select(c => c.Text))));
        }
        public override void MakeDistinct(DiscoveredTable discoveredTable, int timeoutInSeconds)
        {
            string sql =
                @"DELETE f
            FROM (
            SELECT	ROW_NUMBER() OVER (PARTITION BY {0} ORDER BY {0}) AS RowNum
            FROM {1}
            
            ) as f
            where RowNum > 1";

            string columnList = string.Join(",", discoveredTable.DiscoverColumns().Select(c => c.GetRuntimeName()));

            string sqlToExecute = string.Format(sql, columnList, discoveredTable.GetFullyQualifiedName());

            var server = discoveredTable.Database.Server;

            using (var con = server.GetConnection())
            {
                con.Open();
                var cmd = server.GetCommand(sqlToExecute, con);
                cmd.CommandTimeout = timeoutInSeconds;
                cmd.ExecuteNonQuery();
            }
        }
Exemple #7
0
        protected override string BuildUpdateImpl(DiscoveredTable table1, DiscoveredTable table2, List <CustomLine> lines)
        {
            //https://stackoverflow.com/a/7869611
            string joinSql = string.Join(" AND ",
                                         lines.Where(l => l.LocationToInsert == QueryComponent.JoinInfoJoin).Select(c => c.Text));

            string whereSql = string.Join(" AND ",
                                          lines.Where(l => l.LocationToInsert == QueryComponent.WHERE).Select(c => c.Text));

            return(string.Format(
                       @"UPDATE {1} AS t1
SET 
    {0}
FROM
 {2} AS t2 
WHERE
{3}
{4}
{5}
",

                       string.Join(", " + Environment.NewLine, lines.Where(l => l.LocationToInsert == QueryComponent.SET)
                                   .Select(c =>
                                           //seems like you cant specify the table alias in the SET section of the query
                                           c.Text.Replace("t1.", ""))),
                       table1.GetFullyQualifiedName(),
                       table2.GetFullyQualifiedName(),
                       joinSql,
                       !string.IsNullOrWhiteSpace(whereSql) ? "AND" :"",
                       !string.IsNullOrWhiteSpace(whereSql) ? "(" + whereSql + ")":""
                       ));
        }
Exemple #8
0
        /// <summary>
        /// Returns SQL to update the <paramref name="topXRows"/> with the provided SET string
        /// </summary>
        /// <param name="tbl">Table to update</param>
        /// <param name="topXRows">Number of rows to change</param>
        /// <param name="setSql">Set SQL e.g. "Set Col1='fish'"</param>
        /// <returns></returns>
        private string GetUpdateTopXSql(DiscoveredTable tbl, int topXRows, string setSql)
        {
            switch (tbl.Database.Server.DatabaseType)
            {
            case DatabaseType.MicrosoftSQLServer:
                return
                    ($"UPDATE TOP ({topXRows}) {tbl.GetFullyQualifiedName()} {setSql}");

            case DatabaseType.MySql:
                return
                    ($"UPDATE {tbl.GetFullyQualifiedName()} {setSql} LIMIT {topXRows}");

            default:
                throw new ArgumentOutOfRangeException();
            }
        }
Exemple #9
0
        public override int Run()
        {
            DiscoveredTable tbl    = GetServer(_opts.DatabaseConnectionString, _opts.DatabaseType, _opts.TableName);
            var             server = tbl.Database.Server;

            _factory = new DatabaseFailureFactory(tbl);

            _columns       = tbl.DiscoverColumns();
            _columnsNames  = _columns.Select(c => c.GetRuntimeName()).ToArray();
            _stringColumns = _columns.Select(c => c.GetGuesser().Guess.CSharpType == typeof(string)).ToArray();

            using (var con = server.GetConnection())
            {
                con.Open();

                var cmd = server.GetCommand(
                    string.Format("SELECT {0} FROM {1}"
                                  , string.Join("," + Environment.NewLine, _columns.Select(c => c.GetFullyQualifiedName()).ToArray())
                                  , tbl.GetFullyQualifiedName()), con);

                _logger.Info("About to send command:" + Environment.NewLine + cmd.CommandText);

                var reader = cmd.ExecuteReader();

                foreach (Failure failure in reader.Cast <DbDataRecord>().SelectMany(GetFailuresIfAny))
                {
                    AddToReports(failure);
                }

                CloseReports();
            }
            return(0);
        }
Exemple #10
0
        public override void MakeDistinct(DatabaseOperationArgs args, DiscoveredTable discoveredTable)
        {
            var syntax = discoveredTable.GetQuerySyntaxHelper();

            string sql =
                @"DELETE f
            FROM (
            SELECT	ROW_NUMBER() OVER (PARTITION BY {0} ORDER BY {0}) AS RowNum
            FROM {1}
            
            ) as f
            where RowNum > 1";

            string columnList = string.Join(",",
                                            discoveredTable.DiscoverColumns().Select(c => syntax.EnsureWrapped(c.GetRuntimeName())));

            string sqlToExecute = string.Format(sql, columnList, discoveredTable.GetFullyQualifiedName());

            var server = discoveredTable.Database.Server;

            using (var con = args.GetManagedConnection(server))
            {
                using (var cmd = server.GetCommand(sqlToExecute, con))
                    args.ExecuteNonQuery(cmd);
            }
        }
Exemple #11
0
        public void NowTestDataInsertion(DatabaseType dbType)
        {
            AlterTest_InvalidThenRecreateItAndItsValidAgain(dbType);

            _table.Insert(new Dictionary <string, object>
            {
                { "name", "Franky" },
                { "bubbles", 3 },
                { "hic_validFrom", new DateTime(2001, 1, 2) },
                { "hic_dataLoadRunID", 7 }
            });

            var liveOldRow = _table.GetDataTable().Rows.Cast <DataRow>().Single(r => r["bubbles"] as int? == 3);

            Assert.AreEqual(new DateTime(2001, 1, 2), ((DateTime)liveOldRow[SpecialFieldNames.ValidFrom]));

            RunSQL("UPDATE {0} set bubbles =99", _table.GetFullyQualifiedName());

            //new value is 99
            Assert.AreEqual(99, ExecuteScalar("Select bubbles FROM {0} where name = 'Franky'", _table.GetFullyQualifiedName()));
            //archived value is 3
            Assert.AreEqual(3, ExecuteScalar("Select bubbles FROM {0} where name = 'Franky'", _archiveTable.GetFullyQualifiedName()));

            //Legacy table valued function only works for MicrosoftSQLServer
            if (dbType == DatabaseType.MicrosoftSQLServer)
            {
                //legacy in 2001-01-01 it didn't exist
                Assert.IsNull(ExecuteScalar("Select bubbles FROM TriggerTests_Legacy('2001-01-01') where name = 'Franky'"));
                //legacy in 2001-01-03 it did exist and was 3
                Assert.AreEqual(3, ExecuteScalar("Select bubbles FROM TriggerTests_Legacy('2001-01-03') where name = 'Franky'"));
                //legacy boundary case?
                Assert.AreEqual(3, ExecuteScalar("Select bubbles FROM TriggerTests_Legacy('2001-01-02') where name = 'Franky'"));

                //legacy today it is 99
                Assert.AreEqual(99, ExecuteScalar("Select bubbles FROM TriggerTests_Legacy(GETDATE()) where name = 'Franky'"));
            }

            // Live row should now reflect that it is validFrom today
            var liveNewRow = _table.GetDataTable().Rows.Cast <DataRow>().Single(r => r["bubbles"] as int? == 99);

            Assert.AreEqual(DateTime.Now.Date, ((DateTime)liveNewRow[SpecialFieldNames.ValidFrom]).Date);

            // Archived row should not have had it's validFrom field broken
            var archivedRow = _archiveTable.GetDataTable().Rows.Cast <DataRow>().Single(r => r["bubbles"] as int? == 3);

            Assert.AreEqual(new DateTime(2001, 1, 2), ((DateTime)archivedRow[SpecialFieldNames.ValidFrom]));
        }
Exemple #12
0
 public MicrosoftSQLBulkCopy(DiscoveredTable targetTable, IManagedConnection connection, CultureInfo culture) : base(targetTable, connection, culture)
 {
     _bulkcopy = new SqlBulkCopy((SqlConnection)connection.Connection, SqlBulkCopyOptions.KeepIdentity, (SqlTransaction)connection.Transaction)
     {
         BulkCopyTimeout      = 50000,
         DestinationTableName = targetTable.GetFullyQualifiedName()
     };
 }
Exemple #13
0
 /// <summary>
 /// Creates a mock implementation of <see cref="ITableInfo"/> that points to the live database table <paramref name="table"/>
 /// </summary>
 /// <param name="table"></param>
 /// <returns></returns>
 public static ITableInfo Mock_TableInfo(DiscoveredTable table)
 {
     return(Mock.Of <ITableInfo>(p =>
                                 p.Name == table.GetFullyQualifiedName() &&
                                 p.Database == table.Database.GetRuntimeName() &&
                                 p.DatabaseType == table.Database.Server.DatabaseType &&
                                 p.IsTableValuedFunction == (table.TableType == TableType.TableValuedFunction) &&
                                 p.Discover(It.IsAny <DataAccessContext>()) == table));
 }
        public string GetSql()
        {
            var response = _table.GetQuerySyntaxHelper().HowDoWeAchieveTopX(100);

            switch (response.Location)
            {
            case QueryComponent.SELECT:
                return("Select " + response.SQL + " * from " + _table.GetFullyQualifiedName());

            case QueryComponent.WHERE:
                return("Select * from " + _table.GetFullyQualifiedName() + " WHERE " + response.SQL);

            case QueryComponent.Postfix:
                return("Select * from " + _table.GetFullyQualifiedName() + " " + response.SQL);

            default:
                throw new ArgumentOutOfRangeException();
            }
        }
Exemple #15
0
        public override void Setup(IMappingTableOptions options)
        {
            _options   = options;
            _swapTable = options.Discover();
            _server    = _swapTable.Database.Server;

            if (!_swapTable.Exists())
            {
                throw new ArgumentException($"Swap table '{_swapTable.GetFullyQualifiedName()}' did not exist on server '{_server}'");
            }
        }
Exemple #16
0
        /// <summary>
        /// Returns SQL to update a single <paramref name="word"/> in the <paramref name="table"/> row referenced by the primary key value
        /// in <paramref name="failure"/>
        /// </summary>
        /// <param name="table"></param>
        /// <param name="primaryKeys"></param>
        /// <param name="syntax"></param>
        /// <param name="failure"></param>
        /// <param name="word">The word or collection of words that should be redacted</param>
        /// <returns></returns>
        protected string GetUpdateWordSql(DiscoveredTable table,
                                          Dictionary <DiscoveredTable, DiscoveredColumn> primaryKeys, IQuerySyntaxHelper syntax, Failure failure, string word)
        {
            if (string.IsNullOrEmpty(failure.ResourcePrimaryKey))
            {
                throw new ArgumentException("Failure record's primary key is blank, cannot update database");
            }

            return($@"update {table.GetFullyQualifiedName()} 
                SET {syntax.EnsureWrapped(failure.ProblemField)} = 
                REPLACE({syntax.EnsureWrapped(failure.ProblemField)},'{syntax.Escape(word)}', 'SMI_REDACTED')
                WHERE {primaryKeys[table].GetFullyQualifiedName()} = '{syntax.Escape(failure.ResourcePrimaryKey)}'");
        }
Exemple #17
0
        /// <summary>
        /// Sets up a CHI/ECHI mapping table with fallback guid and populates each table with a single record.
        /// 0101010101 is a known CHI and 0202020202 is an known one (which was assigned a temporary guid mapping).
        /// Also prepares the main map table for DLE loading (<see cref="TriggerImplementer"/>)
        /// </summary>
        /// <param name="dbType"></param>
        /// <param name="map"></param>
        /// <param name="guidTable"></param>
        /// <param name="mapperOptions"></param>
        /// <param name="guids">true to create a <see cref="TableLookupWithGuidFallbackSwapper"/> otherwise creates a  <see cref="TableLookupSwapper"/></param>
        private void SetupMappers(DatabaseType dbType, out DiscoveredTable map, out DiscoveredTable guidTable, out IdentifierMapperOptions mapperOptions, bool guids = true)
        {
            var db = GetCleanedServer(dbType);

            using (var dt = new DataTable())
            {
                dt.Columns.Add("CHI");
                dt.Columns.Add("ECHI");

                dt.PrimaryKey = new [] { dt.Columns["CHI"] };

                dt.Rows.Add("0101010101", "0A0A0A0A0A");
                map = db.CreateTable("Map", dt);
            }

            mapperOptions = new IdentifierMapperOptions()
            {
                MappingTableName        = map.GetFullyQualifiedName(),
                MappingConnectionString = db.Server.Builder.ConnectionString,
                SwapColumnName          = "CHI",
                ReplacementColumnName   = "ECHI",
                MappingDatabaseType     = db.Server.DatabaseType,
                SwapperType             = (guids ? typeof(TableLookupWithGuidFallbackSwapper):typeof(TableLookupSwapper)).FullName
            };

            if (guids)
            {
                var swapper = new TableLookupWithGuidFallbackSwapper();
                swapper.Setup(mapperOptions);

                guidTable = swapper.GetGuidTableIfAny(mapperOptions);
                Assert.AreEqual(0, guidTable.GetRowCount(), "No temporary guids should exist yet");
                Assert.AreEqual(1, map.GetRowCount(), "We should have a mapping table with 1 entry");

                //lookup an as yet unknown value
                swapper.GetSubstitutionFor("0202020202", out _);

                Assert.AreEqual(1, map.GetRowCount(), "We should have a mapping table with 1 entry");
                Assert.AreEqual(1, guidTable.GetRowCount(), "We should have a temporary guid for 0202020202");
            }
            else
            {
                guidTable = null;
            }

            // make a fake data load into this table (create trigger and insert/update)
            var triggerImplementer = new TriggerImplementerFactory(dbType).Create(map);

            triggerImplementer.CreateTrigger(new ThrowImmediatelyCheckNotifier());
        }
Exemple #18
0
        public override string GetSubstitutionFor(string toSwap, out string reason)
        {
            reason = null;

            // If the cached key matches, return the last value
            if (string.Equals(toSwap, _lastKey) && _lastVal != null)
            {
                _logger.Debug("Using cached swap value");

                CacheHit++;
                Success++;

                return(_lastVal);
            }

            CacheMiss++;

            // Else fall through to the database lookup
            using (new TimeTracker(DatabaseStopwatch))
                using (DbConnection con = _server.GetConnection())
                {
                    con.Open();

                    string sql = string.Format("SELECT {0} FROM {1} WHERE {2}=@val",
                                               _options.ReplacementColumnName,
                                               _swapTable.GetFullyQualifiedName(),
                                               _options.SwapColumnName);

                    DbCommand cmd = _server.GetCommand(sql, con);
                    _server.AddParameterWithValueToCommand("@val", cmd, toSwap);

                    object result = cmd.ExecuteScalar();

                    if (result == DBNull.Value || result == null)
                    {
                        reason = "No match found for '" + toSwap + "'";
                        Fail++;
                        return(null);
                    }

                    _lastKey = toSwap;
                    _lastVal = result.ToString();

                    ++Success;

                    return(_lastVal);
                }
        }
        protected override string BuildUpdateImpl(DiscoveredTable table1, DiscoveredTable table2, List <CustomLine> lines)
        {
            return(string.Format(
                       @"UPDATE {1} t1
 join  {2} t2 
on 
{3}
SET 
    {0}
WHERE
{4}",
                       string.Join(", " + Environment.NewLine, lines.Where(l => l.LocationToInsert == QueryComponent.SET).Select(c => c.Text)),
                       table1.GetFullyQualifiedName(),
                       table2.GetFullyQualifiedName(),
                       string.Join(" AND ", lines.Where(l => l.LocationToInsert == QueryComponent.JoinInfoJoin).Select(c => c.Text)),
                       string.Join(" AND ", lines.Where(l => l.LocationToInsert == QueryComponent.WHERE).Select(c => c.Text))));
        }
Exemple #20
0
        private string WorkOutArchiveTableCreationSQL()
        {
            //script original table
            string createTableSQL = _table.ScriptTableCreation(true, true, true);

            string toReplaceTableName = "CREATE TABLE " + _table.GetFullyQualifiedName();

            if (!createTableSQL.Contains(toReplaceTableName))
            {
                throw new Exception("Expected to find occurrence of " + toReplaceTableName + " in the SQL " + createTableSQL);
            }

            //rename table
            createTableSQL = createTableSQL.Replace(toReplaceTableName, "CREATE TABLE " + _archiveTable.GetFullyQualifiedName());

            string toRemoveIdentities = "IDENTITY\\(\\d+,\\d+\\)";

            //drop identity bit
            createTableSQL = Regex.Replace(createTableSQL, toRemoveIdentities, "");

            return(createTableSQL);
        }
Exemple #21
0
        public void Add(DiscoveredTable discoveredTable)
        {
            if (items.Any(i => i.Tag.Equals(discoveredTable)))
            {
                return;
            }

            var snip = new SubstringAutocompleteItem(discoveredTable.GetRuntimeName());

            snip.MenuText   = discoveredTable.GetRuntimeName();        //name of table
            snip.Text       = discoveredTable.GetFullyQualifiedName(); //full SQL
            snip.Tag        = discoveredTable;                         //record object for future reference
            snip.ImageIndex = GetIndexFor(discoveredTable, RDMPConcept.TableInfo.ToString());


            AddUnlessDuplicate(snip);

            DiscoveredColumn[] columns = null;
            try
            {
                if (discoveredTable.Exists())
                {
                    columns = discoveredTable.DiscoverColumns();
                }
            }
            catch (Exception)
            {
                //couldn't load nevermind
            }

            if (columns != null)
            {
                foreach (var col in columns)
                {
                    Add(col);
                }
            }
        }
Exemple #22
0
        /// <summary>
        /// Returns a query for fetching the latest entry in the archive that matches a given private identifier (query contains parameter @currentSwapColValue)
        /// </summary>
        /// <param name="archiveTable"></param>
        /// <param name="swapCol">The private identifier column name e.g. CHI</param>
        /// <param name="forCol">The public release identifier column name e.g. ECHI</param>
        /// <returns>SQL for fetching the latest release identifier value (e.g. ECHI value) from the archive</returns>
        private string GetArchiveFetchSql(DiscoveredTable archiveTable, string swapCol, string forCol)
        {
            // Work out how to get the latest entry in the _Archive table that corresponds to a given private identifier (e.g. CHI)
            var syntax = archiveTable.Database.Server.GetQuerySyntaxHelper();

            var topX = syntax.HowDoWeAchieveTopX(1);

            StringBuilder sb = new StringBuilder();

            sb.AppendLine("SELECT ");

            if (topX.Location == QueryComponent.SELECT)
            {
                sb.AppendLine(topX.SQL);
            }

            sb.AppendLine(forCol);
            sb.AppendLine("FROM " + archiveTable.GetFullyQualifiedName());
            sb.AppendLine("WHERE");
            sb.AppendLine($"{swapCol} = @currentSwapColValue");

            if (topX.Location == QueryComponent.WHERE)
            {
                sb.AppendLine("AND");
                sb.AppendLine(topX.SQL);
            }

            sb.AppendLine("ORDER BY");
            sb.AppendLine(SpecialFieldNames.ValidFrom + " desc");

            if (topX.Location == QueryComponent.Postfix)
            {
                sb.AppendLine(topX.SQL);
            }

            return(sb.ToString());
        }
 private void AddColumnToTable(DiscoveredTable table, string desiredColumnName, string desiredColumnType, IDataLoadEventListener listener)
 {
     listener.OnNotify(this, new NotifyEventArgs(ProgressEventType.Information, string.Format("Adding column '{0}' with datatype '{1}' to table '{2}'", desiredColumnName, desiredColumnType, table.GetFullyQualifiedName())));
     table.AddColumn(desiredColumnName, desiredColumnType, true, 500);
 }
Exemple #24
0
        private void DropColumnFromTable(DiscoveredTable table, string columnName, IDataLoadEventListener listener)
        {
            listener.OnNotify(this, new NotifyEventArgs(ProgressEventType.Information, string.Format("Dropping column '{0}' from table '{1}'", columnName, table.GetFullyQualifiedName())));
            var col = table.DiscoverColumn(columnName);

            table.DropColumn(col);
        }
Exemple #25
0
        /// <summary>
        /// Generates and runs an SQL command on <paramref name="t"/>
        /// </summary>
        /// <param name="t"></param>
        /// <param name="message"></param>
        protected virtual int UpdateTable(DiscoveredTable t, UpdateValuesMessage message)
        {
            var audit = _audits.GetOrAdd(t, (k) => new UpdateTableAudit(k));

            StringBuilder builder = new StringBuilder();

            builder.AppendLine("UPDATE ");
            builder.AppendLine(t.GetFullyQualifiedName());
            builder.AppendLine(" SET ");

            for (int i = 0; i < message.WriteIntoFields.Length; i++)
            {
                var col = t.DiscoverColumn(message.WriteIntoFields[i]);

                builder.Append(GetFieldEqualsValueExpression(col, message.Values[i], "="));

                //if there are more SET fields to come
                if (i < message.WriteIntoFields.Length - 1)
                {
                    builder.AppendLine(",");
                }
            }

            builder.AppendLine(" WHERE ");

            for (int i = 0; i < message.WhereFields.Length; i++)
            {
                var col = t.DiscoverColumn(message.WhereFields[i]);

                builder.Append(GetFieldEqualsValueExpression(col, message.HaveValues[i], message?.Operators?[i]));

                //if there are more WHERE fields to come
                if (i < message.WhereFields.Length - 1)
                {
                    builder.AppendLine(" AND ");
                }
            }

            var sql          = builder.ToString();
            int affectedRows = 0;

            audit.StartOne();
            try
            {
                using (var con = t.Database.Server.GetConnection())
                {
                    con.Open();

                    var cmd = t.Database.Server.GetCommand(sql, con);
                    cmd.CommandTimeout = UpdateTimeout;

                    try
                    {
                        return(affectedRows = cmd.ExecuteNonQuery());
                    }
                    catch (Exception ex)
                    {
                        throw new Exception($"Failed to excute query {sql} ", ex);
                    }
                }
            }
            finally
            {
                audit.EndOne(affectedRows < 0 ? 0 : affectedRows);
            }
        }
        private void MigrateExistingData(Func <string, bool> shouldApplySql, DbConnection con, ICheckNotifier notifier, DiscoveredTable tbl)
        {
            string from = _colToNuke.GetRuntimeName(LoadStage.PostLoad);
            string to   = _newANOColumnInfo.GetRuntimeName(LoadStage.PostLoad);


            //create an empty table for the anonymised data
            DbCommand cmdCreateTempMap = DatabaseCommandHelper.GetCommand(string.Format("SELECT top 0 {0},{1} into TempANOMap from {2}", from, to, tbl.GetFullyQualifiedName()), con);

            if (!shouldApplySql(cmdCreateTempMap.CommandText))
            {
                throw new Exception("User decided not to create the TempANOMap table");
            }

            cmdCreateTempMap.ExecuteNonQuery();
            try
            {
                //get the existing data
                DbCommand cmdGetExistingData = DatabaseCommandHelper.GetCommand(string.Format("SELECT {0},{1} from {2}", from, to, tbl.GetFullyQualifiedName()), con);

                DbDataAdapter da = DatabaseCommandHelper.GetDataAdapter(cmdGetExistingData);

                DataTable dt = new DataTable();
                da.Fill(dt);//into memory

                //transform it in memory
                ANOTransformer transformer = new ANOTransformer(_toConformTo, new FromCheckNotifierToDataLoadEventListener(notifier));
                transformer.Transform(dt, dt.Columns[0], dt.Columns[1]);

                var tempAnoMapTbl = tbl.Database.ExpectTable("TempANOMap");

                using (var insert = tempAnoMapTbl.BeginBulkInsert())
                {
                    insert.Upload(dt);
                }

                //create an empty table for the anonymised data
                DbCommand cmdUpdateMainTable = DatabaseCommandHelper.GetCommand(string.Format("UPDATE source set source.{1} = map.{1} from {2} source join TempANOMap map on source.{0}=map.{0}", from, to, tbl.GetFullyQualifiedName()), con);

                if (!shouldApplySql(cmdUpdateMainTable.CommandText))
                {
                    throw new Exception("User decided not to perform update on table");
                }
                cmdUpdateMainTable.ExecuteNonQuery();
            }
            finally
            {
                //always drop the temp anomap
                DbCommand dropMappingTable = DatabaseCommandHelper.GetCommand("DROP TABLE TempANOMap", con);
                dropMappingTable.ExecuteNonQuery();
            }
        }
Exemple #27
0
        private void LoadFile(DiscoveredTable tableToLoad, FileInfo fileToLoad, DiscoveredDatabase dbInfo, Stopwatch timer, IDataLoadJob job, GracefulCancellationToken token)
        {
            using (var con = dbInfo.Server.GetConnection())
            {
                DataTable dt = tableToLoad.GetDataTable(0);

                using (var insert = tableToLoad.BeginBulkInsert(Culture))
                {
                    // setup bulk insert it into destination
                    insert.Timeout = 500000;

                    //if user wants to use a specific explicit format for datetimes
                    if (ExplicitDateTimeFormat != null)
                    {
                        insert.DateTimeDecider.Settings.ExplicitDateFormats = new string[] { ExplicitDateTimeFormat }
                    }
                    ;

                    //bulk insert ito destination
                    job.OnNotify(this, new NotifyEventArgs(ProgressEventType.Information, "About to open file " + fileToLoad.FullName));
                    OpenFile(fileToLoad, job, token);

                    //confirm the validity of the headers
                    ConfirmFlatFileHeadersAgainstDataTable(dt, job);

                    con.Open();

                    //now we will read data out of the file in batches
                    int batchNumber         = 1;
                    int maxBatchSize        = 10000;
                    int recordsCreatedSoFar = 0;

                    try
                    {
                        //while there is data to be loaded into table
                        while (IterativelyBatchLoadDataIntoDataTable(dt, maxBatchSize, token) != 0)
                        {
                            DropEmptyColumns(dt);
                            ConfirmFitToDestination(dt, tableToLoad, job);
                            try
                            {
                                recordsCreatedSoFar += insert.Upload(dt);

                                dt.Rows.Clear(); //very important otherwise we add more to the end of the table but still insert last batches records resulting in exponentially multiplying upload sizes of duplicate records!

                                job.OnProgress(this,
                                               new ProgressEventArgs(tableToLoad.GetFullyQualifiedName(),
                                                                     new ProgressMeasurement(recordsCreatedSoFar, ProgressType.Records), timer.Elapsed));
                            }
                            catch (Exception e)
                            {
                                throw new Exception("Error processing batch number " + batchNumber + " (of batch size " + maxBatchSize + ")", e);
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        throw new FlatFileLoadException("Error processing file " + fileToLoad, e);
                    }
                    finally
                    {
                        CloseFile();
                    }
                }
            }
        }
 private void ConfirmTableDeletion(DiscoveredTable expectTable)
 {
     if (expectTable.Exists())
     {
         var confirm = MessageBox.Show(String.Format("A table named {0} has been created as part of this import. Do you want to keep it?", expectTable.GetFullyQualifiedName()),
                                       "Confirm", MessageBoxButtons.YesNo);
         if (confirm == DialogResult.No)
         {
             expectTable.Drop();
         }
     }
 }
        public override void FillDataTableWithTopX(DiscoveredTable table, int topX, DataTable dt, DbConnection connection, DbTransaction transaction = null)
        {
            ((OracleConnection)connection).PurgeStatementCache();

            var cols = table.DiscoverColumns();

            string sql = "SELECT " + string.Join(",", cols.Select(c => c.GetFullyQualifiedName()).ToArray()) + " FROM " + table.GetFullyQualifiedName() + " OFFSET 0 ROWS FETCH NEXT " + topX + " ROWS ONLY";

            var da = table.Database.Server.GetDataAdapter(sql, connection);

            da.Fill(dt);
        }
 protected override string GetRenameTableSql(DiscoveredTable discoveredTable, string newName)
 {
     return(string.Format(@"alter table {0} rename to {1}", discoveredTable.GetFullyQualifiedName(), newName));
 }