コード例 #1
0
ファイル: PreProcessor.cs プロジェクト: KonsN/SQL-Replay
 private void AddBulkInsertData(BulkInsert bulkInsert, SqlConnection con)
 {
     using (DataTable dataTable = GetBulkInsertDataFromTable(bulkInsert, con))
     {
         for (var rowIndex = 0; rowIndex < bulkInsert.RowCount; rowIndex++)
         {
             var row = new List <object>();
             for (var columnIndex = 0; columnIndex < bulkInsert.Columns.Count; columnIndex++)
             {
                 row.Add(dataTable.Rows[rowIndex][columnIndex]);
             }
             bulkInsert.Rows.Add(row);
         }
     }
 }
コード例 #2
0
ファイル: PreProcessor.cs プロジェクト: KonsN/SQL-Replay
        private DataTable GetBulkInsertDataFromTable(BulkInsert bulkInsert, SqlConnection con)
        {
            var dataTable = new DataTable();
            var cmdText   = $" select top(@count) {string.Join(',', bulkInsert.Columns.Select(c => c.Name).ToArray())} from {bulkInsert.Table}";

            using (var cmd = new SqlCommand(cmdText, con))
            {
                cmd.Parameters.Add(new SqlParameter("@count", SqlDbType.Int)
                {
                    Value = bulkInsert.RowCount
                });
                using (var dataAdapter = new SqlDataAdapter(cmd))
                {
                    dataAdapter.Fill(dataTable);
                }
            }
            return(dataTable);
        }
コード例 #3
0
ファイル: PreProcessor.cs プロジェクト: codyHCHB/SQL-Replay
        internal async Task <Run> PreProcess(string[] fileNames, string connectionString, DateTimeOffset?cutoff)
        {
            var sessions = new ConcurrentDictionary <string, Session>();

            using (var con = new SqlConnection(connectionString))
            {
                await con.OpenAsync();

                foreach (string fileName in fileNames)
                {
                    var xeStream = new XEFileEventStreamer(fileName);
                    await xeStream.ReadEventStream(xevent =>
                    {
                        if (xevent.Actions["database_name"].ToString() != con.Database)
                        {
                            return(Task.CompletedTask);
                        }

                        if (cutoff != null && xevent.Timestamp > cutoff)
                        {
                            return(Task.CompletedTask);
                        }

                        Event evt = null;
                        if (xevent.Name == "rpc_starting" &&
                            xevent.Fields["object_name"].ToString() != "sp_reset_connection" &&
                            !xevent.Fields["statement"].ToString().StartsWith("exec sp_unprepare "))
                        {
                            evt = new Rpc()
                            {
                                EventSequence = xevent.Actions["event_sequence"].ToString(),
                                TransactionId = xevent.Actions["transaction_id"].ToString(),
                                Statement     = xevent.Fields["statement"].ToString(),
                                ObjectName    = xevent.Fields["object_name"].ToString(),
                                Timestamp     = xevent.Timestamp
                            };
                            //Build parameters so we can replay statements as ADO.NET CommandType.StoredProcedure calls in order to avoid extra compilations of raw statement
                            LoadParameters(con, (Rpc)evt);
                        }
                        else if (xevent.Name == "sql_transaction")
                        {
                            if (xevent.Fields["transaction_type"].ToString() == "User")
                            {
                                evt = new Transaction()
                                {
                                    EventSequence    = xevent.Actions["event_sequence"].ToString(),
                                    TransactionId    = xevent.Fields["transaction_id"].ToString(),
                                    TransactionState = xevent.Fields["transaction_state"].ToString(),
                                    Timestamp        = xevent.Timestamp
                                };
                            }
                        }
                        else if (xevent.Name == "sql_batch_starting" &&
                                 xevent.Fields["batch_text"].ToString().Contains("insert bulk"))
                        {
                            var bulkInsert = new BulkInsert()
                            {
                                EventSequence = xevent.Actions["event_sequence"].ToString(),
                                TransactionId = xevent.Actions["transaction_id"].ToString(),
                                BatchText     = xevent.Fields["batch_text"].ToString(),
                                Timestamp     = xevent.Timestamp
                            };

                            bulkInsert.Table = bulkInsert.BatchText.Split(' ')[2];
                            string[] columns = bulkInsert.BatchText.GetParenthesesContent().Split(", ");
                            foreach (string col in columns)
                            {
                                string[] columnInfo = col.Split(' ');
                                bulkInsert.Columns.Add(new Column {
                                    Name = columnInfo[0], DataType = columnInfo[1]
                                });
                            }

                            if (bulkInsert.BatchText.Contains(" with ("))
                            {
                                string[] settings = bulkInsert.BatchText
                                                    .GetParenthesesContent(bulkInsert.BatchText.IndexOf(" with (") + 6).Split(", ");
                                foreach (string setting in settings)
                                {
                                    if (setting == "FIRE_TRIGGERS")
                                    {
                                        bulkInsert.FireTriggers = true;
                                        break;
                                    }
                                }
                            }

                            evt = bulkInsert;
                        }
                        else if (xevent.Name == "sql_batch_completed" &&
                                 xevent.Fields["batch_text"].ToString().Contains("insert bulk"))
                        {
                            if (!sessions.TryGetValue(xevent.Actions["session_id"].ToString(), out var session))
                            {
                                throw new Exception(
                                    $"Could not find session ID {xevent.Actions["session_id"].ToString()} for bulk insert.");
                            }
                            else
                            {
                                var bulkInsert = (BulkInsert)session.Events
                                                 .FirstOrDefault(e =>
                                                                 (e as BulkInsert)?.TransactionId ==
                                                                 xevent.Actions["transaction_id"].ToString() &&
                                                                 (e as BulkInsert)?.BatchText == xevent.Fields["batch_text"].ToString());
                                if (bulkInsert != null)
                                {
                                    bulkInsert.Rows = int.Parse(xevent.Fields["row_count"].ToString());
                                }
                            }
                        }

                        if (evt != null)
                        {
                            string sessionId = xevent.Actions["session_id"].ToString();
                            Session session  = sessions.GetOrAdd(sessionId, new Session()
                            {
                                SessionId = sessionId
                            });
                            session.Events.Add(evt);
                        }

                        return(Task.CompletedTask);
                    }, CancellationToken.None);
                }
            }

            foreach (Session session in sessions.Values)
            {
                session.Events = session.Events.OrderBy(e => e.EventSequence).ToList();
            }

            var run = new Run()
            {
                Sessions = sessions.Values.ToArray().Where(s => s.Events.Count > 0).OrderBy(s => s.Events.First().EventSequence).ToList()
            };

            run.EventCaptureOrigin = run.Sessions.First().Events.First().Timestamp;
            return(run);
        }
コード例 #4
0
ファイル: PreProcessor.cs プロジェクト: KonsN/SQL-Replay
        internal async Task <Run> PreProcessAsync(string[] filePaths, string connectionString)
        {
            var sessionDictionary = new ConcurrentDictionary <string, Session>();

            using (var con = new SqlConnection(connectionString))
            {
                await con.OpenAsync();

                foreach (string filePath in filePaths)
                {
                    if (!Regex.IsMatch(Path.GetFileName(filePath), @"^\w+\.xel$", RegexOptions.IgnoreCase))
                    {
                        //ignore any files that don't fit the pattern of an XE file
                        continue;
                    }
                    var xeStream = new XEFileEventStreamer(filePath);
                    await xeStream.ReadEventStream(xevent =>
                    {
                        if (xevent.Actions["database_name"].ToString() != con.Database)
                        {
                            return(Task.CompletedTask);
                        }
                        Event evt = null;
                        if (xevent.Name == "rpc_starting" &&
                            xevent.Fields["object_name"].ToString() != "sp_reset_connection" &&
                            !xevent.Fields["statement"].ToString().StartsWith("exec sp_unprepare "))
                        {
                            evt = new Rpc()
                            {
                                EventSequence = long.Parse(xevent.Actions["event_sequence"].ToString()),
                                TransactionId = xevent.Actions["transaction_id"].ToString(),
                                Statement     = xevent.Fields["statement"].ToString(),
                                ObjectName    = xevent.Fields["object_name"].ToString(),
                                Timestamp     = xevent.Timestamp
                            };
                            //Build parameters so we can replay statements as ADO.NET CommandType.StoredProcedure calls in order to avoid extra compilations of raw statement
                            LoadParameters(con, (Rpc)evt);
                        }
                        else if (xevent.Name == "sql_transaction")
                        {
                            if (xevent.Fields["transaction_type"].ToString() == "User")
                            {
                                evt = new Transaction()
                                {
                                    EventSequence    = long.Parse(xevent.Actions["event_sequence"].ToString()),
                                    TransactionId    = xevent.Fields["transaction_id"].ToString(),
                                    TransactionState = xevent.Fields["transaction_state"].ToString(),
                                    Timestamp        = xevent.Timestamp
                                };
                            }
                        }
                        else if (xevent.Name == "sql_batch_starting" &&
                                 xevent.Fields["batch_text"].ToString().Contains("insert bulk"))
                        {
                            var bulkInsert = new BulkInsert()
                            {
                                EventSequence = long.Parse(xevent.Actions["event_sequence"].ToString()),
                                TransactionId = xevent.Actions["transaction_id"].ToString(),
                                BatchText     = xevent.Fields["batch_text"].ToString(),
                                Timestamp     = xevent.Timestamp
                            };

                            bulkInsert.Table = bulkInsert.BatchText.Split(' ')[2];
                            if (bulkInsert.Table.Contains('('))
                            {
                                bulkInsert.Table = bulkInsert.Table.Substring(0, bulkInsert.Table.IndexOf('('));
                            }
                            string[] columns = bulkInsert.BatchText.GetParenthesesContent().Split(", ");
                            foreach (string col in columns)
                            {
                                string[] columnInfo = col.Split(' ');
                                bulkInsert.Columns.Add(new Column {
                                    Name = columnInfo[0], SqlDbType = GetSqlDbType(columnInfo[1])
                                });
                            }

                            if (bulkInsert.BatchText.Contains(" with ("))
                            {
                                string[] settings = bulkInsert.BatchText
                                                    .GetParenthesesContent(bulkInsert.BatchText.IndexOf(" with (") + 6).Split(", ");
                                foreach (string setting in settings)
                                {
                                    if (setting == "CHECK_CONSTRAINTS")
                                    {
                                        bulkInsert.CheckConstraints = true;
                                    }
                                    else if (setting == "FIRE_TRIGGERS")
                                    {
                                        bulkInsert.FireTriggers = true;
                                        break;
                                    }
                                }
                            }

                            evt = bulkInsert;
                        }
                        else if (xevent.Name == "sql_batch_completed" &&
                                 xevent.Fields["batch_text"].ToString().Contains("insert bulk"))
                        {
                            if (!sessionDictionary.TryGetValue(xevent.Actions["session_id"].ToString(), out var session))
                            {
                                throw new Exception(
                                    $"Could not find session ID {xevent.Actions["session_id"].ToString()} for bulk insert.");
                            }
                            var bulkInsert = (BulkInsert)session.Events
                                             .FirstOrDefault(e =>
                                                             (e as BulkInsert)?.TransactionId ==
                                                             xevent.Actions["transaction_id"].ToString() &&
                                                             (e as BulkInsert)?.BatchText == xevent.Fields["batch_text"].ToString());
                            if (bulkInsert != null)
                            {
                                bulkInsert.RowCount = int.Parse(xevent.Fields["row_count"].ToString());
                                AddBulkInsertData(bulkInsert, con);
                            }
                        }

                        if (evt != null)
                        {
                            string sessionId = xevent.Actions["session_id"].ToString();
                            Session session  = sessionDictionary.GetOrAdd(sessionId, new Session()
                            {
                                SessionId = sessionId
                            });
                            session.Events.Add(evt);
                        }
                        return(Task.CompletedTask);
                    }, CancellationToken.None);
                }
            }

            var sessions = sessionDictionary.Values.ToList();

            //Remove any sessions with no events
            sessions.RemoveAll(s => s.Events.Count == 0);
            foreach (Session session in sessions)
            {
                //Remove any bulk inserts where we never found a corresponding sql_batch_completed
                session.Events.RemoveAll(e => (e as BulkInsert)?.RowCount == 0);
                session.Events = session.Events.OrderBy(e => e.EventSequence).ToList();
            }

            var run = new Run()
            {
                Sessions = sessions.Where(s => s.Events.Count > 0).OrderBy(s => s.Events.First().Timestamp).ToList()
            };

            run.EventCaptureOrigin = run.Sessions.First().Events.First().Timestamp;
            return(run);
        }