Add upgrade functionality and support for schema-based operations
Introduced new features including database upgrade logic, schema comparison, and schema-based updates. Refactored main program structure for modularity. Added unit tests and updated configuration files to support upgrades and enhanced mapping functionality.
This commit is contained in:
parent
43f492745f
commit
7072399225
577
tbfDBBackup.Tests/Resources/new-r.sql
Normal file
577
tbfDBBackup.Tests/Resources/new-r.sql
Normal file
File diff suppressed because one or more lines are too long
720
tbfDBBackup.Tests/Resources/new.sql
Normal file
720
tbfDBBackup.Tests/Resources/new.sql
Normal file
File diff suppressed because one or more lines are too long
76644
tbfDBBackup.Tests/Resources/old-r.sql
Normal file
76644
tbfDBBackup.Tests/Resources/old-r.sql
Normal file
File diff suppressed because it is too large
Load Diff
15879
tbfDBBackup.Tests/Resources/old.sql
Normal file
15879
tbfDBBackup.Tests/Resources/old.sql
Normal file
File diff suppressed because it is too large
Load Diff
815
tbfDBBackup.Tests/Resources/schema-mapping.json
Normal file
815
tbfDBBackup.Tests/Resources/schema-mapping.json
Normal file
@ -0,0 +1,815 @@
|
||||
{
|
||||
"Tables": [
|
||||
{
|
||||
"TableName": "procedure",
|
||||
"ColumnMappings": [
|
||||
{
|
||||
"OldColumn": "Id",
|
||||
"NewColumn": "Id",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "Id",
|
||||
"Type": "int(11)",
|
||||
"IsPrimaryKey": true,
|
||||
"Nullable": "NO"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "ItemNr",
|
||||
"NewColumn": "ItemNr",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "ItemNr",
|
||||
"Type": "int(11)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "Name",
|
||||
"NewColumn": "Name",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "Name",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "Description",
|
||||
"NewColumn": "Description",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "Description",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "CreationUser",
|
||||
"NewColumn": "CreationUser",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "CreationUser",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "CreationTime",
|
||||
"NewColumn": "CreationTime",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "CreationTime",
|
||||
"Type": "datetime",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "LastChgUser",
|
||||
"NewColumn": "LastChgUser",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "LastChgUser",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "LastChgTime",
|
||||
"NewColumn": "LastChgTime",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "LastChgTime",
|
||||
"Type": "datetime",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "LongDescription",
|
||||
"NewColumn": "LongDescription",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "LongDescription",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "ProcedureState",
|
||||
"NewColumn": "ProcedureState",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "ProcedureState",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "Revision",
|
||||
"NewColumn": "Revision",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "Revision",
|
||||
"Type": "int(11)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "PredecessorId",
|
||||
"NewColumn": "PredecessorId",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "PredecessorId",
|
||||
"Type": "int(11)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "ObtainedByCopy",
|
||||
"NewColumn": "ObtainedByCopy",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "ObtainedByCopy",
|
||||
"Type": "tinyint(1)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "MetersKind",
|
||||
"NewColumn": "MetersKind",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "MetersKind",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "Watermeters",
|
||||
"NewColumn": "Watermeters",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "Watermeters",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "ProtocolTitle",
|
||||
"Status": "new",
|
||||
"Note": "New",
|
||||
"ColumnDef": {
|
||||
"Name": "ProtocolTitle",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "Protected",
|
||||
"NewColumn": "Protected",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "Protected",
|
||||
"Type": "tinyint(1)",
|
||||
"Nullable": "NO"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "MustBeComplete",
|
||||
"NewColumn": "MustBeComplete",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "MustBeComplete",
|
||||
"Type": "tinyint(1)",
|
||||
"Nullable": "NO"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "ManualCtrlDisabled",
|
||||
"NewColumn": "ManualCtrlDisabled",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "ManualCtrlDisabled",
|
||||
"Type": "tinyint(1)",
|
||||
"Nullable": "NO"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "DataEntry",
|
||||
"NewColumn": "DataEntry",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "DataEntry",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "ResultsPrinter",
|
||||
"NewColumn": "ResultsPrinter",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "ResultsPrinter",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "ResultsWriter",
|
||||
"NewColumn": "ResultsWriter",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "ResultsWriter",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "TransitionStart",
|
||||
"NewColumn": "TransitionStart",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "TransitionStart",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "TransitionEnd",
|
||||
"NewColumn": "TransitionEnd",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "TransitionEnd",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "AltProcName",
|
||||
"NewColumn": "AltProcName",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "AltProcName",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "AltProcPeriod",
|
||||
"NewColumn": "AltProcPeriod",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "AltProcPeriod",
|
||||
"Type": "int(11)",
|
||||
"Nullable": "NO"
|
||||
}
|
||||
}
|
||||
],
|
||||
"IsNewTable": false
|
||||
},
|
||||
{
|
||||
"TableName": "test",
|
||||
"ColumnMappings": [
|
||||
{
|
||||
"OldColumn": "Id",
|
||||
"NewColumn": "Id",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "Id",
|
||||
"Type": "int(11)",
|
||||
"IsPrimaryKey": true,
|
||||
"Nullable": "NO"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "ItemNr",
|
||||
"NewColumn": "ItemNr",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "ItemNr",
|
||||
"Type": "int(11)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "Name",
|
||||
"NewColumn": "Name",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "Name",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "Part",
|
||||
"NewColumn": "Part",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "Part",
|
||||
"Type": "int(11)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "Publish",
|
||||
"NewColumn": "Publish",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "Publish",
|
||||
"Type": "tinyint(4)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "Evaluate",
|
||||
"NewColumn": "DoEvaluate",
|
||||
"Status": "Renamed",
|
||||
"Note": "",
|
||||
"ColumnDef": {
|
||||
"Name": "Evaluate",
|
||||
"Type": "tinyint(1)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "Qfrom",
|
||||
"NewColumn": "Qfrom",
|
||||
"Status": "Change",
|
||||
"Note": "Could be part of JSON or renamed",
|
||||
"ColumnDefList": [{
|
||||
"Name": "Qfrom",
|
||||
"Type": "float",
|
||||
"Nullable": "YES"
|
||||
},
|
||||
{
|
||||
"Name": "Qfrom",
|
||||
"Type": "double",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"OldColumn": "Qto",
|
||||
"NewColumn": "Qto",
|
||||
"Status": "Change",
|
||||
"Note": "",
|
||||
"ColumnDefList": [
|
||||
{
|
||||
"Name": "Qto",
|
||||
"Type": "float",
|
||||
"Nullable": "YES"
|
||||
},
|
||||
{
|
||||
"Name": "Qto",
|
||||
"Type": "double",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"OldColumn": "Volume",
|
||||
"Status": "Change",
|
||||
"Note": "",
|
||||
"ColumnDefList": [
|
||||
{
|
||||
"Name": "Volume",
|
||||
"Type": "float",
|
||||
"Nullable": "YES"
|
||||
},
|
||||
{
|
||||
"Name": "Volume",
|
||||
"Type": "double",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"OldColumn": "TstTime",
|
||||
"NewColumn": "TestTime",
|
||||
"Status": "update",
|
||||
"Note": "Could be part of JSON or renamed",
|
||||
"ColumnDefList": [
|
||||
{
|
||||
"Name": "TstTime",
|
||||
"Type": "float",
|
||||
"Nullable": "YES"
|
||||
},
|
||||
{
|
||||
"Name": "TestTime",
|
||||
"Type": "double",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"OldColumn": "Repeats",
|
||||
"NewColumn": "Repeats",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "Repeats",
|
||||
"Type": "int(11)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "Emptying",
|
||||
"NewColumn": "DoDraining",
|
||||
"Status": "Renamed",
|
||||
"Note": "",
|
||||
"ColumnDef": {
|
||||
"Name": "Emptying",
|
||||
"Type": "tinyint(1)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "Zeroing",
|
||||
"Status": "uncertain",
|
||||
"Note": "Could be part of JSON or renamed",
|
||||
"ColumnDef": {
|
||||
"Name": "Zeroing",
|
||||
"Type": "tinyint(1)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "DoControlWaterTemp",
|
||||
"Status": "uncertain",
|
||||
"Note": "Could be part of JSON or renamed",
|
||||
"ColumnDef": {
|
||||
"Name": "DoControlWaterTemp",
|
||||
"Type": "tinyint(1)",
|
||||
"Nullable": "NO"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "TempLimLo",
|
||||
"NewColumn": "TempLimLo",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "TempLimLo",
|
||||
"Type": "float",
|
||||
"Nullable": "NO"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "TempLimHi",
|
||||
"NewColumn": "TempLimHi",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "TempLimHi",
|
||||
"Type": "float",
|
||||
"Nullable": "NO"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "PumpPower",
|
||||
"NewColumn": "PumpPower",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "PumpPower",
|
||||
"Type": "float",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "MassRepeats",
|
||||
"NewColumn": "MassRepeats",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "MassRepeats",
|
||||
"Type": "int(11)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "MassSpread",
|
||||
"NewColumn": "MassSpread",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "MassSpread",
|
||||
"Type": "float",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "MassMethod",
|
||||
"NewColumn": "MassMethod",
|
||||
"Status": "Changed",
|
||||
"Note": "`MassMethod` tinyint(3) unsigned DEFAULT NULL,",
|
||||
"ColumnDefList": [
|
||||
{
|
||||
"Name": "MassMethod",
|
||||
"Type": "tinyint(1)",
|
||||
"Nullable": "YES"
|
||||
},
|
||||
{
|
||||
"Name": "MassMethod",
|
||||
"Type": "tinyint(3)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
|
||||
]
|
||||
},
|
||||
{
|
||||
"OldColumn": "TimeBeforeFlow",
|
||||
"NewColumn": "TimeBeforeFlow",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "TimeBeforeFlow",
|
||||
"Type": "int(11)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "TimeFlow2Mass",
|
||||
"NewColumn": "TimeFlow2Mass",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "TimeFlow2Mass",
|
||||
"Type": "int(11)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "TimeMass2Start",
|
||||
"NewColumn": "TimePump2StartV",
|
||||
"Status": "Renamed",
|
||||
"Note": "",
|
||||
"ColumnDef": {
|
||||
"Name": "TimeMass2Start",
|
||||
"Type": "int(11)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "TimeStop2Mass",
|
||||
"NewColumn": "TimeStop2Mass",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "TimeStop2Mass",
|
||||
"Type": "int(11)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "Method",
|
||||
"NewColumn": "Method",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "Method",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "ErrLimLo",
|
||||
"NewColumn": "ErrLimLo",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "ErrLimLo",
|
||||
"Type": "float",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "ErrLimHi",
|
||||
"NewColumn": "ErrLimHi",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "ErrLimHi",
|
||||
"Type": "float",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "Uncertainty",
|
||||
"NewColumn": "Uncertainty",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "Uncertainty",
|
||||
"Type": "float",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "TolerRed",
|
||||
"Status": "Deleted",
|
||||
"ColumnDef": {
|
||||
"Name": "TolerRed",
|
||||
"Type": "double",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "RedType",
|
||||
"Status": "Deleted",
|
||||
"ColumnDef": {
|
||||
"Name": "RedType",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "FeedingPath",
|
||||
"NewColumn": "FeedingPath",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "FeedingPath",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "BenchPath",
|
||||
"NewColumn": "BenchPath",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "BenchPath",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "OutputPath",
|
||||
"NewColumn": "OutputPath",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "OutputPath",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "MetersPath",
|
||||
"NewColumn": "MetersPath",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "MetersPath",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "HeatMetersPath",
|
||||
"NewColumn": "HeatMetersPath",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "HeatMetersPath",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "RelTransBefore",
|
||||
"NewColumn": "TransBefore",
|
||||
"Status": "Renamed",
|
||||
"ColumnDef": {
|
||||
"Name": "RelTransBefore",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "RelTransBetween",
|
||||
"NewColumn": "TransBetween",
|
||||
"Status": "Renamed",
|
||||
"Note": "",
|
||||
"ColumnDef": {
|
||||
"Name": "RelTransBetween",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "RelTransAfter",
|
||||
"NewColumn": "TransAfter",
|
||||
"Status": "Renamed",
|
||||
"Note": "",
|
||||
"ColumnDef": {
|
||||
"Name": "RelTransAfter",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "TransitionAfter",
|
||||
"Status": "Deleted",
|
||||
"Note": "",
|
||||
"ColumnDef": {
|
||||
"Name": "TransitionAfter",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "Procedure_id",
|
||||
"NewColumn": "Procedure_id",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "Procedure_id",
|
||||
"Type": "int(11)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
}
|
||||
],
|
||||
"IsNewTable": false
|
||||
},
|
||||
{
|
||||
"TableName": "componentprocedure",
|
||||
"ColumnMappings": [
|
||||
{
|
||||
"OldColumn": "Id",
|
||||
"NewColumn": "Id",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "Id",
|
||||
"Type": "int(11)",
|
||||
"IsPrimaryKey": true,
|
||||
"Nullable": "NO"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "CmpntName",
|
||||
"NewColumn": "CmpntName",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "CmpntName",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "Parameters",
|
||||
"NewColumn": "Parameters",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "Parameters",
|
||||
"Type": "varchar(8000)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "Procedure_id",
|
||||
"NewColumn": "Procedure_id",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "Procedure_id",
|
||||
"Type": "int(11)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
}
|
||||
],
|
||||
"IsNewTable": false
|
||||
},
|
||||
{
|
||||
"TableName": "componenttest",
|
||||
"ColumnMappings": [
|
||||
{
|
||||
"OldColumn": "Id",
|
||||
"NewColumn": "Id",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "Id",
|
||||
"Type": "int(11)",
|
||||
"IsPrimaryKey": true,
|
||||
"Nullable": "NO"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "CmpntName",
|
||||
"NewColumn": "CmpntName",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "CmpntName",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "Parameters",
|
||||
"NewColumn": "Parameters",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "Parameters",
|
||||
"Type": "varchar(8000)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "Test_id",
|
||||
"NewColumn": "Test_id",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "Test_id",
|
||||
"Type": "int(11)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
}
|
||||
],
|
||||
"IsNewTable": false
|
||||
}
|
||||
|
||||
]
|
||||
}
|
||||
52
tbfDBBackup.Tests/Resources/test_Block.sql
Normal file
52
tbfDBBackup.Tests/Resources/test_Block.sql
Normal file
@ -0,0 +1,52 @@
|
||||
CREATE TABLE IF NOT EXISTS `test` (
|
||||
`Id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`ItemNr` int(11) DEFAULT NULL,
|
||||
`Name` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
|
||||
`Part` int(11) DEFAULT NULL,
|
||||
`Publish` tinyint(4) DEFAULT NULL,
|
||||
`Evaluate` tinyint(1) DEFAULT NULL,
|
||||
`Qfrom` float DEFAULT NULL,
|
||||
`Qto` float DEFAULT NULL,
|
||||
`Volume` float DEFAULT NULL,
|
||||
`TstTime` float DEFAULT NULL,
|
||||
`Repeats` int(11) DEFAULT NULL,
|
||||
`Emptying` tinyint(1) DEFAULT NULL,
|
||||
`Zeroing` tinyint(1) DEFAULT NULL,
|
||||
`DoControlWaterTemp` tinyint(1) NOT NULL DEFAULT '0',
|
||||
`TempLimLo` float NOT NULL DEFAULT '15',
|
||||
`TempLimHi` float NOT NULL DEFAULT '25',
|
||||
`PumpPower` float DEFAULT NULL,
|
||||
`MassRepeats` int(11) DEFAULT NULL,
|
||||
`MassSpread` float DEFAULT NULL,
|
||||
`MassMethod` tinyint(1) DEFAULT NULL,
|
||||
`TimeBeforeFlow` int(11) DEFAULT NULL,
|
||||
`TimeFlow2Mass` int(11) DEFAULT NULL,
|
||||
`TimeMass2Start` int(11) DEFAULT NULL,
|
||||
`TimeStop2Mass` int(11) DEFAULT NULL,
|
||||
`Method` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
|
||||
`ErrLimLo` float DEFAULT NULL,
|
||||
`ErrLimHi` float DEFAULT NULL,
|
||||
`Uncertainty` float DEFAULT NULL,
|
||||
`TolerRed` double DEFAULT NULL,
|
||||
`RedType` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
|
||||
`FeedingPath` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
|
||||
`BenchPath` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
|
||||
`OutputPath` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
|
||||
`MetersPath` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
|
||||
`HeatMetersPath` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
|
||||
`RelTransBefore` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
|
||||
`RelTransBetween` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
|
||||
`RelTransAfter` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
|
||||
`TransitionAfter` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
|
||||
`Procedure_id` int(11) DEFAULT NULL,
|
||||
PRIMARY KEY (`Id`),
|
||||
KEY `Procedure_id` (`Procedure_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=4322 ;
|
||||
|
||||
--
|
||||
-- Sťahujem dáta pre tabuľku `test`
|
||||
--
|
||||
|
||||
INSERT INTO `test` (`Id`, `ItemNr`, `Name`, `Part`, `Publish`, `Evaluate`, `Qfrom`, `Qto`, `Volume`, `TstTime`, `Repeats`, `Emptying`, `Zeroing`, `DoControlWaterTemp`, `TempLimLo`, `TempLimHi`, `PumpPower`, `MassRepeats`, `MassSpread`, `MassMethod`, `TimeBeforeFlow`, `TimeFlow2Mass`, `TimeMass2Start`, `TimeStop2Mass`, `Method`, `ErrLimLo`, `ErrLimHi`, `Uncertainty`, `TolerRed`, `RedType`, `FeedingPath`, `BenchPath`, `OutputPath`, `MetersPath`, `HeatMetersPath`, `RelTransBefore`, `RelTransBetween`, `RelTransAfter`, `TransitionAfter`, `Procedure_id`) VALUES
|
||||
(1, 0, 'Test1', 0, 1, 1, 2, 2.2, 58.3333, 100, 1, 0, 0, 0, 15, 25, 60, 0, 0, 0, 10, 5, 1, 5, 'FlyingStart.Single', -2, 2, 0, 0, 'Fix', 'CFeed1', 'PBench1', 'CPQ1B', 'PSens1', NULL, '', '', '', '', 4),
|
||||
(2, 0, 'Test1', 0, 1, 1, 2, 2.2, 100, 171.429, 1, 0, 0, 0, 15, 25, 60, 0, 0, 0, 10, 5, 1, 5, 'FlyingStart.Single', -2, 2, 0, 0, 'Fix', 'CFeed1', 'PBench1', 'CPQ1B', 'PSens1', NULL, '', '', '', '', 5);
|
||||
@ -0,0 +1,111 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using JetBrains.Annotations;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using tbfDBBackup.compare_dumps.Parserer;
|
||||
|
||||
namespace tbfDBBackup.Tests.compare_dumps.Parserer;
|
||||
|
||||
[TestClass]
|
||||
[TestSubject(typeof(SqlDumpFileParser))]
|
||||
public class SqlDumpFileParserTest
|
||||
{
|
||||
|
||||
string GetProjectRoot() {
|
||||
string dir = AppContext.BaseDirectory;
|
||||
while (dir != null && !Directory.GetFiles(dir, "*.csproj").Any()) {
|
||||
dir = Directory.GetParent(dir)?.FullName;
|
||||
}
|
||||
return dir ?? throw new Exception("Project root not found.");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void SqlDumpParserFile()
|
||||
{
|
||||
string basePath = GetProjectRoot();
|
||||
string sql = Path.Combine(basePath,"Resources/old.sql");
|
||||
|
||||
ValidateSqlDumpParserResults(sql);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void SqlDumpParserFile2()
|
||||
{
|
||||
string basePath = GetProjectRoot();
|
||||
string sql = Path.Combine(basePath,"Resources/new.sql");
|
||||
|
||||
ValidateSqlDumpParserResults(sql);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void SqlDumpParserFileR()
|
||||
{
|
||||
string basePath = GetProjectRoot();
|
||||
string sql = Path.Combine(basePath,"Resources/old-r.sql");
|
||||
|
||||
ValidateSqlDumpParserResults(sql);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void SqlDumpParserFileR2()
|
||||
{
|
||||
string basePath = GetProjectRoot();
|
||||
string sql = Path.Combine(basePath,"Resources/new-r.sql");
|
||||
|
||||
ValidateSqlDumpParserResults(sql);
|
||||
}
|
||||
|
||||
private static void ValidateSqlDumpParserResults(string sql)
|
||||
{
|
||||
SqlDumpFileParser parser = new();
|
||||
parser.SqlDumpParserFile(sql);
|
||||
|
||||
Assert.IsTrue(parser.TableDefinitions.Count > 1);
|
||||
foreach (var table in parser.TableDefinitions)
|
||||
{
|
||||
Console.WriteLine(table.Key);
|
||||
Assert.IsTrue(table.Value.Substring(0, Math.Min(50, table.Value.Length)).Contains("CREATE"));
|
||||
}
|
||||
|
||||
Assert.IsTrue(parser.TableInserts.Count > 1);
|
||||
|
||||
foreach (var table in parser.TableInserts)
|
||||
{
|
||||
Console.WriteLine(table.Key);
|
||||
foreach (var row in table.Value)
|
||||
{
|
||||
Assert.IsTrue(row.Substring(0, Math.Min(20, row.Length-1)).Contains("INSERT INTO"));
|
||||
string restString = row.Substring(20);
|
||||
if (restString.Contains("INSERT INTO"))
|
||||
{
|
||||
Assert.Fail($"Insert contains insert more than once, see: {row}");
|
||||
}
|
||||
|
||||
string lastCharacters = row.Length >= 5 ? row.Substring(row.Length - 5) : "";
|
||||
Assert.IsTrue(lastCharacters.Contains(';'));
|
||||
}
|
||||
}
|
||||
|
||||
Assert.IsTrue(parser.TableForeignKeys.Count > 1);
|
||||
|
||||
foreach (var table in parser.TableForeignKeys)
|
||||
{
|
||||
Console.WriteLine(table.Key);
|
||||
foreach (var row in table.Value)
|
||||
{
|
||||
//check if it contains alter table
|
||||
Assert.IsTrue(row.Substring(0, Math.Min(20, row.Length-1)).Contains("ALTER TABLE"));
|
||||
//check rest of string for alter table - non valid sql
|
||||
string restString = row.Substring(20);
|
||||
if (restString.Contains("ALTER TABLE"))
|
||||
{
|
||||
Assert.Fail($"Alter contains insert more than once, see: {row}");
|
||||
}
|
||||
//check if it ends with ;
|
||||
string lastCharacters = row.Length >= 5 ? row.Substring(row.Length - 5) : "";
|
||||
Assert.IsTrue(lastCharacters.Contains(';'));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
71
tbfDBBackup.Tests/compare_dumps/SqlDumpParserTest.cs
Normal file
71
tbfDBBackup.Tests/compare_dumps/SqlDumpParserTest.cs
Normal file
@ -0,0 +1,71 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using JetBrains.Annotations;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using tbfDBBackup.compare_dumps;
|
||||
using tbfDBBackup.compare_dumps.Parserer;
|
||||
|
||||
namespace tbfDBBackup.Tests.compare_dumps;
|
||||
|
||||
[TestClass]
|
||||
[TestSubject(typeof(SqlDumpParser))]
|
||||
public class SqlDumpParserTest
|
||||
{
|
||||
|
||||
[TestMethod]
|
||||
public void ParseInsertBlock()
|
||||
{
|
||||
string sqlDump = "INSERT INTO `componentprocedure` (`Id`, `CmpntName`, `Parameters`, `Procedure_id`) " +
|
||||
"VALUES\n(1, 'WM1', '<?xml version=\"1.0\" encoding=\"utf-16\"?>\\r\\n<ProcParams xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">\\r\\n " +
|
||||
"<ProductName />\\r\\n <Producer />\\r\\n <DN>0</DN>\\r\\n <L>0</L>\\r\\n <Mounting>NotSpecified</Mounting>\\r\\n <Qmax>4</Qmax>\\r\\n <Qn>2.5</Qn>\\r\\n <Qt>0.005</Qt>\\r\\n <Qmin>0.003125</Qmin>\\r\\n <MetrologicalClass>A</MetrologicalClass>\\r\\n <TemperatureClass>NotSpecified</TemperatureClass>\\r\\n <PressureLossClass>NotSpecified</PressureLossClass>\\r\\n <MaxAdmissiblePressure>NotSpecified</MaxAdmissiblePressure>\\r\\n <FlowProfileSensitivityClass>NotSpecified</FlowProfileSensitivityClass>\\r\\n <ApprovalInfo />\\r\\n <Certificate />\\r\\n <PulsesPerLtr>1</PulsesPerLtr>\\r\\n <Text1 />\\r\\n <Text2 />\\r\\n <Text3 />\\r\\n <Text4 />\\r\\n <Text5 />\\r\\n <WaterTemp>ColdWater</WaterTemp>\\r\\n</ProcParams>', 1),\n(2, 'WM2', '<?xml version=\"1.0\" encoding=\"utf-16\"?>\\r\\n<ProcParams xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">\\r\\n <ProductName />\\r\\n <Producer />\\r\\n <DN>0</DN>\\r\\n <L>0</L>\\r\\n <Mounting>NotSpecified</Mounting>\\r\\n <Qmax>4</Qmax>\\r\\n <Qn>2.5</Qn>\\r\\n <Qt>0.005</Qt>\\r\\n <Qmin>0.003125</Qmin>\\r\\n <MetrologicalClass>A</MetrologicalClass>\\r\\n <TemperatureClass>NotSpecified</TemperatureClass>\\r\\n <PressureLossClass>NotSpecified</PressureLossClass>\\r\\n <MaxAdmissiblePressure>NotSpecified</MaxAdmissiblePressure>\\r\\n <FlowProfileSensitivityClass>NotSpecified</FlowProfileSensitivityClass>\\r\\n " +
|
||||
"<ApprovalInfo />\\r\\n <Certificate />\\r\\n <PulsesPerLtr>1</PulsesPerLtr>\\r\\n <Text1 />\\r\\n <Text2 />\\r\\n <Text3 />\\r\\n <Text4 />\\r\\n <Text5 />\\r\\n " +
|
||||
"<WaterTemp>ColdWater</WaterTemp>\\r\\n</ProcParams>', 1);";
|
||||
Dictionary<int, Dictionary<string, string>> dictionary = SqlDumpParser.ParseInsertBlock(sqlDump);
|
||||
|
||||
Assert.AreEqual(2, dictionary.Count);
|
||||
}
|
||||
|
||||
|
||||
string GetProjectRoot() {
|
||||
string dir = AppContext.BaseDirectory;
|
||||
while (dir != null && !Directory.GetFiles(dir, "*.csproj").Any()) {
|
||||
dir = Directory.GetParent(dir)?.FullName;
|
||||
}
|
||||
return dir ?? throw new Exception("Project root not found.");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ParseInsertBlock_File()
|
||||
{
|
||||
string projectRoot = GetProjectRoot();
|
||||
string sql = File.ReadAllText( Path.Combine(projectRoot, "Resources","test_Block.sql"));
|
||||
|
||||
var parsed = SqlDumpParser.ParseInsertBlock(sql);
|
||||
foreach (var kvp in parsed)
|
||||
{
|
||||
Console.WriteLine($"ID {kvp.Key}:");
|
||||
//Get first 50 chars for all colums
|
||||
foreach (var col in kvp.Value)
|
||||
Console.WriteLine($" {col.Key} = {col.Value.Substring(0, Math.Min(80, col.Value.Length))}...");
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ParseForeignKeys()
|
||||
{
|
||||
string alter = "ALTER TABLE `componentprocedure`\n ADD CONSTRAINT `FKF52C29EE1EC52E2B` FOREIGN KEY (`Procedure_id`) REFERENCES `procedure` (`Id`);";
|
||||
|
||||
Dictionary<string, List<ForeignKeyDef>> foreignKeys = SqlDumpParser.ParseForeignKeys(alter);
|
||||
|
||||
Assert.AreEqual(1, foreignKeys.Count);
|
||||
Assert.AreEqual(1, foreignKeys.First().Value.Count);
|
||||
Assert.AreEqual("componentprocedure", foreignKeys.First().Key);
|
||||
|
||||
Assert.AreEqual("FKF52C29EE1EC52E2B", foreignKeys.First().Value.First().Name);
|
||||
Assert.AreEqual("Procedure_id", foreignKeys.First().Value.First().Column);
|
||||
Assert.AreEqual("procedure", foreignKeys.First().Value.First().RefTable);
|
||||
Assert.AreEqual("Id", foreignKeys.First().Value.First().RefColumn);
|
||||
}
|
||||
}
|
||||
65
tbfDBBackup.Tests/compare_dumps/joinValues/JoinerTest.cs
Normal file
65
tbfDBBackup.Tests/compare_dumps/joinValues/JoinerTest.cs
Normal file
@ -0,0 +1,65 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using JetBrains.Annotations;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using tbfDBBackup.compare_dumps.joinValues;
|
||||
using tbfDBBackup.configuration;
|
||||
|
||||
namespace tbfDBBackup.Tests.compare_dumps.joinValues;
|
||||
|
||||
[TestClass]
|
||||
[TestSubject(typeof(Joiner))]
|
||||
public class JoinerTest
|
||||
{
|
||||
|
||||
string GetProjectRoot() {
|
||||
string dir = AppContext.BaseDirectory;
|
||||
while (dir != null && !Directory.GetFiles(dir, "*.csproj").Any()) {
|
||||
dir = Directory.GetParent(dir)?.FullName;
|
||||
}
|
||||
return dir ?? throw new Exception("Project root not found.");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void SchemaJoiner()
|
||||
{
|
||||
// Arrange - project test
|
||||
string projectRoot = GetProjectRoot();
|
||||
//Configure test database
|
||||
Configuration dbConfiguration = new Configuration();
|
||||
|
||||
dbConfiguration.DbConnectionStrings = new List<DbConnection>();
|
||||
dbConfiguration.DbConnectionStrings.Add(new DbConnection()
|
||||
{
|
||||
Connection = "SERVER=localhost; DATABASE={DatabaseName}; UID=root; PASSWORD=; CHARSET=utf8;",
|
||||
DatabaseName = "testdbupdate",
|
||||
Enabled = true,
|
||||
IsOneTimeOpaque = true,
|
||||
Name = "test",
|
||||
});
|
||||
dbConfiguration.UpgradeDatabase = new List<Upgrade>();
|
||||
dbConfiguration.UpgradeDatabase.Add(new Upgrade()
|
||||
{
|
||||
DatabaseName = "testdbupdate",
|
||||
Enabled = true,
|
||||
Name = "test upgrade",
|
||||
JSONFileName = "",
|
||||
Query = "",
|
||||
IsOneTimeOpaque = true
|
||||
});
|
||||
|
||||
|
||||
Joiner joiner = new Joiner(
|
||||
dbConfiguration,
|
||||
projectRoot,
|
||||
"Resources/old.sql",
|
||||
"Resources/schema-mapping.json");
|
||||
|
||||
joiner.SchemaJoiner();
|
||||
|
||||
Assert.IsTrue(joiner.IsJoindedSuccesfully);
|
||||
|
||||
}
|
||||
}
|
||||
20
tbfDBBackup.Tests/tbfDBBackup.Tests.csproj
Normal file
20
tbfDBBackup.Tests/tbfDBBackup.Tests.csproj
Normal file
@ -0,0 +1,20 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net8.0</TargetFrameworks>
|
||||
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="JetBrains.Annotations" Version="2025.2.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
|
||||
<PackageReference Include="MSTest.TestAdapter" Version="3.10.1" />
|
||||
<PackageReference Include="MSTest.TestFramework" Version="3.10.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\tbfDBBackup\tbfDBBackup.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@ -2,6 +2,8 @@
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "tbfDBBackup", "tbfDBBackup\tbfDBBackup.csproj", "{9F4F004F-8E31-42B3-BE6D-EA9453EADC7F}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "tbfDBBackup.Tests", "tbfDBBackup.Tests\tbfDBBackup.Tests.csproj", "{0D1C3FA3-7971-4710-9DDC-E498EC635989}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@ -12,5 +14,9 @@ Global
|
||||
{9F4F004F-8E31-42B3-BE6D-EA9453EADC7F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{9F4F004F-8E31-42B3-BE6D-EA9453EADC7F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{9F4F004F-8E31-42B3-BE6D-EA9453EADC7F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{0D1C3FA3-7971-4710-9DDC-E498EC635989}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{0D1C3FA3-7971-4710-9DDC-E498EC635989}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{0D1C3FA3-7971-4710-9DDC-E498EC635989}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{0D1C3FA3-7971-4710-9DDC-E498EC635989}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
||||
@ -24,6 +24,10 @@ public class Configuration
|
||||
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
public List<Backup>? BackupDB { get; set; }
|
||||
|
||||
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
public List<Upgrade>? UpgradeDatabase { get; set; }
|
||||
|
||||
|
||||
public static Configuration DeserializeFromJson(string jsonString)
|
||||
|
||||
@ -1,281 +1,485 @@
|
||||
// See https://aka.ms/new-console-template for more information
|
||||
|
||||
using System.Diagnostics;
|
||||
using System.Text.Json;
|
||||
using System.Text.RegularExpressions;
|
||||
using MySqlConnector;
|
||||
using tbfDBBackup;
|
||||
using tbfDBBackup.compare_dumps;
|
||||
using tbfDBBackup.compare_dumps.joinValues;
|
||||
using tbfDBBackup.compare_dumps.mapping;
|
||||
using tbfDBBackup.configuration;
|
||||
|
||||
namespace tbfDBBackup;
|
||||
|
||||
Console.WriteLine("---- TBF DB Backup process started -----");
|
||||
//Read configuration
|
||||
Configuration? configuration = GetConfiguration();
|
||||
|
||||
if (configuration == null)
|
||||
public class Program
|
||||
{
|
||||
Console.WriteLine("**** Configuration no found!! ***");
|
||||
return -1;
|
||||
}
|
||||
private static string ProgramName = Path.GetFileNameWithoutExtension(Environment.GetCommandLineArgs()[0]);
|
||||
private static string defaultSchemaFimeName = "schema-mapping.json";
|
||||
|
||||
bool storeConfigPotentialChanges = configuration.HasPotentialModification();
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
// Entry point with args support
|
||||
if (args.Length > 0)
|
||||
{
|
||||
string command = args[0].ToLowerInvariant();
|
||||
|
||||
switch (command)
|
||||
{
|
||||
case "compare":
|
||||
RunSchemaComparison(args);
|
||||
return;
|
||||
case "test-schema-mapping":
|
||||
RunTestSchemaMapping(args.Length > 1 ? args[1] : "");
|
||||
return;
|
||||
case "update-by-schema":
|
||||
RunUpdateBySchemaMapping(args);
|
||||
return;
|
||||
|
||||
case "help":
|
||||
PrintHelp();
|
||||
return;
|
||||
|
||||
default:
|
||||
Console.WriteLine($"Unknown command: {command}");
|
||||
PrintHelp();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Console.WriteLine("---- TBF DB Backup process started -----");
|
||||
//Read configuration
|
||||
Configuration? configuration = GetConfiguration();
|
||||
|
||||
if (configuration == null)
|
||||
{
|
||||
Console.WriteLine("**** Configuration no found!! ***");
|
||||
throw new Exception("Configuration no found!!");
|
||||
}
|
||||
|
||||
bool storeConfigPotentialChanges = configuration.HasPotentialModification();
|
||||
|
||||
//update part
|
||||
if (configuration.UpdateString != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
UpdateDb(configuration);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine("------ MySql Data uprade FAILED!! *** -----");
|
||||
Console.WriteLine(e);
|
||||
}
|
||||
}
|
||||
if (configuration.UpdateString != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
UpdateDb(configuration);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine("------ MySql Data uprade FAILED!! *** -----");
|
||||
Console.WriteLine(e);
|
||||
}
|
||||
}
|
||||
|
||||
//database backup part
|
||||
List<BackupCombination> backupCombinations = configuration.GetBackupCombinations();
|
||||
foreach (BackupCombination combination in backupCombinations)
|
||||
{
|
||||
try
|
||||
{
|
||||
BackupDatabase(combination);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine($"------ MySql backup of database: {combination.DatabaseName} FAILED!! *** -----");
|
||||
Console.WriteLine(e);
|
||||
}
|
||||
}
|
||||
List<BackupCombination> backupCombinations = configuration.GetBackupCombinations();
|
||||
foreach (BackupCombination combination in backupCombinations)
|
||||
{
|
||||
try
|
||||
{
|
||||
BackupDatabase(combination);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine($"------ MySql backup of database: {combination.DatabaseName} FAILED!! *** -----");
|
||||
Console.WriteLine(e);
|
||||
}
|
||||
}
|
||||
|
||||
//Update one time config
|
||||
//Upgrade one time config
|
||||
|
||||
if (configuration.UpgradeDatabase != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
UpgradeDb(configuration);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine("------ MySql Data upgrade FAILED!! *** -----");
|
||||
Console.WriteLine(e);
|
||||
}
|
||||
}
|
||||
|
||||
//store configuration
|
||||
if (storeConfigPotentialChanges)
|
||||
{
|
||||
SaveConfiguration(configuration);
|
||||
}
|
||||
if (storeConfigPotentialChanges)
|
||||
{
|
||||
SaveConfiguration(configuration);
|
||||
}
|
||||
|
||||
//final info
|
||||
Console.WriteLine("Program finished correctly!!");
|
||||
Console.WriteLine("Program finished correctly!!");
|
||||
|
||||
//wait to end
|
||||
if (configuration != null && (configuration.WaitOnEndCmdOpen ?? false))
|
||||
{
|
||||
Console.ReadLine();
|
||||
}
|
||||
|
||||
//program END
|
||||
return 0;
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Configuration? GetConfiguration()
|
||||
{
|
||||
try
|
||||
{
|
||||
Console.WriteLine($"---- program started path: {Environment.CurrentDirectory}");
|
||||
string fileNamePath = ConfigurationFileNamePath();
|
||||
Console.WriteLine($"- full config file path: {fileNamePath}");
|
||||
|
||||
|
||||
string jsonConfiguration = "";
|
||||
using (StreamReader reader = new StreamReader(fileNamePath))
|
||||
if (configuration != null && (configuration.WaitOnEndCmdOpen ?? false))
|
||||
{
|
||||
jsonConfiguration = reader.ReadToEnd();
|
||||
Console.ReadLine();
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
private static void UpgradeDb(Configuration configuration)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
Configuration? configurationDeserialized = Configuration.DeserializeFromJson(jsonConfiguration);
|
||||
if (configurationDeserialized != null && (configurationDeserialized.PrintConfigurationEnabled ?? false))
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static Configuration? GetConfiguration()
|
||||
{
|
||||
try
|
||||
{
|
||||
configurationDeserialized.PrintConfiguration();
|
||||
}
|
||||
Console.WriteLine($"---- program started path: {Environment.CurrentDirectory}");
|
||||
string fileNamePath = ConfigurationFileNamePath();
|
||||
Console.WriteLine($"- full config file path: {fileNamePath}");
|
||||
|
||||
return configurationDeserialized;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine(e);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
void SaveConfiguration(Configuration configuration)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Serialize the configuration back to JSON
|
||||
string jsonString = configuration.SerializeToJson();
|
||||
|
||||
string fileNamePath = ConfigurationFileNamePath();
|
||||
Console.WriteLine($"- full config file path: {fileNamePath}");
|
||||
|
||||
// Write the JSON string to the file
|
||||
using (StreamWriter writer = new StreamWriter(fileNamePath))
|
||||
{
|
||||
writer.Write(jsonString);
|
||||
}
|
||||
|
||||
Console.WriteLine("Configuration saved successfully.");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine($"Error saving configuration: {e}");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
void BackupDatabase(BackupCombination backupCombination)
|
||||
{
|
||||
Console.WriteLine($"------ MySql backup of database: {backupCombination.DatabaseName} started -----");
|
||||
DateTime currentTime = DateTime.Now; // Get current date and time
|
||||
|
||||
// Format the date and time as yyyyMMdd_HHmmss (e.g., 20241015_142530)
|
||||
string time = currentTime.ToString("yyyyMMdd_HHmmss");
|
||||
|
||||
// Create the file name by appending the formatted time to the database name
|
||||
string fileName = backupCombination.DatabaseName.Trim()
|
||||
.Replace('\\', '_')
|
||||
.Replace(' ', '_')
|
||||
.ToLower() + "_backup_" + time + ".sql";
|
||||
|
||||
string filePathName = Path.Combine(backupCombination.BackupFilePath, fileName);
|
||||
// Set up the mysqldump command
|
||||
string dumpCommand =
|
||||
$"mysqldump --user={backupCombination.UserName} --password={backupCombination.Password} --host={backupCombination.ServerName} {backupCombination.DatabaseName} --result-file=\"{filePathName}\" --routines --events";
|
||||
|
||||
// Check if the directory exists, and create it if not
|
||||
if (!Directory.Exists(backupCombination.BackupFilePath))
|
||||
{
|
||||
Directory.CreateDirectory(backupCombination.BackupFilePath);
|
||||
}
|
||||
|
||||
// Execute the mysqldump command
|
||||
ProcessStartInfo processInfo = new ProcessStartInfo
|
||||
{
|
||||
FileName = "cmd.exe",
|
||||
RedirectStandardInput = true,
|
||||
RedirectStandardOutput = true,
|
||||
RedirectStandardError = true,
|
||||
UseShellExecute = false,
|
||||
CreateNoWindow = true
|
||||
};
|
||||
|
||||
Process process = new Process
|
||||
{
|
||||
StartInfo = processInfo
|
||||
};
|
||||
|
||||
process.Start();
|
||||
|
||||
using (var writer = process.StandardInput)
|
||||
{
|
||||
if (writer.BaseStream.CanWrite)
|
||||
{
|
||||
if (backupCombination.CommandPath.Length == 0)
|
||||
string jsonConfiguration = "";
|
||||
using (StreamReader reader = new StreamReader(fileNamePath))
|
||||
{
|
||||
writer.WriteLine(dumpCommand);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Split the dumpCommand into the executable and the arguments
|
||||
string[]
|
||||
parts = dumpCommand.Split(' ', 2); // Split into two parts: the command and the rest (arguments)
|
||||
|
||||
// Combine the commandPath with the executable (first part of dumpCommand)
|
||||
string fullCommand = Path.Combine(backupCombination.CommandPath, parts[0]) + " " + parts[1];
|
||||
|
||||
// Execute the command with the full path
|
||||
writer.WriteLine(fullCommand);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
process.WaitForExit();
|
||||
|
||||
string result = process.StandardOutput.ReadToEnd();
|
||||
string error = process.StandardError.ReadToEnd();
|
||||
|
||||
if (!string.IsNullOrEmpty(error))
|
||||
{
|
||||
Console.WriteLine($"Error: {error}");
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine($"Backup created successfully at {filePathName}");
|
||||
}
|
||||
|
||||
process.Close();
|
||||
|
||||
//Deactivate if only one time possible run
|
||||
|
||||
if ((backupCombination.Path.IsOneTimeOpaque ?? false) && (backupCombination.Path.Enabled ?? true))
|
||||
{
|
||||
backupCombination.Path.Enabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateDb(Configuration dbConfiguration)
|
||||
{
|
||||
if (dbConfiguration.DbConnectionStrings != null)
|
||||
foreach (DbConnection dbConnection in dbConfiguration.DbConnectionStrings)
|
||||
{
|
||||
if (!(dbConnection.Enabled ?? true))
|
||||
{
|
||||
continue;
|
||||
jsonConfiguration = reader.ReadToEnd();
|
||||
}
|
||||
|
||||
if (dbConfiguration.UpdateString != null)
|
||||
foreach (Update update in dbConfiguration.UpdateString)
|
||||
Configuration? configurationDeserialized = Configuration.DeserializeFromJson(jsonConfiguration);
|
||||
if (configurationDeserialized != null && (configurationDeserialized.PrintConfigurationEnabled ?? false))
|
||||
{
|
||||
configurationDeserialized.PrintConfiguration();
|
||||
}
|
||||
|
||||
return configurationDeserialized;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine(e);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
static void SaveConfiguration(Configuration configuration)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Serialize the configuration back to JSON
|
||||
string jsonString = configuration.SerializeToJson();
|
||||
|
||||
string fileNamePath = ConfigurationFileNamePath();
|
||||
Console.WriteLine($"- full config file path: {fileNamePath}");
|
||||
|
||||
// Write the JSON string to the file
|
||||
using (StreamWriter writer = new StreamWriter(fileNamePath))
|
||||
{
|
||||
writer.Write(jsonString);
|
||||
}
|
||||
|
||||
Console.WriteLine("Configuration saved successfully.");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine($"Error saving configuration: {e}");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
static void BackupDatabase(BackupCombination backupCombination)
|
||||
{
|
||||
Console.WriteLine($"------ MySql backup of database: {backupCombination.DatabaseName} started -----");
|
||||
DateTime currentTime = DateTime.Now; // Get current date and time
|
||||
|
||||
// Format the date and time as yyyyMMdd_HHmmss (e.g., 20241015_142530)
|
||||
string time = currentTime.ToString("yyyyMMdd_HHmmss");
|
||||
|
||||
// Create the file name by appending the formatted time to the database name
|
||||
string fileName = backupCombination.DatabaseName.Trim()
|
||||
.Replace('\\', '_')
|
||||
.Replace(' ', '_')
|
||||
.ToLower() + "_backup_" + time + ".sql";
|
||||
|
||||
string filePathName = Path.Combine(backupCombination.BackupFilePath, fileName);
|
||||
// Set up the mysqldump command
|
||||
string dumpCommand =
|
||||
$"mysqldump --user={backupCombination.UserName} --password={backupCombination.Password} --host={backupCombination.ServerName} {backupCombination.DatabaseName} --result-file=\"{filePathName}\" --routines --events";
|
||||
|
||||
// Check if the directory exists, and create it if not
|
||||
if (!Directory.Exists(backupCombination.BackupFilePath))
|
||||
{
|
||||
Directory.CreateDirectory(backupCombination.BackupFilePath);
|
||||
}
|
||||
|
||||
// Execute the mysqldump command
|
||||
ProcessStartInfo processInfo = new ProcessStartInfo
|
||||
{
|
||||
FileName = "cmd.exe",
|
||||
RedirectStandardInput = true,
|
||||
RedirectStandardOutput = true,
|
||||
RedirectStandardError = true,
|
||||
UseShellExecute = false,
|
||||
CreateNoWindow = true
|
||||
};
|
||||
|
||||
Process process = new Process
|
||||
{
|
||||
StartInfo = processInfo
|
||||
};
|
||||
|
||||
process.Start();
|
||||
|
||||
using (var writer = process.StandardInput)
|
||||
{
|
||||
if (writer.BaseStream.CanWrite)
|
||||
{
|
||||
if (backupCombination.CommandPath.Length == 0)
|
||||
{
|
||||
if (!(update.Enabled ?? true) || dbConnection.DatabaseName != update.DatabaseName)
|
||||
writer.WriteLine(dumpCommand);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Split the dumpCommand into the executable and the arguments
|
||||
string[]
|
||||
parts = dumpCommand.Split(' ', 2); // Split into two parts: the command and the rest (arguments)
|
||||
|
||||
// Combine the commandPath with the executable (first part of dumpCommand)
|
||||
string fullCommand = Path.Combine(backupCombination.CommandPath, parts[0]) + " " + parts[1];
|
||||
|
||||
// Execute the command with the full path
|
||||
writer.WriteLine(fullCommand);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
process.WaitForExit();
|
||||
|
||||
string result = process.StandardOutput.ReadToEnd();
|
||||
string error = process.StandardError.ReadToEnd();
|
||||
|
||||
if (!string.IsNullOrEmpty(error))
|
||||
{
|
||||
Console.WriteLine($"Error: {error}");
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine($"Backup created successfully at {filePathName}");
|
||||
}
|
||||
|
||||
process.Close();
|
||||
|
||||
//Deactivate if only one time possible run
|
||||
|
||||
if ((backupCombination.Path.IsOneTimeOpaque ?? false) && (backupCombination.Path.Enabled ?? true))
|
||||
{
|
||||
backupCombination.Path.Enabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
static void UpdateDb(Configuration dbConfiguration)
|
||||
{
|
||||
if (dbConfiguration.DbConnectionStrings != null)
|
||||
foreach (DbConnection dbConnection in dbConfiguration.DbConnectionStrings)
|
||||
{
|
||||
if (!(dbConnection.Enabled ?? true))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (dbConfiguration.UpdateString != null)
|
||||
foreach (Update update in dbConfiguration.UpdateString)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
Console.WriteLine($"------ MySql Data upgrade name: {update.Name} starting -----");
|
||||
string connectionString =
|
||||
dbConnection.Connection.Replace("{DatabaseName}", dbConnection.DatabaseName);
|
||||
MySqlConnection connection = new MySqlConnection(connectionString);
|
||||
connection.Open();
|
||||
|
||||
|
||||
MySqlCommand command =
|
||||
new MySqlCommand(update.Query.Replace("{DatabaseName}", update.DatabaseName), connection);
|
||||
int affectedItems = command.ExecuteNonQuery();
|
||||
|
||||
Console.WriteLine($"Affected items: {affectedItems}");
|
||||
|
||||
connection.Close();
|
||||
|
||||
if (update.IsOneTimeOpaque ?? false)
|
||||
if (!(update.Enabled ?? true) || dbConnection.DatabaseName != update.DatabaseName)
|
||||
{
|
||||
update.Enabled = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
Console.WriteLine($"------ MySql Data upgrade name: {update.Name} finished! -----");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine($"------ MySql Data upgrade name: {update.Name} ERROR!");
|
||||
Console.WriteLine(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
try
|
||||
{
|
||||
Console.WriteLine($"------ MySql Data upgrade name: {update.Name} starting -----");
|
||||
string connectionString =
|
||||
dbConnection.Connection.Replace("{DatabaseName}", dbConnection.DatabaseName);
|
||||
MySqlConnection connection = new MySqlConnection(connectionString);
|
||||
connection.Open();
|
||||
|
||||
string ConfigurationFileNamePath()
|
||||
|
||||
MySqlCommand command =
|
||||
new MySqlCommand(update.Query.Replace("{DatabaseName}", update.DatabaseName),
|
||||
connection);
|
||||
int affectedItems = command.ExecuteNonQuery();
|
||||
|
||||
Console.WriteLine($"Affected items: {affectedItems}");
|
||||
|
||||
connection.Close();
|
||||
|
||||
if (update.IsOneTimeOpaque ?? false)
|
||||
{
|
||||
update.Enabled = false;
|
||||
}
|
||||
|
||||
Console.WriteLine($"------ MySql Data upgrade name: {update.Name} finished! -----");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine($"------ MySql Data upgrade name: {update.Name} ERROR!");
|
||||
Console.WriteLine(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static string GetProjectPath()
|
||||
{
|
||||
string fileNamePath;
|
||||
string currentDir;
|
||||
#if DEBUG
|
||||
Console.WriteLine("-- DEV version of THE PROJECT -- ");
|
||||
string projectPath = Directory.GetParent(Directory.GetCurrentDirectory()).Parent.Parent.FullName;
|
||||
|
||||
fileNamePath = Path.Combine(projectPath, Configuration.ConfigDir, Configuration.FileName);
|
||||
currentDir = Directory.GetParent(Directory.GetCurrentDirectory()).Parent.Parent.FullName;
|
||||
#else
|
||||
// For release mode, use an absolute path or the application base directory
|
||||
Console.WriteLine("-- PROD version of THE PROJECT -- ");
|
||||
fileNamePath = Path.Combine(Environment.CurrentDirectory, Configuration.ConfigDir, Configuration.FileName);
|
||||
// For release mode, use an absolute path or the application base directory
|
||||
Console.WriteLine("-- PROD version of THE PROJECT -- ");
|
||||
currentDir = Environment.CurrentDirectory;
|
||||
#endif
|
||||
return fileNamePath;
|
||||
return currentDir;
|
||||
}
|
||||
|
||||
static string ConfigurationFileNamePath()
|
||||
{
|
||||
string projectPath = GetProjectPath();
|
||||
return Path.Combine(projectPath, Configuration.ConfigDir, Configuration.FileName);
|
||||
}
|
||||
|
||||
// ==================== SUPPORTING METHODS ====================
|
||||
|
||||
static void RunSchemaComparison(string[] args)
|
||||
{
|
||||
if (args.Length < 3)
|
||||
{
|
||||
Console.WriteLine($"Usage: {ProgramName} compare <old_dump.sql> <new_dump.sql>");
|
||||
return;
|
||||
}
|
||||
|
||||
string oldPath = args[1];
|
||||
string newPath = args[2];
|
||||
|
||||
if (!File.Exists(oldPath) || !File.Exists(newPath))
|
||||
{
|
||||
Console.WriteLine($"Old file path not found: {Path.GetFullPath(oldPath)}");
|
||||
Console.WriteLine($"New file path not found: {Path.GetFullPath(newPath)}");
|
||||
|
||||
Console.WriteLine("Error: One or both dump files not found.");
|
||||
return;
|
||||
}
|
||||
|
||||
Console.WriteLine($"Comparing: {Path.GetFileName(oldPath)} vs {Path.GetFileName(newPath)}");
|
||||
|
||||
var oldSchema = SqlDumpSchemaParser.Parse(oldPath);
|
||||
var newSchema = SqlDumpSchemaParser.Parse(newPath);
|
||||
|
||||
SchemaMapping compareSchemas = SqlDumpSchemaParser.Compare(oldSchema, newSchema);
|
||||
SchemaMapping compareSchemas2 = SqlDumpSchemaParser.CompareSchemas(oldSchema, newSchema);
|
||||
|
||||
var json = JsonSerializer.Serialize(compareSchemas2, new JsonSerializerOptions { WriteIndented = true });
|
||||
File.WriteAllText("schema-mapping.json", json);
|
||||
}
|
||||
|
||||
static void RunTestSchemaMapping(string schemaFimeName = "")
|
||||
{
|
||||
if (schemaFimeName.Length == 0)
|
||||
{
|
||||
schemaFimeName = defaultSchemaFimeName;
|
||||
}
|
||||
|
||||
if (!File.Exists(schemaFimeName))
|
||||
{
|
||||
Console.WriteLine($"Schema file not found: {Path.GetFullPath(schemaFimeName)}");
|
||||
return;
|
||||
}
|
||||
|
||||
var editedMapping = JsonSerializer.Deserialize<SchemaMapping>(File.ReadAllText("schema-mapping.json"));
|
||||
|
||||
foreach (var table in editedMapping.Tables)
|
||||
{
|
||||
foreach (var mapping in table.ColumnMappings)
|
||||
{
|
||||
if (mapping.Status == "uncertain" && string.IsNullOrEmpty(mapping.NewColumn))
|
||||
{
|
||||
Console.WriteLine($"⚠️ Column {mapping.OldColumn} in table {table.TableName} is still not mapped.");
|
||||
}
|
||||
|
||||
// You can also check: does NewColumn exist in the new schema?
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static void RunUpdateBySchemaMapping(string[] args)
|
||||
{
|
||||
if (args.Length < 3)
|
||||
{
|
||||
Console.WriteLine($"Usage: {ProgramName} update-by-schema <old_dump.sql> <schema-mapping.json>");
|
||||
return;
|
||||
}
|
||||
|
||||
string basePath = Path.Combine(GetProjectPath(), "joinConfig");
|
||||
Configuration? configuration = GetConfiguration();
|
||||
|
||||
if (configuration == null)
|
||||
{
|
||||
throw new Exception($"Configuration no found on path: {basePath} !!");
|
||||
}
|
||||
|
||||
Joiner joiner = new Joiner(
|
||||
configuration,
|
||||
basePath,
|
||||
args[1],
|
||||
args[2]);
|
||||
|
||||
joiner.TestInputsAndFiles();
|
||||
joiner.SchemaJoiner();
|
||||
Console.WriteLine(joiner.IsJoindedSuccesfully? "Upgrade successful!" : "Upgrade failed!");
|
||||
}
|
||||
|
||||
static void PrintHelp()
|
||||
{
|
||||
Console.WriteLine("Usage:");
|
||||
Console.WriteLine($" {ProgramName} \n --> Run default backup/update process using configuration.");
|
||||
Console.WriteLine($" {ProgramName} compare <old.sql> <new.sql> \n --> Compare two SQL dump files.");
|
||||
Console.WriteLine($" {ProgramName} test-schema-mapping <*?.json> \n --> Test undefined schema mapping file.");
|
||||
Console.WriteLine($" {ProgramName} update-by-schema <old.sql> <*?.json> \n --> Update by schema mapping and dump files.");
|
||||
Console.WriteLine($" {ProgramName} help \n --> Show help information.");
|
||||
}
|
||||
|
||||
|
||||
static string? TransformInsert(string line, SchemaMapping mapping)
|
||||
{
|
||||
// Match INSERT INTO `table` (`col1`, `col2`) VALUES ...
|
||||
var regex = new Regex(@"INSERT INTO\s+`?(\w+)`?\s*\(([^)]+)\)\s*VALUES\s*(.+);", RegexOptions.IgnoreCase);
|
||||
var match = regex.Match(line);
|
||||
if (!match.Success)
|
||||
return null;
|
||||
|
||||
string oldTableName = match.Groups[1].Value;
|
||||
string[] oldColumns = match.Groups[2].Value.Split(',').Select(c => c.Trim(' ', '`')).ToArray();
|
||||
string values = match.Groups[3].Value;
|
||||
|
||||
var table = mapping.Tables.FirstOrDefault(t => t.TableName.Equals(oldTableName, StringComparison.OrdinalIgnoreCase));
|
||||
if (table == null)
|
||||
{
|
||||
Console.WriteLine($"[WARNING] Table not found in mapping: {oldTableName}");
|
||||
return null;
|
||||
}
|
||||
|
||||
var columnMap = new Dictionary<string, string>();
|
||||
foreach (var col in oldColumns)
|
||||
{
|
||||
var map = table.ColumnMappings.FirstOrDefault(c => c.OldColumn == col && c.Status != "Deleted");
|
||||
if (map != null && map.NewColumn != null)
|
||||
columnMap[col] = map.NewColumn;
|
||||
else
|
||||
Console.WriteLine($"[INFO] Skipping column '{col}' (no mapping found or deleted)");
|
||||
}
|
||||
|
||||
var newColumns = oldColumns.Where(c => columnMap.ContainsKey(c)).Select(c => $"`{columnMap[c]}`");
|
||||
var insert = $"INSERT INTO `{table.TableName}` ({string.Join(", ", newColumns)}) VALUES {values};";
|
||||
|
||||
return insert;
|
||||
}
|
||||
|
||||
}
|
||||
55
tbfDBBackup/ReadMe.md
Normal file
55
tbfDBBackup/ReadMe.md
Normal file
@ -0,0 +1,55 @@
|
||||
# Program tbfDBBackup
|
||||
Program is designed to backup, upgrade, compare and restore database.
|
||||
Only for advanced users!
|
||||
* Program is written in C# and .NET 8.0.
|
||||
* Program is using MySql.Data.MySqlClient.
|
||||
* Program using mysqldump.exe in some cases.
|
||||
* Program is designed for Windows.
|
||||
* Program is designed to use with MySQL.
|
||||
|
||||
## Program features
|
||||
* Backup database.
|
||||
* Upgrade database.
|
||||
* Compare database.
|
||||
* Restore database.
|
||||
|
||||
|
||||
### Backup database.
|
||||
We can use this program to define a backup procedure. Can work like a cron job, or services to run backup procedure.
|
||||
|
||||
### Upgrade database.
|
||||
We can use this program to define an upgrade procedure. Can work cyclic or one time per run.
|
||||
|
||||
# Description about program parameters
|
||||
|
||||
The program operates as a command-line driver, accepting parameters to control its behavior.
|
||||
|
||||
## Configuration
|
||||
When using a configuration file, the program can function autonomously, execute a single-use procedure, or encapsulate the operation as an opaque process.
|
||||
|
||||
## Dirrect commnad-line
|
||||
|
||||
### List of cmd commands
|
||||
|
||||
|
||||
## Cmd Help
|
||||
|
||||
### Connect to database via cmd
|
||||
|
||||
```aiignore
|
||||
mysql -h 127.0.0.1 -P 3306 -u root
|
||||
```
|
||||
Under database, we can create our own schema or use standard SQL syntax. For example:
|
||||
```aiignore
|
||||
"CREATE DATABASE slm-end;"
|
||||
```
|
||||
|
||||
### Reload dump to new schema
|
||||
```aiignore
|
||||
PS C:\xampp\mysql\bin> Get-Content "C:\Users\micha\git\sensus\tbfDBBackup\tbfDBBackup\bin\Debug\net8.0\old.sql" |
|
||||
>> .\mysql.exe -h 127.0.0.1 -P 3306 -u root --one-database slm-end
|
||||
```
|
||||
```aiignore
|
||||
PS C:\xampp\mysql\bin> Get-Content "C:\Users\micha\git\sensus\tbfDBBackup\tbfDBBackup\bin\Debug\net8.0\old-r.sql" |
|
||||
>> .\mysql.exe -h 127.0.0.1 -P 3306 -u root --one-database slm-end-r
|
||||
```
|
||||
12
tbfDBBackup/compare_dumps/ColumnDef.cs
Normal file
12
tbfDBBackup/compare_dumps/ColumnDef.cs
Normal file
@ -0,0 +1,12 @@
|
||||
namespace tbfDBBackup.compare_dumps;
|
||||
|
||||
public class ColumnDef
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public string Type { get; set; }
|
||||
public string Nullable { get; set; }
|
||||
|
||||
public bool IsPrimaryKey { get; set; }
|
||||
|
||||
public override string ToString() => $"{Name} {Type} {(Nullable == "NO" ? "NOT NULL" : "NULL")}";
|
||||
}
|
||||
12
tbfDBBackup/compare_dumps/Parserer/ForeignKeyDef.cs
Normal file
12
tbfDBBackup/compare_dumps/Parserer/ForeignKeyDef.cs
Normal file
@ -0,0 +1,12 @@
|
||||
namespace tbfDBBackup.compare_dumps.Parserer;
|
||||
|
||||
public class ForeignKeyDef
|
||||
{
|
||||
public string Name { get; set; } = "";
|
||||
public string Column { get; set; } = "";
|
||||
public string RefTable { get; set; } = "";
|
||||
public string RefColumn { get; set; } = "";
|
||||
|
||||
public override string ToString() =>
|
||||
$"{Name}: {Column} -> {RefTable}.{RefColumn}";
|
||||
}
|
||||
122
tbfDBBackup/compare_dumps/Parserer/SqlDumpFileParser.cs
Normal file
122
tbfDBBackup/compare_dumps/Parserer/SqlDumpFileParser.cs
Normal file
@ -0,0 +1,122 @@
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace tbfDBBackup.compare_dumps.Parserer;
|
||||
|
||||
public class SqlDumpFileParser
|
||||
{
|
||||
public Dictionary<string, string> TableDefinitions { get;set; }
|
||||
public Dictionary<string, List<string>> TableInserts { get;set; }
|
||||
|
||||
public Dictionary<string, List<string>> TableForeignKeys { get; private set; } = new();
|
||||
|
||||
public void SqlDumpParserFile(string filePath)
|
||||
{
|
||||
TableDefinitions = new Dictionary<string, string>();
|
||||
TableInserts = new Dictionary<string, List<string>>();
|
||||
TableForeignKeys = new Dictionary<string, List<string>>();
|
||||
|
||||
SqlSection currentSection = SqlSection.None;
|
||||
StringBuilder blockBuilder = new StringBuilder();
|
||||
string currentTable = null;
|
||||
|
||||
foreach (var line in File.ReadLines(filePath))
|
||||
{
|
||||
// Normalize line
|
||||
var trimmed = line.Trim();
|
||||
|
||||
if (trimmed.StartsWith("CREATE TABLE", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
currentSection = SqlSection.CreateTable;
|
||||
blockBuilder.Clear();
|
||||
blockBuilder.AppendLine(line);
|
||||
|
||||
// Extract table name
|
||||
var match = Regex.Match(trimmed, @"CREATE TABLE(?: IF NOT EXISTS)? `(\w+)`", RegexOptions.IgnoreCase);
|
||||
if (match.Success)
|
||||
currentTable = match.Groups[1].Value;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (trimmed.StartsWith("INSERT INTO", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
currentSection = SqlSection.InsertInto;
|
||||
blockBuilder.Clear();
|
||||
blockBuilder.AppendLine(line);
|
||||
|
||||
var match = Regex.Match(trimmed, @"INSERT INTO `(\w+)`", RegexOptions.IgnoreCase);
|
||||
if (match.Success)
|
||||
currentTable = match.Groups[1].Value;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// --- ALTER TABLE (foreign keys, constraints, etc.) ---
|
||||
if (trimmed.StartsWith("ALTER TABLE", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
currentSection = SqlSection.AlterTable;
|
||||
blockBuilder.Clear();
|
||||
blockBuilder.AppendLine(line);
|
||||
|
||||
var match = Regex.Match(trimmed, @"ALTER TABLE `(\w+)`", RegexOptions.IgnoreCase);
|
||||
if (match.Success)
|
||||
currentTable = match.Groups[1].Value;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// ------------------------
|
||||
// Accumulate CREATE TABLE
|
||||
// ------------------------
|
||||
if (currentSection == SqlSection.CreateTable)
|
||||
{
|
||||
blockBuilder.AppendLine(line);
|
||||
if (trimmed.EndsWith(";"))
|
||||
{
|
||||
// Save table schema
|
||||
if (currentTable != null)
|
||||
TableDefinitions[currentTable] = blockBuilder.ToString();
|
||||
currentSection = SqlSection.None;
|
||||
}
|
||||
}
|
||||
// ------------------------
|
||||
// Accumulate INSERT INTO
|
||||
// ------------------------
|
||||
else if (currentSection == SqlSection.InsertInto)
|
||||
{
|
||||
blockBuilder.AppendLine(line);
|
||||
if (trimmed.EndsWith(";"))
|
||||
{
|
||||
// Save INSERT block
|
||||
if (currentTable != null)
|
||||
{
|
||||
if (!TableInserts.ContainsKey(currentTable))
|
||||
TableInserts[currentTable] = new List<string>();
|
||||
TableInserts[currentTable].Add(blockBuilder.ToString());
|
||||
}
|
||||
|
||||
currentSection = SqlSection.None;
|
||||
}
|
||||
}
|
||||
// ------------------------
|
||||
// Accumulate ALTER TABLE
|
||||
// ------------------------
|
||||
else if (currentSection == SqlSection.AlterTable)
|
||||
{
|
||||
blockBuilder.AppendLine(line);
|
||||
if (trimmed.EndsWith(";"))
|
||||
{
|
||||
if (currentTable != null)
|
||||
{
|
||||
if (!TableForeignKeys.ContainsKey(currentTable))
|
||||
TableForeignKeys[currentTable] = new List<string>();
|
||||
TableForeignKeys[currentTable].Add(blockBuilder.ToString());
|
||||
}
|
||||
|
||||
currentSection = SqlSection.None;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
150
tbfDBBackup/compare_dumps/Parserer/SqlDumpParser.cs
Normal file
150
tbfDBBackup/compare_dumps/Parserer/SqlDumpParser.cs
Normal file
@ -0,0 +1,150 @@
|
||||
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using tbfDBBackup.compare_dumps.Parserer;
|
||||
|
||||
namespace tbfDBBackup.compare_dumps;
|
||||
|
||||
public class SqlDumpParser
|
||||
{
|
||||
public static Dictionary<int, Dictionary<string, string>> ParseInsertBlock(string sql)
|
||||
{
|
||||
var result = new Dictionary<int, Dictionary<string, string>>();
|
||||
|
||||
var fullInsertRegex = new Regex(
|
||||
@"INSERT INTO\s+`(?<table>\w+)`\s*\((?<columns>[^)]+)\)\s*VALUES\s*(?<values>.+);",
|
||||
RegexOptions.Singleline | RegexOptions.IgnoreCase);
|
||||
|
||||
var match = fullInsertRegex.Match(sql);
|
||||
if (!match.Success)
|
||||
throw new Exception("INSERT block not matched.");
|
||||
|
||||
var columns = match.Groups["columns"].Value
|
||||
.Split(',')
|
||||
.Select(c => c.Trim().Trim('`', ' '))
|
||||
.ToArray();
|
||||
|
||||
var valuesBlock = match.Groups["values"].Value;
|
||||
|
||||
// Match each value row: (1, 'WM1', '...', 1)
|
||||
var rowRegex = new Regex(@"\(([^()]*(?:\([^)]*\)[^()]*)*)\)", RegexOptions.Singleline);
|
||||
var rowMatches = rowRegex.Matches(valuesBlock);
|
||||
|
||||
foreach (Match rowMatch in rowMatches)
|
||||
{
|
||||
var rawRow = rowMatch.Groups[1].Value;
|
||||
var values = ParseCsvRow(rawRow);
|
||||
|
||||
if (values.Count != columns.Length)
|
||||
throw new Exception("Mismatch in column count.");
|
||||
|
||||
var rowDict = new Dictionary<string, string>();
|
||||
for (int i = 0; i < columns.Length; i++)
|
||||
rowDict[columns[i]] = values[i];
|
||||
|
||||
int rowId = int.Parse(rowDict["Id"]);
|
||||
result[rowId] = rowDict;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static List<string> ParseCsvRow(string row)
|
||||
{
|
||||
var values = new List<string>();
|
||||
var current = new StringBuilder();
|
||||
bool inQuotes = false;
|
||||
char quoteChar = '\'';
|
||||
|
||||
for (int i = 0; i < row.Length; i++)
|
||||
{
|
||||
char c = row[i];
|
||||
|
||||
if (inQuotes)
|
||||
{
|
||||
if (c == quoteChar)
|
||||
{
|
||||
if (i + 1 < row.Length && row[i + 1] == quoteChar)
|
||||
{
|
||||
current.Append(c); // Escaped quote
|
||||
i++;
|
||||
}
|
||||
else
|
||||
{
|
||||
inQuotes = false; // End quote
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
current.Append(c);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (c == '\'' || c == '"')
|
||||
{
|
||||
inQuotes = true;
|
||||
quoteChar = c;
|
||||
}
|
||||
else if (c == ',')
|
||||
{
|
||||
values.Add(current.ToString().Trim());
|
||||
current.Clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
current.Append(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (current.Length > 0)
|
||||
values.Add(current.ToString().Trim());
|
||||
|
||||
return values;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Regex for ALTER TABLE ... ADD CONSTRAINT ... FOREIGN KEY ...
|
||||
private static readonly Regex alterTableForeignKeyRegex = new Regex(
|
||||
@"ALTER\s+TABLE\s+`(?<table>\w+)`\s+ADD\s+CONSTRAINT\s+`(?<constraint>\w+)`\s+FOREIGN\s+KEY\s*\(`(?<column>\w+)`\)\s+REFERENCES\s+`(?<refTable>\w+)`\s*\(`(?<refColumn>\w+)`\)",
|
||||
RegexOptions.IgnoreCase);
|
||||
|
||||
public static Dictionary<string, List<ForeignKeyDef>> ParseForeignKeys(string line)
|
||||
{
|
||||
var tableForeignKeys = new Dictionary<string, List<ForeignKeyDef>>();
|
||||
|
||||
|
||||
var trimmed = line.Trim();
|
||||
if (string.IsNullOrEmpty(trimmed) || trimmed.StartsWith("--"))
|
||||
return tableForeignKeys;
|
||||
|
||||
var match = alterTableForeignKeyRegex.Match(trimmed);
|
||||
if (match.Success)
|
||||
{
|
||||
string table = match.Groups["table"].Value;
|
||||
string constraint = match.Groups["constraint"].Value;
|
||||
string column = match.Groups["column"].Value;
|
||||
string refTable = match.Groups["refTable"].Value;
|
||||
string refColumn = match.Groups["refColumn"].Value;
|
||||
|
||||
var fk = new ForeignKeyDef
|
||||
{
|
||||
Name = constraint,
|
||||
Column = column,
|
||||
RefTable = refTable,
|
||||
RefColumn = refColumn
|
||||
};
|
||||
|
||||
if (!tableForeignKeys.ContainsKey(table))
|
||||
tableForeignKeys[table] = new List<ForeignKeyDef>();
|
||||
|
||||
tableForeignKeys[table].Add(fk);
|
||||
|
||||
}
|
||||
|
||||
return tableForeignKeys;
|
||||
}
|
||||
|
||||
}
|
||||
9
tbfDBBackup/compare_dumps/Parserer/SqlSection.cs
Normal file
9
tbfDBBackup/compare_dumps/Parserer/SqlSection.cs
Normal file
@ -0,0 +1,9 @@
|
||||
namespace tbfDBBackup.compare_dumps;
|
||||
|
||||
public enum SqlSection
|
||||
{
|
||||
None,
|
||||
CreateTable,
|
||||
InsertInto,
|
||||
AlterTable
|
||||
}
|
||||
286
tbfDBBackup/compare_dumps/SqlDumpSchemaParser.cs
Normal file
286
tbfDBBackup/compare_dumps/SqlDumpSchemaParser.cs
Normal file
@ -0,0 +1,286 @@
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Text.Json;
|
||||
using tbfDBBackup.compare_dumps.mapping;
|
||||
|
||||
namespace tbfDBBackup.compare_dumps;
|
||||
|
||||
public class SqlDumpSchemaParser
|
||||
{
|
||||
public static Dictionary<string, TableDef> Parse(string filePath)
|
||||
{
|
||||
var schema = new Dictionary<string, TableDef>();
|
||||
var lines = File.ReadAllLines(filePath);
|
||||
|
||||
TableDef? currentTable = null;
|
||||
bool inCreateTable = false;
|
||||
|
||||
var createTableRegex = new Regex(@"CREATE TABLE\s+(IF NOT EXISTS\s+)?`?(\w+)`?", RegexOptions.IgnoreCase);
|
||||
var columnDefRegex = new Regex(@"^\s*`(\w+)`\s+([a-zA-Z0-9\(\)]+)(.*)", RegexOptions.IgnoreCase);
|
||||
|
||||
foreach (var rawLine in lines)
|
||||
{
|
||||
var line = rawLine.Trim();
|
||||
|
||||
if (string.IsNullOrEmpty(line) || line.StartsWith("--") || line.StartsWith("/*") || line.StartsWith("/*!"))
|
||||
continue;
|
||||
|
||||
// Start of CREATE TABLE
|
||||
if (line.StartsWith("CREATE TABLE", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
var match = createTableRegex.Match(line);
|
||||
if (match.Success)
|
||||
{
|
||||
string tableName = match.Groups[2].Value;
|
||||
currentTable = new TableDef { Name = tableName };
|
||||
schema[tableName] = currentTable;
|
||||
inCreateTable = true;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// End of table
|
||||
if (inCreateTable && line.StartsWith(")"))
|
||||
{
|
||||
currentTable?.PairPrivateKeys();
|
||||
currentTable = null;
|
||||
inCreateTable = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (inCreateTable && currentTable != null)
|
||||
{
|
||||
if (line.StartsWith("PRIMARY KEY"))
|
||||
{
|
||||
currentTable.privateKeys.AddRange(GetPrimayKeysFromString(line));
|
||||
}
|
||||
|
||||
// Skip keys and constraints
|
||||
if (line.StartsWith("PRIMARY KEY") || line.StartsWith("UNIQUE") ||
|
||||
line.StartsWith("KEY") || line.StartsWith("CONSTRAINT") || line.StartsWith("INDEX"))
|
||||
continue;
|
||||
|
||||
// Match a column line
|
||||
var match = columnDefRegex.Match(line);
|
||||
if (match.Success)
|
||||
{
|
||||
string columnName = match.Groups[1].Value;
|
||||
string dataType = match.Groups[2].Value;
|
||||
string rest = match.Groups[3].Value.ToUpperInvariant();
|
||||
|
||||
string nullable = rest.Contains("NOT NULL") ? "NO" : "YES";
|
||||
|
||||
currentTable.Columns.Add(new ColumnDef
|
||||
{
|
||||
Name = columnName,
|
||||
Type = dataType,
|
||||
Nullable = nullable,
|
||||
IsPrimaryKey = false
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return schema;
|
||||
}
|
||||
|
||||
private static List<string> GetPrimayKeysFromString(string input)
|
||||
{
|
||||
List<string> keys = new List<string>();
|
||||
// Regex: captures everything between parentheses, allows whitespace
|
||||
string pattern = @"PRIMARY\s+KEY\s*\(\s*`([^`]+)`(?:\s*,\s*`([^`]+)`)*\s*\)";
|
||||
|
||||
Match match = Regex.Match(input, pattern, RegexOptions.IgnoreCase);
|
||||
if (match.Success)
|
||||
{
|
||||
// First group is always the first PK column
|
||||
keys.Add(match.Groups[1].Value);
|
||||
// If multiple PKs, they’ll be in Captures of Group 2
|
||||
foreach (Capture c in match.Groups[2].Captures)
|
||||
{
|
||||
keys.Add(c.Value);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return keys;
|
||||
}
|
||||
|
||||
public static SchemaMapping Compare(Dictionary<string, TableDef> oldSchema, Dictionary<string, TableDef> newSchema)
|
||||
{
|
||||
var result = new SchemaMapping();
|
||||
var allTables = oldSchema.Keys.Union(newSchema.Keys);
|
||||
|
||||
foreach (var table in allTables)
|
||||
{
|
||||
Console.WriteLine($"\n=== Table: {table} ===");
|
||||
var tableMapping = new TableMapping { TableName = table };
|
||||
|
||||
if (!oldSchema.ContainsKey(table))
|
||||
{
|
||||
Console.WriteLine(" Table added in new schema.");
|
||||
TableMissingInSchema(newSchema, table, tableMapping, result, true);
|
||||
result.Tables.Add(tableMapping);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!newSchema.ContainsKey(table))
|
||||
{
|
||||
Console.WriteLine(" Table removed in new schema.");
|
||||
TableMissingInSchema(oldSchema, table, tableMapping, result, false);
|
||||
continue;
|
||||
}
|
||||
|
||||
var oldCols = oldSchema[table].Columns.ToDictionary(c => c.Name);
|
||||
var newCols = newSchema[table].Columns.ToDictionary(c => c.Name);
|
||||
|
||||
foreach (var col in oldCols.Keys.Except(newCols.Keys))
|
||||
{
|
||||
Console.WriteLine($" Column removed: {col}");
|
||||
tableMapping.ColumnMappings.Add(new ColumnMapping
|
||||
{
|
||||
NewColumn = col,
|
||||
Status = "missing",
|
||||
Note = "Table not found in old schema"
|
||||
});
|
||||
}
|
||||
|
||||
foreach (var col in newCols.Keys.Except(oldCols.Keys))
|
||||
{
|
||||
Console.WriteLine($" Column added: {col}");
|
||||
tableMapping.ColumnMappings.Add(new ColumnMapping
|
||||
{
|
||||
OldColumn = col,
|
||||
Status = "missing",
|
||||
Note = "Table not found in old schema",
|
||||
ColumnDef = newCols[col]
|
||||
});
|
||||
}
|
||||
|
||||
foreach (var col in oldCols.Keys.Intersect(newCols.Keys))
|
||||
{
|
||||
var o = oldCols[col];
|
||||
var n = newCols[col];
|
||||
if (o.Type != n.Type || o.Nullable != n.Nullable)
|
||||
{
|
||||
Console.WriteLine($" Column changed: {col}");
|
||||
Console.WriteLine($" Old: {o}");
|
||||
Console.WriteLine($" New: {n}");
|
||||
|
||||
tableMapping.ColumnMappings.Add(new ColumnMapping
|
||||
{
|
||||
OldColumn = col,
|
||||
Status = o.Type != n.Type ? "different" : "different_nullable",
|
||||
Note = "Table not found in old schema",
|
||||
ColumnDef = oldCols[col]
|
||||
});
|
||||
} else
|
||||
{
|
||||
Console.WriteLine($" Column mached: {col}");
|
||||
tableMapping.ColumnMappings.Add(new ColumnMapping
|
||||
{
|
||||
OldColumn = col,
|
||||
Status = "matched",
|
||||
Note = "Table not found in old schema",
|
||||
ColumnDef = oldCols[col]
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static void TableMissingInSchema(Dictionary<string, TableDef> tableSchema, string table, TableMapping tableMapping,
|
||||
SchemaMapping result, bool isNewTable)
|
||||
{
|
||||
foreach (var column in tableSchema[table].Columns)
|
||||
{
|
||||
tableMapping.ColumnMappings.Add(new ColumnMapping
|
||||
{
|
||||
NewColumn = column.Name,
|
||||
ColumnDef = column,
|
||||
Status = "missing",
|
||||
Note = "Table not found in old schema"
|
||||
});
|
||||
}
|
||||
tableMapping.IsNewTable = isNewTable;
|
||||
result.Tables.Add(tableMapping);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static SchemaMapping CompareSchemas(
|
||||
Dictionary<string, TableDef> oldSchema,
|
||||
Dictionary<string, TableDef> newSchema)
|
||||
{
|
||||
var result = new SchemaMapping();
|
||||
|
||||
foreach (var (oldTableName, oldTableDef) in oldSchema)
|
||||
{
|
||||
var tableMapping = new TableMapping { TableName = oldTableName };
|
||||
|
||||
if (!newSchema.TryGetValue(oldTableName, out var newTableDef))
|
||||
{
|
||||
// Table removed or renamed
|
||||
foreach (var oldCol in oldTableDef.Columns)
|
||||
{
|
||||
tableMapping.ColumnMappings.Add(new ColumnMapping
|
||||
{
|
||||
OldColumn = oldCol.Name,
|
||||
ColumnDef = oldCol,
|
||||
Status = "missing",
|
||||
Note = "Table not found in new schema"
|
||||
});
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var oldCol in oldTableDef.Columns)
|
||||
{
|
||||
var match = newTableDef.Columns.FirstOrDefault(c =>
|
||||
string.Equals(c.Name, oldCol.Name, StringComparison.OrdinalIgnoreCase) &&
|
||||
string.Equals(c.Type, oldCol.Type, StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
if (match != null)
|
||||
{
|
||||
tableMapping.ColumnMappings.Add(new ColumnMapping
|
||||
{
|
||||
OldColumn = oldCol.Name,
|
||||
ColumnDef = oldCol,
|
||||
NewColumn = match.Name,
|
||||
Status = "matched"
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
// Try fuzzy match (e.g., JSON joins)
|
||||
var possible = newTableDef.Columns
|
||||
.Where(c => c.Type.Contains("json", StringComparison.OrdinalIgnoreCase))
|
||||
.Select(c => c.Name)
|
||||
.FirstOrDefault();
|
||||
|
||||
tableMapping.ColumnMappings.Add(new ColumnMapping
|
||||
{
|
||||
OldColumn = oldCol.Name,
|
||||
ColumnDef = oldCol,
|
||||
NewColumn = possible,
|
||||
Status = "uncertain",
|
||||
Note = "Could be part of JSON or renamed"
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result.Tables.Add(tableMapping);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public SchemaMapping? LoadSchema(string combine)
|
||||
{
|
||||
var jsonString = File.ReadAllText(combine);
|
||||
return System.Text.Json.JsonSerializer.Deserialize<SchemaMapping>(jsonString);
|
||||
}
|
||||
}
|
||||
27
tbfDBBackup/compare_dumps/TableDef.cs
Normal file
27
tbfDBBackup/compare_dumps/TableDef.cs
Normal file
@ -0,0 +1,27 @@
|
||||
namespace tbfDBBackup.compare_dumps;
|
||||
|
||||
public class TableDef
|
||||
{
|
||||
public string Name;
|
||||
public List<ColumnDef> Columns = new();
|
||||
public List<string> privateKeys = new();
|
||||
|
||||
public void PairPrivateKeys()
|
||||
{
|
||||
foreach (string privateKey in privateKeys)
|
||||
{
|
||||
if (privateKey.Length <= 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach (ColumnDef column in Columns)
|
||||
{
|
||||
if (column.Name == privateKey)
|
||||
{
|
||||
column.IsPrimaryKey = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
496
tbfDBBackup/compare_dumps/joinValues/Joiner.cs
Normal file
496
tbfDBBackup/compare_dumps/joinValues/Joiner.cs
Normal file
@ -0,0 +1,496 @@
|
||||
using System.Data;
|
||||
using System.Text;
|
||||
using MySqlConnector;
|
||||
using tbfDBBackup.compare_dumps.mapping;
|
||||
using tbfDBBackup.compare_dumps.Parserer;
|
||||
using tbfDBBackup.configuration;
|
||||
|
||||
namespace tbfDBBackup.compare_dumps.joinValues;
|
||||
|
||||
public class Joiner
|
||||
{
|
||||
const int iMaxStepInsertRows = 20;
|
||||
|
||||
private Configuration dbConfiguration;
|
||||
private string basePath;
|
||||
private string oldDump;
|
||||
private string schema;
|
||||
|
||||
public bool isJoindedSuccesfully = false;
|
||||
public bool IsJoindedSuccesfully
|
||||
{
|
||||
get { return isJoindedSuccesfully; }
|
||||
}
|
||||
|
||||
public Joiner(Configuration dbConfiguration, string basePath, string oldDump, string schema)
|
||||
{
|
||||
this.dbConfiguration = dbConfiguration;
|
||||
this.basePath = basePath;
|
||||
this.oldDump = oldDump;
|
||||
this.schema = schema;
|
||||
}
|
||||
|
||||
private MySqlConnection _connection;
|
||||
|
||||
private static string QuoteIdentifier(string identifier)
|
||||
{
|
||||
// Enforce a strict whitelist for identifiers (letters, digits, underscore).
|
||||
// Adjust if you must allow more, but be cautious.
|
||||
if (string.IsNullOrWhiteSpace(identifier) || !System.Text.RegularExpressions.Regex.IsMatch(identifier, @"^[A-Za-z0-9_]+$"))
|
||||
throw new ArgumentException("Invalid identifier.", nameof(identifier));
|
||||
|
||||
// Escape backticks just in case you relax the whitelist in the future.
|
||||
var escaped = identifier.Replace("`", "``");
|
||||
return $"`{escaped}`";
|
||||
}
|
||||
|
||||
|
||||
private long GetMaxId(string tableName, string columnName)
|
||||
{
|
||||
if (columnName == null || columnName.Length == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
OpenFirstDbConnection();
|
||||
|
||||
var qTable = QuoteIdentifier(tableName);
|
||||
var qColumn = QuoteIdentifier(columnName);
|
||||
|
||||
try
|
||||
{
|
||||
using var cmd = new MySqlCommand($"SELECT COALESCE(MAX({qColumn}), 0) FROM {qTable};", _connection)
|
||||
{
|
||||
CommandTimeout = 30
|
||||
};
|
||||
|
||||
var result = cmd.ExecuteScalar();
|
||||
if (result is DBNull)
|
||||
return 0;
|
||||
|
||||
try
|
||||
{
|
||||
// Consider checked/unchecked based on your tolerance for overflow.
|
||||
return Convert.ToInt64(result, System.Globalization.CultureInfo.InvariantCulture);
|
||||
}
|
||||
catch (OverflowException)
|
||||
{
|
||||
// Decide on policy: throw with context or clamp/return 0.
|
||||
throw new OverflowException($"MAX({columnName}) in {tableName} exceeds Int64 range.");
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
// Decide on policy: throw with context or clamp/return 0.
|
||||
throw new Exception($"MAX({columnName}) in {tableName} has problems: {e.Message}.");
|
||||
}
|
||||
}
|
||||
|
||||
public void SchemaJoiner()
|
||||
{
|
||||
try
|
||||
{
|
||||
string combinePath = Path.Combine(basePath, this.schema);
|
||||
SqlDumpSchemaParser schemaParser = new SqlDumpSchemaParser();
|
||||
SchemaMapping? schemaMapping = schemaParser.LoadSchema(combinePath);
|
||||
if (schemaMapping == null)
|
||||
{
|
||||
Console.WriteLine($"SchemaMapping is null, check {combinePath}");
|
||||
return;
|
||||
}
|
||||
|
||||
if (schemaMapping.Tables.Count == 0)
|
||||
{
|
||||
Console.WriteLine($"Nothing to do! See schema: {combinePath}");
|
||||
}
|
||||
|
||||
//we have schema mapping
|
||||
|
||||
SqlDumpFileParser oldDumpParser = new();
|
||||
//SqlDumpFileParser newDumpParser = new();
|
||||
oldDumpParser.SqlDumpParserFile(Path.Combine(basePath, oldDump));
|
||||
//newDumpParser.SqlDumpParserFile(Path.Combine(basePath, newDump));
|
||||
|
||||
//we have opened files
|
||||
// now list the schema to find out what to change
|
||||
|
||||
|
||||
foreach (TableMapping table in schemaMapping?.Tables!)
|
||||
{
|
||||
Dictionary<int, Dictionary<string, string>> blockTable = new();
|
||||
if (oldDumpParser.TableDefinitions.Keys.Contains(table.TableName))
|
||||
{
|
||||
bool tryGetInsertValue =
|
||||
oldDumpParser.TableInserts.TryGetValue(table.TableName, out List<string>? oldRowsInserts);
|
||||
StringBuilder builder = new StringBuilder();
|
||||
|
||||
|
||||
if (tryGetInsertValue)
|
||||
{
|
||||
//get primary columns
|
||||
List<string> primaryColumns = new List<string>();
|
||||
table.ColumnMappings?.ForEach(col =>
|
||||
{
|
||||
if (col.IsPrimaryColumn) { primaryColumns.Add(col?.OldColumn); }
|
||||
});
|
||||
//get foreigner columns
|
||||
bool tryGetForeignerColums =
|
||||
oldDumpParser.TableForeignKeys.TryGetValue(table.TableName, out List<string>? oldForeignerTableNames);
|
||||
List<ForeignKeyDef> foreignKeys = new List<ForeignKeyDef>();
|
||||
if (tryGetForeignerColums)
|
||||
{
|
||||
oldForeignerTableNames.ForEach(ForeignKeyConstraintRow =>
|
||||
{
|
||||
Dictionary<string, List<ForeignKeyDef>> foreignerList =
|
||||
SqlDumpParser.ParseForeignKeys(ForeignKeyConstraintRow);
|
||||
if (foreignerList.Count == 1) // we expecting only one foreign key definition per table
|
||||
{
|
||||
var keyValuePair = foreignerList.First().Value;
|
||||
foreach (var combination in keyValuePair)
|
||||
{
|
||||
foreignKeys.Add(combination);
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
//get max id from table - for insert
|
||||
long iMaxId = GetMaxId(table.TableName, primaryColumns.First());
|
||||
iMaxId ++;
|
||||
table.PrivateKeyShift = iMaxId;
|
||||
//store max id and increment it
|
||||
|
||||
|
||||
//collect data by columns to insert command
|
||||
oldRowsInserts.ForEach(colapsedInsertRow =>
|
||||
{
|
||||
Dictionary<int, Dictionary<string, string>> insertBlock = SqlDumpParser.ParseInsertBlock(colapsedInsertRow);
|
||||
|
||||
foreach (KeyValuePair<int, Dictionary<string, string>> keyValuePair in insertBlock)
|
||||
{
|
||||
//get columns from insert block - store to permittedColumns
|
||||
Dictionary<string, string> permittedColumns = new();
|
||||
foreach (KeyValuePair<string, string> column in keyValuePair.Value)
|
||||
{
|
||||
foreach (ColumnMapping columnMapping in table.ColumnMappings)
|
||||
{
|
||||
if (columnMapping.OldColumn == column.Key
|
||||
&& columnMapping.NewColumn != null)
|
||||
{
|
||||
//if is column PRIMARY KEY we need add shift upgrade - if we have
|
||||
if (columnMapping.IsPrimaryColumn && iMaxId > 0)
|
||||
{
|
||||
long _actualValue = ConvertValToLong(column.Value);
|
||||
permittedColumns.Add(columnMapping.NewColumn, (_actualValue + iMaxId).ToString());
|
||||
}
|
||||
//if is Forine key we need add shift upgrade - of table max id
|
||||
else if (foreignKeys.Count > 0 && foreignKeys.Any(fk => fk.Column == columnMapping.OldColumn))
|
||||
{
|
||||
//we have foreigner table name
|
||||
foreach (ForeignKeyDef fk in foreignKeys)
|
||||
{
|
||||
if (fk.Column == columnMapping.OldColumn)
|
||||
{
|
||||
long shift = 0;
|
||||
foreach (TableMapping tableMapping in schemaMapping.Tables)
|
||||
{
|
||||
TableMapping? tMap = schemaMapping.Tables.FirstOrDefault(t => t.TableName == fk.RefTable);
|
||||
if (tMap != null)
|
||||
{
|
||||
shift = tMap.PrivateKeyShift;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//TODO BUMI !! finish this - need react to converted data in different tables
|
||||
long _actualValue = ConvertValToLong(column.Value);
|
||||
permittedColumns.Add(columnMapping.NewColumn,
|
||||
(_actualValue + shift).ToString());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
permittedColumns.Add(columnMapping.NewColumn, column.Value);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
blockTable.Add(keyValuePair.Key, permittedColumns);
|
||||
}
|
||||
|
||||
//TODO Insert data step by step into database ??
|
||||
builder.Append($" Inserts: {blockTable.Count}, ");
|
||||
});
|
||||
Console.WriteLine(builder.ToString());
|
||||
}
|
||||
else
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//TODO Insert data step by step into database
|
||||
WriteBlockTableToDB(dbConfiguration, table.TableName, blockTable);
|
||||
}
|
||||
|
||||
|
||||
// finally, ok
|
||||
isJoindedSuccesfully = true;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine(e.Message);
|
||||
isJoindedSuccesfully = false;
|
||||
}
|
||||
finally
|
||||
{
|
||||
ReleaseConnectionToDB();
|
||||
}
|
||||
}
|
||||
|
||||
private long ConvertValToLong(object columnValue)
|
||||
{
|
||||
long result;
|
||||
if (columnValue is long l)
|
||||
{
|
||||
result = l;
|
||||
}
|
||||
else if (columnValue is string s && long.TryParse(s, out long parsed))
|
||||
{
|
||||
result = parsed;
|
||||
}
|
||||
else
|
||||
{
|
||||
// fallback if null/invalid
|
||||
result = 0;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private void WriteBlockTableToDB(Configuration dbConfiguration,string tableName,
|
||||
Dictionary<int, Dictionary<string, string>> blockTable)
|
||||
{
|
||||
if (dbConfiguration == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(dbConfiguration));
|
||||
}
|
||||
|
||||
if (blockTable == null || blockTable.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (dbConfiguration.DbConnectionStrings != null)
|
||||
foreach (DbConnection dbConnection in dbConfiguration.DbConnectionStrings)
|
||||
{
|
||||
if (!(dbConnection.Enabled ?? true))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if (dbConfiguration.UpgradeDatabase != null)
|
||||
foreach (Upgrade upgrade in dbConfiguration.UpgradeDatabase)
|
||||
{
|
||||
string databaseName = upgrade.DatabaseName;
|
||||
List<string> columns = blockTable.First().Value.Keys.ToList();
|
||||
|
||||
|
||||
int iRowsStepCount = 0;
|
||||
//join values
|
||||
StringBuilder builderValues = new StringBuilder();
|
||||
foreach (KeyValuePair<int, Dictionary<string, string>> table in blockTable)
|
||||
{
|
||||
builderValues.Append('(');
|
||||
|
||||
// Values
|
||||
bool first = true;
|
||||
foreach (string colName in columns)
|
||||
{
|
||||
var colValExist = table.Value.TryGetValue(colName, out string? col);
|
||||
if (!first)
|
||||
builderValues.Append(", ");
|
||||
|
||||
// Wrap string values in quotes
|
||||
if (!colValExist)
|
||||
builderValues.Append("NULL");
|
||||
else
|
||||
builderValues.Append($"'{col?.Replace("'", "''")}'");
|
||||
|
||||
first = false;
|
||||
}
|
||||
|
||||
builderValues.Append("),");
|
||||
|
||||
|
||||
//Send upgrade string to db
|
||||
if (iRowsStepCount >= iMaxStepInsertRows)
|
||||
{
|
||||
SendInsertCommandToDb(dbConnection,databaseName, tableName, columns, builderValues);
|
||||
builderValues.Clear();
|
||||
iRowsStepCount = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
iRowsStepCount++;
|
||||
}
|
||||
}
|
||||
|
||||
if (builderValues.Length > 0)
|
||||
{
|
||||
SendInsertCommandToDb(dbConnection, databaseName, tableName, columns, builderValues);
|
||||
builderValues.Clear();
|
||||
iRowsStepCount = 0;
|
||||
}
|
||||
//we upgrade only one Upgrade connection
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void SendInsertCommandToDb(DbConnection dbConnection,string databaseName, string tableName, List<string> columns, StringBuilder builderValues)
|
||||
{
|
||||
if (builderValues.Length > 0)
|
||||
{
|
||||
Console.WriteLine(builderValues.Length);
|
||||
}
|
||||
//Create upgrade string
|
||||
StringBuilder builder = new StringBuilder();
|
||||
|
||||
builder.Append("INSERT INTO");
|
||||
// Optional: prepend database name if provided
|
||||
if (!string.IsNullOrEmpty(databaseName))
|
||||
{
|
||||
builder.Append($" `{databaseName}`.`{tableName}` ");
|
||||
}
|
||||
else
|
||||
{
|
||||
builder.Append($" `{tableName}` ");
|
||||
}
|
||||
|
||||
// Columns
|
||||
builder.Append('(');
|
||||
builder.Append(string.Join(", ", columns));
|
||||
builder.Append(") VALUES ");
|
||||
|
||||
builderValues.Remove(builderValues.Length - 1, 1);
|
||||
builder.Append(builderValues).Append(';');
|
||||
|
||||
//Write to db
|
||||
OpenConnectionToDB(dbConnection);
|
||||
|
||||
try
|
||||
{
|
||||
using (var tx = _connection.BeginTransaction())
|
||||
using (var command = new MySqlCommand(builder.ToString(), _connection, tx))
|
||||
{
|
||||
int affectedItems = command.ExecuteNonQuery();
|
||||
tx.Commit();
|
||||
Console.WriteLine($"Affected items: {affectedItems}");
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine("Command execution failed, see details: ",e);
|
||||
File.AppendAllText("error.txt", "\nLOG Bug: \n");
|
||||
File.AppendAllText("error.txt", e.Message);
|
||||
//TODO BUMI remove this part as default
|
||||
#if DEBUG
|
||||
File.AppendAllText("error.txt", "\n\n ----------------------------------------------------------------------\n");
|
||||
File.AppendAllText("error.txt", builder.ToString());
|
||||
#else
|
||||
throw;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
private void OpenFirstDbConnection()
|
||||
{
|
||||
if (dbConfiguration.DbConnectionStrings != null)
|
||||
foreach (DbConnection dbConnection in dbConfiguration.DbConnectionStrings)
|
||||
{
|
||||
if (!(dbConnection.Enabled ?? true))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (dbConfiguration.UpgradeDatabase != null)
|
||||
foreach (Upgrade upgrade in dbConfiguration.UpgradeDatabase)
|
||||
{
|
||||
OpenConnectionToDB(dbConnection, true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OpenConnectionToDB(DbConnection dbConnection, bool ForcedReloading = false)
|
||||
{
|
||||
if (ForcedReloading)
|
||||
{
|
||||
ReleaseConnectionToDB();
|
||||
}
|
||||
if (_connection == null || _connection.State == ConnectionState.Closed || _connection.State == ConnectionState.Broken)
|
||||
{
|
||||
ReleaseConnectionToDB();
|
||||
|
||||
string connectionString =
|
||||
dbConnection.Connection.Replace("{DatabaseName}", dbConnection.DatabaseName);
|
||||
_connection = new MySqlConnection(connectionString);
|
||||
_connection.Open();
|
||||
}
|
||||
}
|
||||
|
||||
void ReleaseConnectionToDB()
|
||||
{
|
||||
if (_connection != null)
|
||||
{
|
||||
_connection.Dispose();
|
||||
_connection.Close();
|
||||
_connection = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void TestInputsAndFiles()
|
||||
{
|
||||
if (dbConfiguration is null)
|
||||
throw new ArgumentNullException(nameof(dbConfiguration));
|
||||
|
||||
if (dbConfiguration.DbConnectionStrings is null || dbConfiguration.DbConnectionStrings.Count == 0)
|
||||
throw new ArgumentException("DbConnectionStrings must not be null or empty.", nameof(dbConfiguration));
|
||||
|
||||
|
||||
if (string.IsNullOrWhiteSpace(basePath))
|
||||
throw new ArgumentException("Base path must not be null or empty.", nameof(basePath));
|
||||
if (string.IsNullOrWhiteSpace(oldDump))
|
||||
throw new ArgumentException("Old dump file name must not be null or empty.", nameof(oldDump));
|
||||
if (string.IsNullOrWhiteSpace(schema))
|
||||
throw new ArgumentException("Schema mapping file name must not be null or empty.", nameof(schema));
|
||||
|
||||
var files = new[]
|
||||
{
|
||||
(Name: oldDump, Path: Path.Combine(basePath, oldDump)),
|
||||
(Name: schema, Path: Path.Combine(basePath, schema)),
|
||||
};
|
||||
|
||||
var missing = new List<string>();
|
||||
foreach (var f in files)
|
||||
{
|
||||
if (!File.Exists(f.Path))
|
||||
missing.Add(f.Name);
|
||||
}
|
||||
|
||||
if (missing.Count > 0)
|
||||
throw new FileNotFoundException($"Missing files: {string.Join(", ", missing)} on path {basePath} .");
|
||||
|
||||
}
|
||||
}
|
||||
34
tbfDBBackup/compare_dumps/mapping/ColumnMapping.cs
Normal file
34
tbfDBBackup/compare_dumps/mapping/ColumnMapping.cs
Normal file
@ -0,0 +1,34 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace tbfDBBackup.compare_dumps.mapping;
|
||||
|
||||
public class ColumnMapping
|
||||
{
|
||||
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
public string? OldColumn { get; set; } // null if column only exists in new schema
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
public string? NewColumn { get; set; } // null if column was removed or not yet mapped
|
||||
public string Status { get; set; } // "matched", "uncertain", "missing", "added"
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
public string? Note { get; set; }
|
||||
|
||||
public ColumnDef ColumnDef { get; set; }
|
||||
public List<ColumnDef> ColumnDefList { get; set; }
|
||||
|
||||
private bool? _isPrimaryColumn;
|
||||
public bool IsPrimaryColumn { get { return GetPrimaryColumn(); } set { _isPrimaryColumn = value; } }
|
||||
|
||||
private bool GetPrimaryColumn()
|
||||
{
|
||||
if (_isPrimaryColumn != null)
|
||||
{
|
||||
return _isPrimaryColumn.Value;
|
||||
}
|
||||
|
||||
return ColumnDef != null ? ColumnDef.IsPrimaryKey : false;
|
||||
}
|
||||
|
||||
private JoinColumn? _joinColumn;
|
||||
public JoinColumn? JoinColumn { get { return _joinColumn; } set { _joinColumn = value; } }
|
||||
}
|
||||
7
tbfDBBackup/compare_dumps/mapping/JoinColumn.cs
Normal file
7
tbfDBBackup/compare_dumps/mapping/JoinColumn.cs
Normal file
@ -0,0 +1,7 @@
|
||||
namespace tbfDBBackup.compare_dumps.mapping;
|
||||
|
||||
public class JoinColumn
|
||||
{
|
||||
public string ColumnName { get; set; }
|
||||
public string TableName { get; set; }
|
||||
}
|
||||
8
tbfDBBackup/compare_dumps/mapping/SchemaMapping.cs
Normal file
8
tbfDBBackup/compare_dumps/mapping/SchemaMapping.cs
Normal file
@ -0,0 +1,8 @@
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace tbfDBBackup.compare_dumps.mapping;
|
||||
|
||||
public class SchemaMapping
|
||||
{
|
||||
public List<TableMapping> Tables { get; set; } = new();
|
||||
}
|
||||
11
tbfDBBackup/compare_dumps/mapping/TableMapping.cs
Normal file
11
tbfDBBackup/compare_dumps/mapping/TableMapping.cs
Normal file
@ -0,0 +1,11 @@
|
||||
namespace tbfDBBackup.compare_dumps.mapping;
|
||||
|
||||
public class TableMapping
|
||||
{
|
||||
public string TableName { get; set; }
|
||||
public List<ColumnMapping> ColumnMappings { get; set; } = new();
|
||||
public bool IsNewTable { get; set; } = false;
|
||||
|
||||
public bool IsNeedRecalculate { get => PrivateKeyShift != 0; }
|
||||
public long PrivateKeyShift { get; set; }
|
||||
}
|
||||
@ -7,48 +7,41 @@
|
||||
"Name": "Settings DB",
|
||||
"Connection": "SERVER=localhost; DATABASE={DatabaseName}; UID=root; PASSWORD=; CHARSET=utf8;",
|
||||
"DatabaseName": "wrcswindon298",
|
||||
"Enabled": false
|
||||
},
|
||||
{
|
||||
"Name": "Results DB",
|
||||
"Connection": "SERVER=localhost; DATABASE={DatabaseName}; UID=root; PASSWORD=; CHARSET=utf8;",
|
||||
"DatabaseName": "wrcswindon298-r",
|
||||
"Enabled": true
|
||||
}
|
||||
],
|
||||
"UpdateString": [
|
||||
{
|
||||
"Enabled": false,
|
||||
"Name": "Alter table Water Meter",
|
||||
"Query": "ALTER TABLE `{DatabaseName}`.`WaterMeter` ADD COLUMN `RadioAddress` BOOLEAN;",
|
||||
"DatabaseName": "wrcswindon298-r"
|
||||
}
|
||||
],
|
||||
"BackupDB": [
|
||||
{
|
||||
"DbConnectionStringsName": "Results DB",
|
||||
"StoreDirPaths": [
|
||||
{
|
||||
"Path": "C:\\TBF\\",
|
||||
"IsOneTimeOpaque": true
|
||||
},
|
||||
{
|
||||
"Path": "C:\\TBF\\storeString"
|
||||
}
|
||||
],
|
||||
"Enabled": true
|
||||
"Query": "INSERT INTO \u0060group\u0060 (Name, AccessFlags) VALUES (\u0027MetrologicalAuthority\u0027, 0);\nINSERT INTO \u0060group\u0060 (Name, AccessFlags) VALUES (\u0027WaterMeterAuthority\u0027, 0);",
|
||||
"DatabaseName": "wrcswindon298",
|
||||
"Enabled": false,
|
||||
"IsOneTimeOpaque": true
|
||||
},
|
||||
{
|
||||
"DbConnectionStringsName": "Settings DB",
|
||||
"StoreDirPaths": [
|
||||
{
|
||||
"Path": "C:\\TBF\\"
|
||||
},
|
||||
{
|
||||
"Path": "C:\\TBF\\storeString"
|
||||
}
|
||||
],
|
||||
"Enabled": false
|
||||
"Name": "Alter table Water Meter",
|
||||
"Query": "INSERT INTO usersgroups (Group_id, User_id) VALUES (8, 1);\nINSERT INTO usersgroups (Group_id, User_id) VALUES (9, 1);",
|
||||
"DatabaseName": "wrcswindon298",
|
||||
"Enabled": false,
|
||||
"IsOneTimeOpaque": true
|
||||
}
|
||||
],
|
||||
"UpgradeDatabase": [
|
||||
{
|
||||
"Enabled": true,
|
||||
"Name": "Upgrade by JSON",
|
||||
"Query": "",
|
||||
"JSONFileName": "",
|
||||
"DatabaseName": "wrcswindon298",
|
||||
"IsOneTimeOpaque": true
|
||||
},
|
||||
{
|
||||
"Enabled": true,
|
||||
"Name": "Alter table Water Meter",
|
||||
"Query": "INSERT INTO usersgroups (Group_id, User_id) VALUES (8, 1);\nINSERT INTO usersgroups (Group_id, User_id) VALUES (9, 1);",
|
||||
"JSONFileName": null,
|
||||
"DatabaseName": "wrcswindon298",
|
||||
"IsOneTimeOpaque": true
|
||||
}
|
||||
]
|
||||
}
|
||||
29
tbfDBBackup/config/configuration_forBackup.json
Normal file
29
tbfDBBackup/config/configuration_forBackup.json
Normal file
@ -0,0 +1,29 @@
|
||||
{
|
||||
"PathToDumpMysql": "C:\\xampp\\mysql\\bin",
|
||||
"WaitOnEndCmdOpen": false,
|
||||
"PrintConfigurationEnabled": false,
|
||||
"DbConnectionStrings": [
|
||||
{
|
||||
"Name": "Settings DB",
|
||||
"Connection": "SERVER=localhost; DATABASE={DatabaseName}; UID=root; PASSWORD=; CHARSET=utf8;",
|
||||
"DatabaseName": "wrcswindon298",
|
||||
"Enabled": true
|
||||
}
|
||||
],
|
||||
"UpdateString": [
|
||||
{
|
||||
"Enabled": true,
|
||||
"Name": "Alter table Water Meter",
|
||||
"Query": "INSERT INTO `group` (Name, AccessFlags) VALUES ('MetrologicalAuthority', 0);\nINSERT INTO `group` (Name, AccessFlags) VALUES ('WaterMeterAuthority', 0);",
|
||||
"DatabaseName": "wrcswindon298",
|
||||
"IsOneTimeOpaque": true
|
||||
},
|
||||
{
|
||||
"Enabled": true,
|
||||
"Name": "Alter table Water Meter",
|
||||
"Query": "INSERT INTO usersgroups (Group_id, User_id) VALUES (8, 1);\nINSERT INTO usersgroups (Group_id, User_id) VALUES (9, 1);",
|
||||
"DatabaseName": "wrcswindon298",
|
||||
"IsOneTimeOpaque": true
|
||||
}
|
||||
]
|
||||
}
|
||||
810
tbfDBBackup/config/schema-mapping-first-atempt.json
Normal file
810
tbfDBBackup/config/schema-mapping-first-atempt.json
Normal file
@ -0,0 +1,810 @@
|
||||
{
|
||||
"Tables": [
|
||||
{
|
||||
"TableName": "componentprocedure",
|
||||
"ColumnMappings": [
|
||||
{
|
||||
"OldColumn": "Id",
|
||||
"NewColumn": "Id",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "Id",
|
||||
"Type": "int(11)",
|
||||
"Nullable": "NO"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "CmpntName",
|
||||
"NewColumn": "CmpntName",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "CmpntName",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "Parameters",
|
||||
"NewColumn": "Parameters",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "Parameters",
|
||||
"Type": "varchar(8000)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "Procedure_id",
|
||||
"NewColumn": "Procedure_id",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "Procedure_id",
|
||||
"Type": "int(11)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
}
|
||||
],
|
||||
"IsNewTable": false
|
||||
},
|
||||
{
|
||||
"TableName": "componenttest",
|
||||
"ColumnMappings": [
|
||||
{
|
||||
"OldColumn": "Id",
|
||||
"NewColumn": "Id",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "Id",
|
||||
"Type": "int(11)",
|
||||
"Nullable": "NO"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "CmpntName",
|
||||
"NewColumn": "CmpntName",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "CmpntName",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "Parameters",
|
||||
"NewColumn": "Parameters",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "Parameters",
|
||||
"Type": "varchar(8000)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "Test_id",
|
||||
"NewColumn": "Test_id",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "Test_id",
|
||||
"Type": "int(11)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
}
|
||||
],
|
||||
"IsNewTable": false
|
||||
},
|
||||
{
|
||||
"TableName": "procedure",
|
||||
"ColumnMappings": [
|
||||
{
|
||||
"OldColumn": "Id",
|
||||
"NewColumn": "Id",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "Id",
|
||||
"Type": "int(11)",
|
||||
"Nullable": "NO"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "ItemNr",
|
||||
"NewColumn": "ItemNr",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "ItemNr",
|
||||
"Type": "int(11)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "Name",
|
||||
"NewColumn": "Name",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "Name",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "Description",
|
||||
"NewColumn": "Description",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "Description",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "CreationUser",
|
||||
"NewColumn": "CreationUser",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "CreationUser",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "CreationTime",
|
||||
"NewColumn": "CreationTime",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "CreationTime",
|
||||
"Type": "datetime",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "LastChgUser",
|
||||
"NewColumn": "LastChgUser",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "LastChgUser",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "LastChgTime",
|
||||
"NewColumn": "LastChgTime",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "LastChgTime",
|
||||
"Type": "datetime",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "LongDescription",
|
||||
"NewColumn": "LongDescription",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "LongDescription",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "ProcedureState",
|
||||
"NewColumn": "ProcedureState",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "ProcedureState",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "Revision",
|
||||
"NewColumn": "Revision",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "Revision",
|
||||
"Type": "int(11)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "PredecessorId",
|
||||
"NewColumn": "PredecessorId",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "PredecessorId",
|
||||
"Type": "int(11)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "ObtainedByCopy",
|
||||
"NewColumn": "ObtainedByCopy",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "ObtainedByCopy",
|
||||
"Type": "tinyint(1)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "MetersKind",
|
||||
"NewColumn": "MetersKind",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "MetersKind",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "Watermeters",
|
||||
"NewColumn": "Watermeters",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "Watermeters",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "ProtocolTitle",
|
||||
"Status": "new",
|
||||
"Note": "New",
|
||||
"ColumnDef": {
|
||||
"Name": "ProtocolTitle",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "Protected",
|
||||
"NewColumn": "Protected",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "Protected",
|
||||
"Type": "tinyint(1)",
|
||||
"Nullable": "NO"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "MustBeComplete",
|
||||
"NewColumn": "MustBeComplete",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "MustBeComplete",
|
||||
"Type": "tinyint(1)",
|
||||
"Nullable": "NO"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "ManualCtrlDisabled",
|
||||
"NewColumn": "ManualCtrlDisabled",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "ManualCtrlDisabled",
|
||||
"Type": "tinyint(1)",
|
||||
"Nullable": "NO"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "DataEntry",
|
||||
"NewColumn": "DataEntry",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "DataEntry",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "ResultsPrinter",
|
||||
"NewColumn": "ResultsPrinter",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "ResultsPrinter",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "ResultsWriter",
|
||||
"NewColumn": "ResultsWriter",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "ResultsWriter",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "TransitionStart",
|
||||
"NewColumn": "TransitionStart",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "TransitionStart",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "TransitionEnd",
|
||||
"NewColumn": "TransitionEnd",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "TransitionEnd",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "AltProcName",
|
||||
"NewColumn": "AltProcName",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "AltProcName",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "AltProcPeriod",
|
||||
"NewColumn": "AltProcPeriod",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "AltProcPeriod",
|
||||
"Type": "int(11)",
|
||||
"Nullable": "NO"
|
||||
}
|
||||
}
|
||||
],
|
||||
"IsNewTable": false
|
||||
},
|
||||
{
|
||||
"TableName": "test",
|
||||
"ColumnMappings": [
|
||||
{
|
||||
"OldColumn": "Id",
|
||||
"NewColumn": "Id",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "Id",
|
||||
"Type": "int(11)",
|
||||
"Nullable": "NO"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "ItemNr",
|
||||
"NewColumn": "ItemNr",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "ItemNr",
|
||||
"Type": "int(11)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "Name",
|
||||
"NewColumn": "Name",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "Name",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "Part",
|
||||
"NewColumn": "Part",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "Part",
|
||||
"Type": "int(11)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "Publish",
|
||||
"NewColumn": "Publish",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "Publish",
|
||||
"Type": "tinyint(4)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "Evaluate",
|
||||
"NewColumn": "DoEvaluate",
|
||||
"Status": "Renamed",
|
||||
"Note": "",
|
||||
"ColumnDef": {
|
||||
"Name": "Evaluate",
|
||||
"Type": "tinyint(1)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "Qfrom",
|
||||
"NewColumn": "Qfrom",
|
||||
"Status": "Change",
|
||||
"Note": "Could be part of JSON or renamed",
|
||||
"ColumnDefList": [{
|
||||
"Name": "Qfrom",
|
||||
"Type": "float",
|
||||
"Nullable": "YES"
|
||||
},
|
||||
{
|
||||
"Name": "Qfrom",
|
||||
"Type": "double",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"OldColumn": "Qto",
|
||||
"NewColumn": "Qto",
|
||||
"Status": "Change",
|
||||
"Note": "",
|
||||
"ColumnDefList": [
|
||||
{
|
||||
"Name": "Qto",
|
||||
"Type": "float",
|
||||
"Nullable": "YES"
|
||||
},
|
||||
{
|
||||
"Name": "Qto",
|
||||
"Type": "double",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"OldColumn": "Volume",
|
||||
"Status": "Change",
|
||||
"Note": "",
|
||||
"ColumnDefList": [
|
||||
{
|
||||
"Name": "Volume",
|
||||
"Type": "float",
|
||||
"Nullable": "YES"
|
||||
},
|
||||
{
|
||||
"Name": "Volume",
|
||||
"Type": "double",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"OldColumn": "TstTime",
|
||||
"NewColumn": "TestTime",
|
||||
"Status": "update",
|
||||
"Note": "Could be part of JSON or renamed",
|
||||
"ColumnDefList": [
|
||||
{
|
||||
"Name": "TstTime",
|
||||
"Type": "float",
|
||||
"Nullable": "YES"
|
||||
},
|
||||
{
|
||||
"Name": "TestTime",
|
||||
"Type": "double",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"OldColumn": "Repeats",
|
||||
"NewColumn": "Repeats",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "Repeats",
|
||||
"Type": "int(11)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "Emptying",
|
||||
"NewColumn": "DoDraining",
|
||||
"Status": "Renamed",
|
||||
"Note": "",
|
||||
"ColumnDef": {
|
||||
"Name": "Emptying",
|
||||
"Type": "tinyint(1)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "Zeroing",
|
||||
"Status": "uncertain",
|
||||
"Note": "Could be part of JSON or renamed",
|
||||
"ColumnDef": {
|
||||
"Name": "Zeroing",
|
||||
"Type": "tinyint(1)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "DoControlWaterTemp",
|
||||
"Status": "uncertain",
|
||||
"Note": "Could be part of JSON or renamed",
|
||||
"ColumnDef": {
|
||||
"Name": "DoControlWaterTemp",
|
||||
"Type": "tinyint(1)",
|
||||
"Nullable": "NO"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "TempLimLo",
|
||||
"NewColumn": "TempLimLo",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "TempLimLo",
|
||||
"Type": "float",
|
||||
"Nullable": "NO"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "TempLimHi",
|
||||
"NewColumn": "TempLimHi",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "TempLimHi",
|
||||
"Type": "float",
|
||||
"Nullable": "NO"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "PumpPower",
|
||||
"NewColumn": "PumpPower",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "PumpPower",
|
||||
"Type": "float",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "MassRepeats",
|
||||
"NewColumn": "MassRepeats",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "MassRepeats",
|
||||
"Type": "int(11)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "MassSpread",
|
||||
"NewColumn": "MassSpread",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "MassSpread",
|
||||
"Type": "float",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "MassMethod",
|
||||
"NewColumn": "MassMethod",
|
||||
"Status": "Changed",
|
||||
"Note": "`MassMethod` tinyint(3) unsigned DEFAULT NULL,",
|
||||
"ColumnDefList": [
|
||||
{
|
||||
"Name": "MassMethod",
|
||||
"Type": "tinyint(1)",
|
||||
"Nullable": "YES"
|
||||
},
|
||||
{
|
||||
"Name": "MassMethod",
|
||||
"Type": "tinyint(3)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
|
||||
]
|
||||
},
|
||||
{
|
||||
"OldColumn": "TimeBeforeFlow",
|
||||
"NewColumn": "TimeBeforeFlow",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "TimeBeforeFlow",
|
||||
"Type": "int(11)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "TimeFlow2Mass",
|
||||
"NewColumn": "TimeFlow2Mass",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "TimeFlow2Mass",
|
||||
"Type": "int(11)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "TimeMass2Start",
|
||||
"NewColumn": "TimePump2StartV",
|
||||
"Status": "Renamed",
|
||||
"Note": "",
|
||||
"ColumnDef": {
|
||||
"Name": "TimeMass2Start",
|
||||
"Type": "int(11)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "TimeStop2Mass",
|
||||
"NewColumn": "TimeStop2Mass",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "TimeStop2Mass",
|
||||
"Type": "int(11)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "Method",
|
||||
"NewColumn": "Method",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "Method",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "ErrLimLo",
|
||||
"NewColumn": "ErrLimLo",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "ErrLimLo",
|
||||
"Type": "float",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "ErrLimHi",
|
||||
"NewColumn": "ErrLimHi",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "ErrLimHi",
|
||||
"Type": "float",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "Uncertainty",
|
||||
"NewColumn": "Uncertainty",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "Uncertainty",
|
||||
"Type": "float",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "TolerRed",
|
||||
"Status": "Deleted",
|
||||
"ColumnDef": {
|
||||
"Name": "TolerRed",
|
||||
"Type": "double",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "RedType",
|
||||
"Status": "Deleted",
|
||||
"ColumnDef": {
|
||||
"Name": "RedType",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "FeedingPath",
|
||||
"NewColumn": "FeedingPath",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "FeedingPath",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "BenchPath",
|
||||
"NewColumn": "BenchPath",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "BenchPath",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "OutputPath",
|
||||
"NewColumn": "OutputPath",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "OutputPath",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "MetersPath",
|
||||
"NewColumn": "MetersPath",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "MetersPath",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "HeatMetersPath",
|
||||
"NewColumn": "HeatMetersPath",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "HeatMetersPath",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "RelTransBefore",
|
||||
"NewColumn": "TransBefore",
|
||||
"Status": "Renamed",
|
||||
"ColumnDef": {
|
||||
"Name": "RelTransBefore",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "RelTransBetween",
|
||||
"NewColumn": "TransBetween",
|
||||
"Status": "Renamed",
|
||||
"Note": "",
|
||||
"ColumnDef": {
|
||||
"Name": "RelTransBetween",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "RelTransAfter",
|
||||
"NewColumn": "TransAfter",
|
||||
"Status": "Renamed",
|
||||
"Note": "",
|
||||
"ColumnDef": {
|
||||
"Name": "RelTransAfter",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "TransitionAfter",
|
||||
"Status": "Deleted",
|
||||
"Note": "",
|
||||
"ColumnDef": {
|
||||
"Name": "TransitionAfter",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "Procedure_id",
|
||||
"NewColumn": "Procedure_id",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "Procedure_id",
|
||||
"Type": "int(11)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
}
|
||||
],
|
||||
"IsNewTable": false
|
||||
}
|
||||
]
|
||||
}
|
||||
810
tbfDBBackup/config/schema-mapping.json
Normal file
810
tbfDBBackup/config/schema-mapping.json
Normal file
@ -0,0 +1,810 @@
|
||||
{
|
||||
"Tables": [
|
||||
{
|
||||
"TableName": "componentprocedure",
|
||||
"ColumnMappings": [
|
||||
{
|
||||
"OldColumn": "Id",
|
||||
"NewColumn": "Id",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "Id",
|
||||
"Type": "int(11)",
|
||||
"Nullable": "NO"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "CmpntName",
|
||||
"NewColumn": "CmpntName",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "CmpntName",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "Parameters",
|
||||
"NewColumn": "Parameters",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "Parameters",
|
||||
"Type": "varchar(8000)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "Procedure_id",
|
||||
"NewColumn": "Procedure_id",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "Procedure_id",
|
||||
"Type": "int(11)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
}
|
||||
],
|
||||
"IsNewTable": false
|
||||
},
|
||||
{
|
||||
"TableName": "componenttest",
|
||||
"ColumnMappings": [
|
||||
{
|
||||
"OldColumn": "Id",
|
||||
"NewColumn": "Id",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "Id",
|
||||
"Type": "int(11)",
|
||||
"Nullable": "NO"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "CmpntName",
|
||||
"NewColumn": "CmpntName",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "CmpntName",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "Parameters",
|
||||
"NewColumn": "Parameters",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "Parameters",
|
||||
"Type": "varchar(8000)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "Test_id",
|
||||
"NewColumn": "Test_id",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "Test_id",
|
||||
"Type": "int(11)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
}
|
||||
],
|
||||
"IsNewTable": false
|
||||
},
|
||||
{
|
||||
"TableName": "procedure",
|
||||
"ColumnMappings": [
|
||||
{
|
||||
"OldColumn": "Id",
|
||||
"NewColumn": "Id",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "Id",
|
||||
"Type": "int(11)",
|
||||
"Nullable": "NO"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "ItemNr",
|
||||
"NewColumn": "ItemNr",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "ItemNr",
|
||||
"Type": "int(11)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "Name",
|
||||
"NewColumn": "Name",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "Name",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "Description",
|
||||
"NewColumn": "Description",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "Description",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "CreationUser",
|
||||
"NewColumn": "CreationUser",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "CreationUser",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "CreationTime",
|
||||
"NewColumn": "CreationTime",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "CreationTime",
|
||||
"Type": "datetime",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "LastChgUser",
|
||||
"NewColumn": "LastChgUser",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "LastChgUser",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "LastChgTime",
|
||||
"NewColumn": "LastChgTime",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "LastChgTime",
|
||||
"Type": "datetime",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "LongDescription",
|
||||
"NewColumn": "LongDescription",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "LongDescription",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "ProcedureState",
|
||||
"NewColumn": "ProcedureState",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "ProcedureState",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "Revision",
|
||||
"NewColumn": "Revision",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "Revision",
|
||||
"Type": "int(11)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "PredecessorId",
|
||||
"NewColumn": "PredecessorId",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "PredecessorId",
|
||||
"Type": "int(11)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "ObtainedByCopy",
|
||||
"NewColumn": "ObtainedByCopy",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "ObtainedByCopy",
|
||||
"Type": "tinyint(1)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "MetersKind",
|
||||
"NewColumn": "MetersKind",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "MetersKind",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "Watermeters",
|
||||
"NewColumn": "Watermeters",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "Watermeters",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "ProtocolTitle",
|
||||
"Status": "new",
|
||||
"Note": "New",
|
||||
"ColumnDef": {
|
||||
"Name": "ProtocolTitle",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "Protected",
|
||||
"NewColumn": "Protected",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "Protected",
|
||||
"Type": "tinyint(1)",
|
||||
"Nullable": "NO"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "MustBeComplete",
|
||||
"NewColumn": "MustBeComplete",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "MustBeComplete",
|
||||
"Type": "tinyint(1)",
|
||||
"Nullable": "NO"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "ManualCtrlDisabled",
|
||||
"NewColumn": "ManualCtrlDisabled",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "ManualCtrlDisabled",
|
||||
"Type": "tinyint(1)",
|
||||
"Nullable": "NO"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "DataEntry",
|
||||
"NewColumn": "DataEntry",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "DataEntry",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "ResultsPrinter",
|
||||
"NewColumn": "ResultsPrinter",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "ResultsPrinter",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "ResultsWriter",
|
||||
"NewColumn": "ResultsWriter",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "ResultsWriter",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "TransitionStart",
|
||||
"NewColumn": "TransitionStart",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "TransitionStart",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "TransitionEnd",
|
||||
"NewColumn": "TransitionEnd",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "TransitionEnd",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "AltProcName",
|
||||
"NewColumn": "AltProcName",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "AltProcName",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "AltProcPeriod",
|
||||
"NewColumn": "AltProcPeriod",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "AltProcPeriod",
|
||||
"Type": "int(11)",
|
||||
"Nullable": "NO"
|
||||
}
|
||||
}
|
||||
],
|
||||
"IsNewTable": false
|
||||
},
|
||||
{
|
||||
"TableName": "test",
|
||||
"ColumnMappings": [
|
||||
{
|
||||
"OldColumn": "Id",
|
||||
"NewColumn": "Id",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "Id",
|
||||
"Type": "int(11)",
|
||||
"Nullable": "NO"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "ItemNr",
|
||||
"NewColumn": "ItemNr",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "ItemNr",
|
||||
"Type": "int(11)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "Name",
|
||||
"NewColumn": "Name",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "Name",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "Part",
|
||||
"NewColumn": "Part",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "Part",
|
||||
"Type": "int(11)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "Publish",
|
||||
"NewColumn": "Publish",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "Publish",
|
||||
"Type": "tinyint(4)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "Evaluate",
|
||||
"NewColumn": "DoEvaluate",
|
||||
"Status": "Renamed",
|
||||
"Note": "",
|
||||
"ColumnDef": {
|
||||
"Name": "Evaluate",
|
||||
"Type": "tinyint(1)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "Qfrom",
|
||||
"NewColumn": "Qfrom",
|
||||
"Status": "Change",
|
||||
"Note": "Could be part of JSON or renamed",
|
||||
"ColumnDefList": [{
|
||||
"Name": "Qfrom",
|
||||
"Type": "float",
|
||||
"Nullable": "YES"
|
||||
},
|
||||
{
|
||||
"Name": "Qfrom",
|
||||
"Type": "double",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"OldColumn": "Qto",
|
||||
"NewColumn": "Qto",
|
||||
"Status": "Change",
|
||||
"Note": "",
|
||||
"ColumnDefList": [
|
||||
{
|
||||
"Name": "Qto",
|
||||
"Type": "float",
|
||||
"Nullable": "YES"
|
||||
},
|
||||
{
|
||||
"Name": "Qto",
|
||||
"Type": "double",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"OldColumn": "Volume",
|
||||
"Status": "Change",
|
||||
"Note": "",
|
||||
"ColumnDefList": [
|
||||
{
|
||||
"Name": "Volume",
|
||||
"Type": "float",
|
||||
"Nullable": "YES"
|
||||
},
|
||||
{
|
||||
"Name": "Volume",
|
||||
"Type": "double",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"OldColumn": "TstTime",
|
||||
"NewColumn": "TestTime",
|
||||
"Status": "update",
|
||||
"Note": "Could be part of JSON or renamed",
|
||||
"ColumnDefList": [
|
||||
{
|
||||
"Name": "TstTime",
|
||||
"Type": "float",
|
||||
"Nullable": "YES"
|
||||
},
|
||||
{
|
||||
"Name": "TestTime",
|
||||
"Type": "double",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"OldColumn": "Repeats",
|
||||
"NewColumn": "Repeats",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "Repeats",
|
||||
"Type": "int(11)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "Emptying",
|
||||
"NewColumn": "DoDraining",
|
||||
"Status": "Renamed",
|
||||
"Note": "",
|
||||
"ColumnDef": {
|
||||
"Name": "Emptying",
|
||||
"Type": "tinyint(1)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "Zeroing",
|
||||
"Status": "uncertain",
|
||||
"Note": "Could be part of JSON or renamed",
|
||||
"ColumnDef": {
|
||||
"Name": "Zeroing",
|
||||
"Type": "tinyint(1)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "DoControlWaterTemp",
|
||||
"Status": "uncertain",
|
||||
"Note": "Could be part of JSON or renamed",
|
||||
"ColumnDef": {
|
||||
"Name": "DoControlWaterTemp",
|
||||
"Type": "tinyint(1)",
|
||||
"Nullable": "NO"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "TempLimLo",
|
||||
"NewColumn": "TempLimLo",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "TempLimLo",
|
||||
"Type": "float",
|
||||
"Nullable": "NO"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "TempLimHi",
|
||||
"NewColumn": "TempLimHi",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "TempLimHi",
|
||||
"Type": "float",
|
||||
"Nullable": "NO"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "PumpPower",
|
||||
"NewColumn": "PumpPower",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "PumpPower",
|
||||
"Type": "float",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "MassRepeats",
|
||||
"NewColumn": "MassRepeats",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "MassRepeats",
|
||||
"Type": "int(11)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "MassSpread",
|
||||
"NewColumn": "MassSpread",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "MassSpread",
|
||||
"Type": "float",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "MassMethod",
|
||||
"NewColumn": "MassMethod",
|
||||
"Status": "Changed",
|
||||
"Note": "`MassMethod` tinyint(3) unsigned DEFAULT NULL,",
|
||||
"ColumnDefList": [
|
||||
{
|
||||
"Name": "MassMethod",
|
||||
"Type": "tinyint(1)",
|
||||
"Nullable": "YES"
|
||||
},
|
||||
{
|
||||
"Name": "MassMethod",
|
||||
"Type": "tinyint(3)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
|
||||
]
|
||||
},
|
||||
{
|
||||
"OldColumn": "TimeBeforeFlow",
|
||||
"NewColumn": "TimeBeforeFlow",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "TimeBeforeFlow",
|
||||
"Type": "int(11)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "TimeFlow2Mass",
|
||||
"NewColumn": "TimeFlow2Mass",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "TimeFlow2Mass",
|
||||
"Type": "int(11)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "TimeMass2Start",
|
||||
"NewColumn": "TimePump2StartV",
|
||||
"Status": "Renamed",
|
||||
"Note": "",
|
||||
"ColumnDef": {
|
||||
"Name": "TimeMass2Start",
|
||||
"Type": "int(11)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "TimeStop2Mass",
|
||||
"NewColumn": "TimeStop2Mass",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "TimeStop2Mass",
|
||||
"Type": "int(11)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "Method",
|
||||
"NewColumn": "Method",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "Method",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "ErrLimLo",
|
||||
"NewColumn": "ErrLimLo",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "ErrLimLo",
|
||||
"Type": "float",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "ErrLimHi",
|
||||
"NewColumn": "ErrLimHi",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "ErrLimHi",
|
||||
"Type": "float",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "Uncertainty",
|
||||
"NewColumn": "Uncertainty",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "Uncertainty",
|
||||
"Type": "float",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "TolerRed",
|
||||
"Status": "Deleted",
|
||||
"ColumnDef": {
|
||||
"Name": "TolerRed",
|
||||
"Type": "double",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "RedType",
|
||||
"Status": "Deleted",
|
||||
"ColumnDef": {
|
||||
"Name": "RedType",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "FeedingPath",
|
||||
"NewColumn": "FeedingPath",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "FeedingPath",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "BenchPath",
|
||||
"NewColumn": "BenchPath",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "BenchPath",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "OutputPath",
|
||||
"NewColumn": "OutputPath",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "OutputPath",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "MetersPath",
|
||||
"NewColumn": "MetersPath",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "MetersPath",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "HeatMetersPath",
|
||||
"NewColumn": "HeatMetersPath",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "HeatMetersPath",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "RelTransBefore",
|
||||
"NewColumn": "TransBefore",
|
||||
"Status": "Renamed",
|
||||
"ColumnDef": {
|
||||
"Name": "RelTransBefore",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "RelTransBetween",
|
||||
"NewColumn": "TransBetween",
|
||||
"Status": "Renamed",
|
||||
"Note": "",
|
||||
"ColumnDef": {
|
||||
"Name": "RelTransBetween",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "RelTransAfter",
|
||||
"NewColumn": "TransAfter",
|
||||
"Status": "Renamed",
|
||||
"Note": "",
|
||||
"ColumnDef": {
|
||||
"Name": "RelTransAfter",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "TransitionAfter",
|
||||
"Status": "Deleted",
|
||||
"Note": "",
|
||||
"ColumnDef": {
|
||||
"Name": "TransitionAfter",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "Procedure_id",
|
||||
"NewColumn": "Procedure_id",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "Procedure_id",
|
||||
"Type": "int(11)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
}
|
||||
],
|
||||
"IsNewTable": false
|
||||
}
|
||||
]
|
||||
}
|
||||
2980
tbfDBBackup/config/schema-mapping_backup.json
Normal file
2980
tbfDBBackup/config/schema-mapping_backup.json
Normal file
File diff suppressed because it is too large
Load Diff
16
tbfDBBackup/configuration/Upgrade.cs
Normal file
16
tbfDBBackup/configuration/Upgrade.cs
Normal file
@ -0,0 +1,16 @@
|
||||
namespace tbfDBBackup.configuration;
|
||||
|
||||
public class Upgrade
|
||||
{
|
||||
public bool Enabled { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string Query { get; set; }
|
||||
public string JSONFileName { get; set; }
|
||||
public string DatabaseName { get; set; }
|
||||
public bool IsOneTimeOpaque { get; set; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"Upgrade: {Name}";
|
||||
}
|
||||
}
|
||||
46
tbfDBBackup/joinConfig/configuration.json
Normal file
46
tbfDBBackup/joinConfig/configuration.json
Normal file
@ -0,0 +1,46 @@
|
||||
{
|
||||
"PathToDumpMysql": "C:\\xampp\\mysql\\bin",
|
||||
"WaitOnEndCmdOpen": false,
|
||||
"PrintConfigurationEnabled": false,
|
||||
"DbConnectionStrings": [
|
||||
{
|
||||
"Name": "Settings DB",
|
||||
"Connection": "SERVER=localhost; DATABASE={DatabaseName}; UID=root; PASSWORD=; CHARSET=utf8;",
|
||||
"DatabaseName": "wrcswindon298",
|
||||
"Enabled": true
|
||||
}
|
||||
],
|
||||
"UpdateString": [
|
||||
{
|
||||
"Enabled": true,
|
||||
"Name": "Alter table Water Meter",
|
||||
"Query": "INSERT INTO `group` (Name, AccessFlags) VALUES ('MetrologicalAuthority', 0);\nINSERT INTO `group` (Name, AccessFlags) VALUES ('WaterMeterAuthority', 0);",
|
||||
"DatabaseName": "wrcswindon298",
|
||||
"IsOneTimeOpaque": true
|
||||
},
|
||||
{
|
||||
"Enabled": true,
|
||||
"Name": "Alter table Water Meter",
|
||||
"Query": "INSERT INTO usersgroups (Group_id, User_id) VALUES (8, 1);\nINSERT INTO usersgroups (Group_id, User_id) VALUES (9, 1);",
|
||||
"DatabaseName": "wrcswindon298",
|
||||
"IsOneTimeOpaque": true
|
||||
}
|
||||
],
|
||||
"UpgradeDatabase": [
|
||||
{
|
||||
"Enabled": true,
|
||||
"Name": "Upgrade by JSON",
|
||||
"Query": "",
|
||||
"JSONFileName": "",
|
||||
"DatabaseName": "wrcswindon298",
|
||||
"IsOneTimeOpaque": true
|
||||
},
|
||||
{
|
||||
"Enabled": true,
|
||||
"Name": "Alter table Water Meter",
|
||||
"Query": "INSERT INTO usersgroups (Group_id, User_id) VALUES (8, 1);\nINSERT INTO usersgroups (Group_id, User_id) VALUES (9, 1);",
|
||||
"DatabaseName": "wrcswindon298",
|
||||
"IsOneTimeOpaque": true
|
||||
}
|
||||
]
|
||||
}
|
||||
577
tbfDBBackup/joinConfig/new-r.sql
Normal file
577
tbfDBBackup/joinConfig/new-r.sql
Normal file
File diff suppressed because one or more lines are too long
720
tbfDBBackup/joinConfig/new.sql
Normal file
720
tbfDBBackup/joinConfig/new.sql
Normal file
File diff suppressed because one or more lines are too long
76644
tbfDBBackup/joinConfig/old-r.sql
Normal file
76644
tbfDBBackup/joinConfig/old-r.sql
Normal file
File diff suppressed because it is too large
Load Diff
15879
tbfDBBackup/joinConfig/old.sql
Normal file
15879
tbfDBBackup/joinConfig/old.sql
Normal file
File diff suppressed because it is too large
Load Diff
815
tbfDBBackup/joinConfig/schema-mapping.json
Normal file
815
tbfDBBackup/joinConfig/schema-mapping.json
Normal file
@ -0,0 +1,815 @@
|
||||
{
|
||||
"Tables": [
|
||||
{
|
||||
"TableName": "procedure",
|
||||
"ColumnMappings": [
|
||||
{
|
||||
"OldColumn": "Id",
|
||||
"NewColumn": "Id",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "Id",
|
||||
"Type": "int(11)",
|
||||
"IsPrimaryKey": true,
|
||||
"Nullable": "NO"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "ItemNr",
|
||||
"NewColumn": "ItemNr",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "ItemNr",
|
||||
"Type": "int(11)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "Name",
|
||||
"NewColumn": "Name",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "Name",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "Description",
|
||||
"NewColumn": "Description",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "Description",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "CreationUser",
|
||||
"NewColumn": "CreationUser",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "CreationUser",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "CreationTime",
|
||||
"NewColumn": "CreationTime",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "CreationTime",
|
||||
"Type": "datetime",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "LastChgUser",
|
||||
"NewColumn": "LastChgUser",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "LastChgUser",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "LastChgTime",
|
||||
"NewColumn": "LastChgTime",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "LastChgTime",
|
||||
"Type": "datetime",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "LongDescription",
|
||||
"NewColumn": "LongDescription",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "LongDescription",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "ProcedureState",
|
||||
"NewColumn": "ProcedureState",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "ProcedureState",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "Revision",
|
||||
"NewColumn": "Revision",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "Revision",
|
||||
"Type": "int(11)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "PredecessorId",
|
||||
"NewColumn": "PredecessorId",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "PredecessorId",
|
||||
"Type": "int(11)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "ObtainedByCopy",
|
||||
"NewColumn": "ObtainedByCopy",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "ObtainedByCopy",
|
||||
"Type": "tinyint(1)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "MetersKind",
|
||||
"NewColumn": "MetersKind",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "MetersKind",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "Watermeters",
|
||||
"NewColumn": "Watermeters",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "Watermeters",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "ProtocolTitle",
|
||||
"Status": "new",
|
||||
"Note": "New",
|
||||
"ColumnDef": {
|
||||
"Name": "ProtocolTitle",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "Protected",
|
||||
"NewColumn": "Protected",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "Protected",
|
||||
"Type": "tinyint(1)",
|
||||
"Nullable": "NO"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "MustBeComplete",
|
||||
"NewColumn": "MustBeComplete",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "MustBeComplete",
|
||||
"Type": "tinyint(1)",
|
||||
"Nullable": "NO"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "ManualCtrlDisabled",
|
||||
"NewColumn": "ManualCtrlDisabled",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "ManualCtrlDisabled",
|
||||
"Type": "tinyint(1)",
|
||||
"Nullable": "NO"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "DataEntry",
|
||||
"NewColumn": "DataEntry",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "DataEntry",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "ResultsPrinter",
|
||||
"NewColumn": "ResultsPrinter",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "ResultsPrinter",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "ResultsWriter",
|
||||
"NewColumn": "ResultsWriter",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "ResultsWriter",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "TransitionStart",
|
||||
"NewColumn": "TransitionStart",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "TransitionStart",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "TransitionEnd",
|
||||
"NewColumn": "TransitionEnd",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "TransitionEnd",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "AltProcName",
|
||||
"NewColumn": "AltProcName",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "AltProcName",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "AltProcPeriod",
|
||||
"NewColumn": "AltProcPeriod",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "AltProcPeriod",
|
||||
"Type": "int(11)",
|
||||
"Nullable": "NO"
|
||||
}
|
||||
}
|
||||
],
|
||||
"IsNewTable": false
|
||||
},
|
||||
{
|
||||
"TableName": "test",
|
||||
"ColumnMappings": [
|
||||
{
|
||||
"OldColumn": "Id",
|
||||
"NewColumn": "Id",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "Id",
|
||||
"Type": "int(11)",
|
||||
"IsPrimaryKey": true,
|
||||
"Nullable": "NO"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "ItemNr",
|
||||
"NewColumn": "ItemNr",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "ItemNr",
|
||||
"Type": "int(11)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "Name",
|
||||
"NewColumn": "Name",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "Name",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "Part",
|
||||
"NewColumn": "Part",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "Part",
|
||||
"Type": "int(11)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "Publish",
|
||||
"NewColumn": "Publish",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "Publish",
|
||||
"Type": "tinyint(4)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "Evaluate",
|
||||
"NewColumn": "DoEvaluate",
|
||||
"Status": "Renamed",
|
||||
"Note": "",
|
||||
"ColumnDef": {
|
||||
"Name": "Evaluate",
|
||||
"Type": "tinyint(1)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "Qfrom",
|
||||
"NewColumn": "Qfrom",
|
||||
"Status": "Change",
|
||||
"Note": "Could be part of JSON or renamed",
|
||||
"ColumnDefList": [{
|
||||
"Name": "Qfrom",
|
||||
"Type": "float",
|
||||
"Nullable": "YES"
|
||||
},
|
||||
{
|
||||
"Name": "Qfrom",
|
||||
"Type": "double",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"OldColumn": "Qto",
|
||||
"NewColumn": "Qto",
|
||||
"Status": "Change",
|
||||
"Note": "",
|
||||
"ColumnDefList": [
|
||||
{
|
||||
"Name": "Qto",
|
||||
"Type": "float",
|
||||
"Nullable": "YES"
|
||||
},
|
||||
{
|
||||
"Name": "Qto",
|
||||
"Type": "double",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"OldColumn": "Volume",
|
||||
"Status": "Change",
|
||||
"Note": "",
|
||||
"ColumnDefList": [
|
||||
{
|
||||
"Name": "Volume",
|
||||
"Type": "float",
|
||||
"Nullable": "YES"
|
||||
},
|
||||
{
|
||||
"Name": "Volume",
|
||||
"Type": "double",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"OldColumn": "TstTime",
|
||||
"NewColumn": "TestTime",
|
||||
"Status": "update",
|
||||
"Note": "Could be part of JSON or renamed",
|
||||
"ColumnDefList": [
|
||||
{
|
||||
"Name": "TstTime",
|
||||
"Type": "float",
|
||||
"Nullable": "YES"
|
||||
},
|
||||
{
|
||||
"Name": "TestTime",
|
||||
"Type": "double",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"OldColumn": "Repeats",
|
||||
"NewColumn": "Repeats",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "Repeats",
|
||||
"Type": "int(11)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "Emptying",
|
||||
"NewColumn": "DoDraining",
|
||||
"Status": "Renamed",
|
||||
"Note": "",
|
||||
"ColumnDef": {
|
||||
"Name": "Emptying",
|
||||
"Type": "tinyint(1)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "Zeroing",
|
||||
"Status": "uncertain",
|
||||
"Note": "Could be part of JSON or renamed",
|
||||
"ColumnDef": {
|
||||
"Name": "Zeroing",
|
||||
"Type": "tinyint(1)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "DoControlWaterTemp",
|
||||
"Status": "uncertain",
|
||||
"Note": "Could be part of JSON or renamed",
|
||||
"ColumnDef": {
|
||||
"Name": "DoControlWaterTemp",
|
||||
"Type": "tinyint(1)",
|
||||
"Nullable": "NO"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "TempLimLo",
|
||||
"NewColumn": "TempLimLo",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "TempLimLo",
|
||||
"Type": "float",
|
||||
"Nullable": "NO"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "TempLimHi",
|
||||
"NewColumn": "TempLimHi",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "TempLimHi",
|
||||
"Type": "float",
|
||||
"Nullable": "NO"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "PumpPower",
|
||||
"NewColumn": "PumpPower",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "PumpPower",
|
||||
"Type": "float",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "MassRepeats",
|
||||
"NewColumn": "MassRepeats",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "MassRepeats",
|
||||
"Type": "int(11)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "MassSpread",
|
||||
"NewColumn": "MassSpread",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "MassSpread",
|
||||
"Type": "float",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "MassMethod",
|
||||
"NewColumn": "MassMethod",
|
||||
"Status": "Changed",
|
||||
"Note": "`MassMethod` tinyint(3) unsigned DEFAULT NULL,",
|
||||
"ColumnDefList": [
|
||||
{
|
||||
"Name": "MassMethod",
|
||||
"Type": "tinyint(1)",
|
||||
"Nullable": "YES"
|
||||
},
|
||||
{
|
||||
"Name": "MassMethod",
|
||||
"Type": "tinyint(3)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
|
||||
]
|
||||
},
|
||||
{
|
||||
"OldColumn": "TimeBeforeFlow",
|
||||
"NewColumn": "TimeBeforeFlow",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "TimeBeforeFlow",
|
||||
"Type": "int(11)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "TimeFlow2Mass",
|
||||
"NewColumn": "TimeFlow2Mass",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "TimeFlow2Mass",
|
||||
"Type": "int(11)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "TimeMass2Start",
|
||||
"NewColumn": "TimePump2StartV",
|
||||
"Status": "Renamed",
|
||||
"Note": "",
|
||||
"ColumnDef": {
|
||||
"Name": "TimeMass2Start",
|
||||
"Type": "int(11)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "TimeStop2Mass",
|
||||
"NewColumn": "TimeStop2Mass",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "TimeStop2Mass",
|
||||
"Type": "int(11)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "Method",
|
||||
"NewColumn": "Method",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "Method",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "ErrLimLo",
|
||||
"NewColumn": "ErrLimLo",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "ErrLimLo",
|
||||
"Type": "float",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "ErrLimHi",
|
||||
"NewColumn": "ErrLimHi",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "ErrLimHi",
|
||||
"Type": "float",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "Uncertainty",
|
||||
"NewColumn": "Uncertainty",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "Uncertainty",
|
||||
"Type": "float",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "TolerRed",
|
||||
"Status": "Deleted",
|
||||
"ColumnDef": {
|
||||
"Name": "TolerRed",
|
||||
"Type": "double",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "RedType",
|
||||
"Status": "Deleted",
|
||||
"ColumnDef": {
|
||||
"Name": "RedType",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "FeedingPath",
|
||||
"NewColumn": "FeedingPath",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "FeedingPath",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "BenchPath",
|
||||
"NewColumn": "BenchPath",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "BenchPath",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "OutputPath",
|
||||
"NewColumn": "OutputPath",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "OutputPath",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "MetersPath",
|
||||
"NewColumn": "MetersPath",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "MetersPath",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "HeatMetersPath",
|
||||
"NewColumn": "HeatMetersPath",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "HeatMetersPath",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "RelTransBefore",
|
||||
"NewColumn": "TransBefore",
|
||||
"Status": "Renamed",
|
||||
"ColumnDef": {
|
||||
"Name": "RelTransBefore",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "RelTransBetween",
|
||||
"NewColumn": "TransBetween",
|
||||
"Status": "Renamed",
|
||||
"Note": "",
|
||||
"ColumnDef": {
|
||||
"Name": "RelTransBetween",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "RelTransAfter",
|
||||
"NewColumn": "TransAfter",
|
||||
"Status": "Renamed",
|
||||
"Note": "",
|
||||
"ColumnDef": {
|
||||
"Name": "RelTransAfter",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "TransitionAfter",
|
||||
"Status": "Deleted",
|
||||
"Note": "",
|
||||
"ColumnDef": {
|
||||
"Name": "TransitionAfter",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "Procedure_id",
|
||||
"NewColumn": "Procedure_id",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "Procedure_id",
|
||||
"Type": "int(11)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
}
|
||||
],
|
||||
"IsNewTable": false
|
||||
},
|
||||
{
|
||||
"TableName": "componentprocedure",
|
||||
"ColumnMappings": [
|
||||
{
|
||||
"OldColumn": "Id",
|
||||
"NewColumn": "Id",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "Id",
|
||||
"Type": "int(11)",
|
||||
"IsPrimaryKey": true,
|
||||
"Nullable": "NO"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "CmpntName",
|
||||
"NewColumn": "CmpntName",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "CmpntName",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "Parameters",
|
||||
"NewColumn": "Parameters",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "Parameters",
|
||||
"Type": "varchar(8000)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "Procedure_id",
|
||||
"NewColumn": "Procedure_id",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "Procedure_id",
|
||||
"Type": "int(11)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
}
|
||||
],
|
||||
"IsNewTable": false
|
||||
},
|
||||
{
|
||||
"TableName": "componenttest",
|
||||
"ColumnMappings": [
|
||||
{
|
||||
"OldColumn": "Id",
|
||||
"NewColumn": "Id",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "Id",
|
||||
"Type": "int(11)",
|
||||
"IsPrimaryKey": true,
|
||||
"Nullable": "NO"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "CmpntName",
|
||||
"NewColumn": "CmpntName",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "CmpntName",
|
||||
"Type": "varchar(255)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "Parameters",
|
||||
"NewColumn": "Parameters",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "Parameters",
|
||||
"Type": "varchar(8000)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OldColumn": "Test_id",
|
||||
"NewColumn": "Test_id",
|
||||
"Status": "matched",
|
||||
"ColumnDef": {
|
||||
"Name": "Test_id",
|
||||
"Type": "int(11)",
|
||||
"Nullable": "YES"
|
||||
}
|
||||
}
|
||||
],
|
||||
"IsNewTable": false
|
||||
}
|
||||
|
||||
]
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user