1377 lines
53 KiB
C#
1377 lines
53 KiB
C#
using System;
|
|
using System.Drawing;
|
|
using System.Collections;
|
|
using System.ComponentModel;
|
|
using System.Windows.Forms;
|
|
using System.Data;
|
|
using FirebirdSql.Data.FirebirdClient;
|
|
using System.Data.SqlClient;
|
|
using System.Text;
|
|
using System.Threading;
|
|
using System.Text.RegularExpressions;
|
|
|
|
namespace ToMSSQL
|
|
{
|
|
/// <summary>
|
|
/// Summary description for Form1.
|
|
/// </summary>
|
|
public class Form1 : System.Windows.Forms.Form
|
|
{
|
|
/// <summary>
|
|
/// Required designer variable.
|
|
/// </summary>
|
|
private System.ComponentModel.Container components = null;
|
|
|
|
private System.Windows.Forms.Button btnImport;
|
|
private System.Windows.Forms.Button btnCancel;
|
|
private Infragistics.Win.Misc.UltraLabel ultraLabel1;
|
|
private Infragistics.Win.Misc.UltraLabel ultraLabel2;
|
|
private Infragistics.Win.UltraWinEditors.UltraTextEditor edFBConnect;
|
|
private Infragistics.Win.UltraWinEditors.UltraTextEditor edMSConnect;
|
|
private Infragistics.Win.UltraWinProgressBar.UltraProgressBar pgCurrentOp;
|
|
private System.Windows.Forms.Button btnTest;
|
|
private BackgroundWorker bw;
|
|
private Infragistics.Win.UltraWinProgressBar.UltraProgressBar pgOverall;
|
|
|
|
public Form1()
|
|
{
|
|
//
|
|
// Required for Windows Form Designer support
|
|
//
|
|
InitializeComponent();
|
|
|
|
//
|
|
// TODO: Add any constructor code after InitializeComponent call
|
|
//
|
|
}
|
|
|
|
/// <summary>
|
|
/// Clean up any resources being used.
|
|
/// </summary>
|
|
protected override void Dispose( bool disposing )
|
|
{
|
|
if( disposing )
|
|
{
|
|
if (components != null)
|
|
{
|
|
components.Dispose();
|
|
}
|
|
}
|
|
base.Dispose( disposing );
|
|
}
|
|
|
|
#region Windows Form Designer generated code
|
|
/// <summary>
|
|
/// Required method for Designer support - do not modify
|
|
/// the contents of this method with the code editor.
|
|
/// </summary>
|
|
private void InitializeComponent()
|
|
{
|
|
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Form1));
|
|
this.pgCurrentOp = new Infragistics.Win.UltraWinProgressBar.UltraProgressBar();
|
|
this.btnImport = new System.Windows.Forms.Button();
|
|
this.btnCancel = new System.Windows.Forms.Button();
|
|
this.edFBConnect = new Infragistics.Win.UltraWinEditors.UltraTextEditor();
|
|
this.edMSConnect = new Infragistics.Win.UltraWinEditors.UltraTextEditor();
|
|
this.ultraLabel1 = new Infragistics.Win.Misc.UltraLabel();
|
|
this.ultraLabel2 = new Infragistics.Win.Misc.UltraLabel();
|
|
this.pgOverall = new Infragistics.Win.UltraWinProgressBar.UltraProgressBar();
|
|
this.btnTest = new System.Windows.Forms.Button();
|
|
this.bw = new System.ComponentModel.BackgroundWorker();
|
|
((System.ComponentModel.ISupportInitialize)(this.edFBConnect)).BeginInit();
|
|
((System.ComponentModel.ISupportInitialize)(this.edMSConnect)).BeginInit();
|
|
this.SuspendLayout();
|
|
//
|
|
// pgCurrentOp
|
|
//
|
|
this.pgCurrentOp.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
|
|
| System.Windows.Forms.AnchorStyles.Right)));
|
|
this.pgCurrentOp.Location = new System.Drawing.Point(1, 191);
|
|
this.pgCurrentOp.Name = "pgCurrentOp";
|
|
this.pgCurrentOp.Size = new System.Drawing.Size(665, 27);
|
|
this.pgCurrentOp.Step = 1;
|
|
this.pgCurrentOp.TabIndex = 0;
|
|
this.pgCurrentOp.Text = "[Formatted]";
|
|
this.pgCurrentOp.Visible = false;
|
|
//
|
|
// btnImport
|
|
//
|
|
this.btnImport.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
|
|
this.btnImport.Image = ((System.Drawing.Image)(resources.GetObject("btnImport.Image")));
|
|
this.btnImport.Location = new System.Drawing.Point(569, 225);
|
|
this.btnImport.Name = "btnImport";
|
|
this.btnImport.Size = new System.Drawing.Size(90, 40);
|
|
this.btnImport.TabIndex = 28;
|
|
this.btnImport.Visible = false;
|
|
this.btnImport.Click += new System.EventHandler(this.btnImport_Click);
|
|
//
|
|
// btnCancel
|
|
//
|
|
this.btnCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
|
this.btnCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
|
|
this.btnCancel.Image = ((System.Drawing.Image)(resources.GetObject("btnCancel.Image")));
|
|
this.btnCancel.Location = new System.Drawing.Point(8, 227);
|
|
this.btnCancel.Name = "btnCancel";
|
|
this.btnCancel.Size = new System.Drawing.Size(94, 40);
|
|
this.btnCancel.TabIndex = 27;
|
|
this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click);
|
|
//
|
|
// edFBConnect
|
|
//
|
|
this.edFBConnect.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
|
|
| System.Windows.Forms.AnchorStyles.Right)));
|
|
this.edFBConnect.Location = new System.Drawing.Point(2, 36);
|
|
this.edFBConnect.Name = "edFBConnect";
|
|
this.edFBConnect.Size = new System.Drawing.Size(665, 24);
|
|
this.edFBConnect.TabIndex = 29;
|
|
this.edFBConnect.Text = "ServerType=1;DataBase=C:\\Program Files\\Ground Zero Tech-Works Inc\\AyaNova 3\\AYANO" +
|
|
"VA.FDB;Dialect=3;";
|
|
this.edFBConnect.ValueChanged += new System.EventHandler(this.edFBConnect_ValueChanged);
|
|
//
|
|
// edMSConnect
|
|
//
|
|
this.edMSConnect.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
|
|
| System.Windows.Forms.AnchorStyles.Right)));
|
|
this.edMSConnect.Location = new System.Drawing.Point(2, 110);
|
|
this.edMSConnect.Name = "edMSConnect";
|
|
this.edMSConnect.Size = new System.Drawing.Size(663, 24);
|
|
this.edMSConnect.TabIndex = 30;
|
|
this.edMSConnect.Text = "Server=COMPUTERNAME\\SQLExpress;initial catalog=master;User Id=sa; Password=PASSWO" +
|
|
"RD;";
|
|
this.edMSConnect.ValueChanged += new System.EventHandler(this.edMSConnect_ValueChanged);
|
|
//
|
|
// ultraLabel1
|
|
//
|
|
this.ultraLabel1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
|
|
| System.Windows.Forms.AnchorStyles.Right)));
|
|
this.ultraLabel1.Location = new System.Drawing.Point(2, 3);
|
|
this.ultraLabel1.Name = "ultraLabel1";
|
|
this.ultraLabel1.Size = new System.Drawing.Size(665, 27);
|
|
this.ultraLabel1.TabIndex = 31;
|
|
this.ultraLabel1.Text = "Firebird database connection string:";
|
|
//
|
|
// ultraLabel2
|
|
//
|
|
this.ultraLabel2.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
|
|
| System.Windows.Forms.AnchorStyles.Right)));
|
|
this.ultraLabel2.Location = new System.Drawing.Point(2, 77);
|
|
this.ultraLabel2.Name = "ultraLabel2";
|
|
this.ultraLabel2.Size = new System.Drawing.Size(665, 27);
|
|
this.ultraLabel2.TabIndex = 32;
|
|
this.ultraLabel2.Text = "Microsoft SQL database connection string:";
|
|
//
|
|
// pgOverall
|
|
//
|
|
this.pgOverall.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
|
|
| System.Windows.Forms.AnchorStyles.Right)));
|
|
this.pgOverall.Location = new System.Drawing.Point(1, 156);
|
|
this.pgOverall.Name = "pgOverall";
|
|
this.pgOverall.Size = new System.Drawing.Size(665, 27);
|
|
this.pgOverall.Step = 1;
|
|
this.pgOverall.TabIndex = 33;
|
|
this.pgOverall.Text = "[Formatted]";
|
|
this.pgOverall.Visible = false;
|
|
//
|
|
// btnTest
|
|
//
|
|
this.btnTest.Location = new System.Drawing.Point(244, 232);
|
|
this.btnTest.Name = "btnTest";
|
|
this.btnTest.Size = new System.Drawing.Size(271, 26);
|
|
this.btnTest.TabIndex = 34;
|
|
this.btnTest.Text = "Open database connections";
|
|
this.btnTest.Click += new System.EventHandler(this.btnTest_Click);
|
|
//
|
|
// bw
|
|
//
|
|
this.bw.WorkerReportsProgress = true;
|
|
this.bw.WorkerSupportsCancellation = true;
|
|
this.bw.DoWork += new System.ComponentModel.DoWorkEventHandler(this.bw_DoWork);
|
|
this.bw.ProgressChanged += new System.ComponentModel.ProgressChangedEventHandler(this.bw_ProgressChanged);
|
|
this.bw.RunWorkerCompleted += new System.ComponentModel.RunWorkerCompletedEventHandler(this.bw_RunWorkerCompleted);
|
|
//
|
|
// Form1
|
|
//
|
|
this.AutoScaleBaseSize = new System.Drawing.Size(6, 15);
|
|
this.CancelButton = this.btnCancel;
|
|
this.ClientSize = new System.Drawing.Size(674, 268);
|
|
this.ControlBox = false;
|
|
this.Controls.Add(this.btnTest);
|
|
this.Controls.Add(this.pgOverall);
|
|
this.Controls.Add(this.ultraLabel2);
|
|
this.Controls.Add(this.ultraLabel1);
|
|
this.Controls.Add(this.edMSConnect);
|
|
this.Controls.Add(this.edFBConnect);
|
|
this.Controls.Add(this.btnImport);
|
|
this.Controls.Add(this.btnCancel);
|
|
this.Controls.Add(this.pgCurrentOp);
|
|
this.MinimumSize = new System.Drawing.Size(0, 265);
|
|
this.Name = "Form1";
|
|
this.Text = "FireBird to SQL Migrator";
|
|
this.Load += new System.EventHandler(this.Form1_Load);
|
|
((System.ComponentModel.ISupportInitialize)(this.edFBConnect)).EndInit();
|
|
((System.ComponentModel.ISupportInitialize)(this.edMSConnect)).EndInit();
|
|
this.ResumeLayout(false);
|
|
this.PerformLayout();
|
|
|
|
}
|
|
#endregion
|
|
|
|
/// <summary>
|
|
/// The main entry point for the application.
|
|
/// </summary>
|
|
[STAThread]
|
|
static void Main()
|
|
{
|
|
Application.Run(new Form1());
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// __ _ _ ___ ____ __ __ __ __ __ ___ ___
|
|
// / _)( )( )/ __)(_ _)/ \( \/ ) / _)/ \( \( _)
|
|
// ( (_ )()( \__ \ )( ( () )) ( ( (_( () )) ) )) _)
|
|
// \__) \__/ (___/ (__) \__/(_/\/\_) \__)\__/(___/(___)
|
|
//************************************************************
|
|
|
|
FbConnection fbcn = null;
|
|
System.Data.SqlClient.SqlConnection mscn=null;
|
|
//private Thread tr;
|
|
private void btnCancel_Click(object sender, System.EventArgs e)
|
|
{
|
|
//if(tr!=null && tr.IsAlive)
|
|
// tr.Abort();
|
|
bw.CancelAsync();
|
|
this.Close();
|
|
|
|
}
|
|
|
|
private void btnImport_Click(object sender, System.EventArgs e)
|
|
{
|
|
|
|
DialogResult result=MessageBox.Show(
|
|
"WARNING: If you proceed a new database called \"AyaNova\" \r\n"+
|
|
"will be created on the Microsoft SQL server you have indicated.\r\n\r\n" +
|
|
|
|
"If there is an existing AyaNova database on that server it will be\r\n" +
|
|
"erased prior to importing data from the Firebird AyaNova database.\r\n\r\n"+
|
|
|
|
"There is no way to reverse this process once it has started.\r\n\r\n"+
|
|
|
|
"Are you certain you wish to proceed?","Warning",MessageBoxButtons.YesNo,
|
|
MessageBoxIcon.Warning,MessageBoxDefaultButton.Button2);
|
|
|
|
if (result != DialogResult.Yes)
|
|
return;
|
|
btnImport.Visible = false;
|
|
this.pgCurrentOp.Visible = true;
|
|
this.pgOverall.Visible = true;
|
|
bw.RunWorkerAsync();
|
|
//tr = new Thread(new ThreadStart(this.DoImport));
|
|
//tr.IsBackground = true;
|
|
//tr.Start();
|
|
|
|
}
|
|
|
|
public static string DisplayVersion(Version fileVersion)//case 2003
|
|
{
|
|
return fileVersion.Major.ToString() + "." + fileVersion.Minor.ToString();
|
|
}
|
|
|
|
private void Form1_Load(object sender, System.EventArgs e)
|
|
{
|
|
System.Reflection.Assembly a = System.Reflection.Assembly.GetExecutingAssembly();
|
|
System.Text.StringBuilder sb = new StringBuilder();
|
|
sb.Append("AyaNova® FireBird to MSSQL migrator ");
|
|
sb.Append(DisplayVersion(a.GetName().Version));
|
|
sb.Append(" ");
|
|
|
|
System.Diagnostics.FileVersionInfo fileVersion = System.Diagnostics.FileVersionInfo.GetVersionInfo(a.Location);
|
|
int nHotFix = fileVersion.FileBuildPart;//case 2003
|
|
if (nHotFix > 0)
|
|
sb.AppendLine("(Patch " + nHotFix.ToString() + ")");
|
|
|
|
this.Text = sb.ToString();
|
|
|
|
//Case 642 so that it matches the new db location
|
|
this.edFBConnect.Text="ServerType=1;DataBase=" +
|
|
Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData) +
|
|
"\\AyaNovaData\\AYANOVA.FDB;Dialect=3;";
|
|
|
|
#if(DEBUG)
|
|
//this.edFBConnect.Text = @"ServerType=1;DataBase=C:\data\AyaNova\database\AYANOVA.FDB;Dialect=3;";
|
|
//this.edMSConnect.Text = @"Server=VIRTDEVJOHN;initial catalog=master;User Id=sa; Password=abraxis;";
|
|
this.edFBConnect.Text = @"ServerType=1;DataBase=C:\data\AyaNova\database\AYANOVA.FDB;Dialect=3;";
|
|
this.edMSConnect.Text = @"Server=DEV-V7-LAPTOP\SQLEXPRESS;initial catalog=master;User Id=sa; Password=abraxis;";
|
|
#endif
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#region Create sql db
|
|
private void CreateSQLDatabase(string sConnection, bool bDeleteExisting)
|
|
{
|
|
//this.pgCurrentOp.Maximum=100;
|
|
//this.pgCurrentOp.Text="Create SQL database [Formatted]";
|
|
//this.pgCurrentOp.Value=10;
|
|
Report(10, -1, "Connecting to MSSQL server", "");
|
|
mscn = new SqlConnection(sConnection);
|
|
SqlCommand cm = new SqlCommand();
|
|
cm.Connection=mscn;
|
|
try
|
|
{
|
|
mscn.Open();
|
|
|
|
if(bDeleteExisting)
|
|
{
|
|
//Delete if present
|
|
cm.CommandText=("IF EXISTS (SELECT name FROM sysdatabases " +
|
|
"WHERE name = N'AyaNova') DROP DATABASE AyaNova");
|
|
Report(20, -1, "Deleting existing AyaNova on MSSQL (if present)", "");
|
|
cm.ExecuteNonQuery();
|
|
}
|
|
//this.pgCurrentOp.Value=50;
|
|
//Create new
|
|
Report(50, -1, "Creating new AyaNova on MSSQL", "");
|
|
cm.CommandText=" CREATE DATABASE AyaNova ";
|
|
cm.ExecuteNonQuery();
|
|
|
|
}
|
|
catch
|
|
{
|
|
throw;
|
|
}
|
|
finally
|
|
{
|
|
mscn.Close();
|
|
}
|
|
//this.pgCurrentOp.Value=100;
|
|
Report(100, -1, "Created new AyaNova on MSSQL", "");
|
|
return;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Tables
|
|
private void MigrateTables()
|
|
{
|
|
SqlCommand cm = new SqlCommand();
|
|
cm.Connection=mscn;
|
|
StringBuilder q=new StringBuilder();
|
|
|
|
|
|
|
|
DataTable t=fbcn.GetSchema("Tables", new string[] { null, null,null, "TABLE" });
|
|
//this.pgCurrentOp.Value=0;
|
|
double nTotalRows = t.Rows.Count;
|
|
double nCurrentRow = 0;
|
|
int nProgress = 0;
|
|
//pgCurrentOp.Maximum=t.Rows.Count;
|
|
|
|
|
|
bool bHasIdentity=false;//flag that table being processed has an identity column (hard coded)
|
|
string sIdentityColumnName="";
|
|
|
|
//iterate all tables
|
|
foreach(DataRow drTable in t.Rows)
|
|
{
|
|
|
|
//check for current table
|
|
//requiring an identity column set
|
|
switch(drTable["TABLE_NAME"].ToString())
|
|
{
|
|
case "APARTINVENTORYADJUSTMENT":
|
|
sIdentityColumnName="AADJUSTMENTNUMBER";
|
|
bHasIdentity=true;
|
|
break;
|
|
|
|
case "APURCHASEORDER":
|
|
sIdentityColumnName="APONUMBER";
|
|
bHasIdentity=true;
|
|
break;
|
|
|
|
case "AWORKORDERPREVENTIVEMAINTENANCE":
|
|
sIdentityColumnName="APREVENTIVEMAINTENANCENUMBER";
|
|
bHasIdentity=true;
|
|
break;
|
|
|
|
case "AWORKORDERQUOTE":
|
|
sIdentityColumnName="AQUOTENUMBER";
|
|
bHasIdentity=true;
|
|
break;
|
|
|
|
case "AWORKORDERSERVICE":
|
|
sIdentityColumnName="ASERVICENUMBER";
|
|
bHasIdentity=true;
|
|
break;
|
|
|
|
default:
|
|
bHasIdentity=false;
|
|
sIdentityColumnName="";
|
|
break;
|
|
}
|
|
nCurrentRow++;
|
|
nProgress = (int)((nCurrentRow / nTotalRows) * 100);
|
|
Report(nProgress, -1, "Table " + drTable["TABLE_NAME"].ToString(), "");
|
|
//this.pgCurrentOp.Text="Create "+ drTable["TABLE_NAME"].ToString()+ " [Formatted]";
|
|
q.Append("CREATE TABLE ");
|
|
q.Append(drTable["TABLE_NAME"].ToString());
|
|
q.Append(" (");
|
|
DataTable tColumns= fbcn.GetSchema("Columns", new string[] { null,null, drTable["TABLE_NAME"].ToString() });
|
|
foreach(DataRow drColumns in tColumns.Rows)
|
|
{
|
|
q.Append(drColumns["COLUMN_NAME"].ToString());
|
|
q.Append(" ");
|
|
|
|
string sType="";
|
|
if(drColumns["DOMAIN_NAME"]!=System.DBNull.Value)
|
|
{
|
|
sType=drColumns["DOMAIN_NAME"].ToString();
|
|
|
|
}
|
|
else
|
|
sType=drColumns["COLUMN_DATA_TYPE"].ToString();
|
|
|
|
switch(sType)
|
|
{
|
|
//DOMAIN TYPES
|
|
case "D_GUID":
|
|
q.Append("uniqueidentifier");
|
|
break;
|
|
case "D_MEMO":
|
|
q.Append("ntext");
|
|
break;
|
|
case "D_BOOL":
|
|
q.Append("bit");
|
|
break;
|
|
|
|
//STANDARD TYPES
|
|
case "smallint":
|
|
q.Append("smallint");
|
|
break;
|
|
case "varchar":
|
|
q.Append("nvarchar");
|
|
q.Append(" (");
|
|
q.Append(drColumns["COLUMN_SIZE"].ToString());
|
|
q.Append(")");
|
|
break;
|
|
case "char":
|
|
q.Append("char");
|
|
q.Append(" (");
|
|
q.Append(drColumns["COLUMN_SIZE"].ToString());
|
|
q.Append(")");
|
|
break;
|
|
case "timestamp":
|
|
q.Append("datetime");
|
|
break;
|
|
|
|
case "decimal":
|
|
q.Append("decimal (19,5)");
|
|
break;
|
|
case "integer":
|
|
q.Append("int");
|
|
break;
|
|
|
|
case "bigint":
|
|
q.Append("bigint");
|
|
break;
|
|
|
|
case "blob":
|
|
q.Append("image");
|
|
break;
|
|
default:
|
|
throw new System.ApplicationException("Migrate tables: Unknown type: " + sType +
|
|
"\r\n\r\nIN: " + q.ToString());
|
|
}
|
|
|
|
//Set IDENTITY IF applicable
|
|
if (bHasIdentity && drColumns["COLUMN_NAME"].ToString() == sIdentityColumnName)
|
|
q.Append(" IDENTITY ");
|
|
|
|
//Nullable?
|
|
if (((bool)drColumns["IS_NULLABLE"]) == false)//Case 649 Used to be 0 now is boolean false
|
|
q.Append(" NOT NULL");
|
|
else
|
|
q.Append(" NULL");
|
|
|
|
q.Append(", ");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
q.Append(" )");
|
|
cm.CommandText=q.ToString();
|
|
cm.ExecuteNonQuery();
|
|
q.Length=0;
|
|
//pgCurrentOp.PerformStep();
|
|
}
|
|
Report(100, -1, "Finished", "Migrating table structure");
|
|
}
|
|
|
|
#endregion tables
|
|
|
|
#region Copy data
|
|
private void CopyData()
|
|
{
|
|
SqlCommand cm = new SqlCommand();
|
|
cm.Connection=mscn;
|
|
bool bHasIdentity=false;
|
|
|
|
DataTable t=fbcn.GetSchema("Tables", new string[] { null, null,null, "TABLE" });
|
|
//this.pgCurrentOp.Value=0;
|
|
//pgCurrentOp.Maximum=t.Rows.Count;
|
|
double nTotalRows = t.Rows.Count;
|
|
double nCurrentRow = 0;
|
|
int nProgress = 0;
|
|
|
|
|
|
foreach(DataRow drTable in t.Rows)
|
|
{
|
|
|
|
//this.pgCurrentOp.Text="Migrate "+ drTable["TABLE_NAME"].ToString()+ " [Formatted]";
|
|
nCurrentRow++;
|
|
nProgress = (int)((nCurrentRow / nTotalRows) * 100);
|
|
Report(nProgress, -1, "Table " + drTable["TABLE_NAME"].ToString(), "");
|
|
|
|
//check for current table
|
|
//requiring an identity column set
|
|
switch(drTable["TABLE_NAME"].ToString())
|
|
{
|
|
case "APARTINVENTORYADJUSTMENT":
|
|
|
|
bHasIdentity=true;
|
|
break;
|
|
|
|
case "APURCHASEORDER":
|
|
|
|
bHasIdentity=true;
|
|
break;
|
|
|
|
case "AWORKORDERPREVENTIVEMAINTENANCE":
|
|
|
|
bHasIdentity=true;
|
|
break;
|
|
|
|
case "AWORKORDERQUOTE":
|
|
|
|
bHasIdentity=true;
|
|
break;
|
|
|
|
case "AWORKORDERSERVICE":
|
|
|
|
bHasIdentity=true;
|
|
break;
|
|
|
|
default:
|
|
bHasIdentity=false;
|
|
|
|
break;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
FbDataReader dr=new FbCommand("SELECT * FROM " + drTable["TABLE_NAME"].ToString(),fbcn).ExecuteReader();
|
|
|
|
//Set allow identity insert on?
|
|
if(bHasIdentity)
|
|
{
|
|
cm.CommandText="SET IDENTITY_INSERT " +drTable["TABLE_NAME"].ToString()+" ON; " + GetInsertSQL(dr,drTable["TABLE_NAME"].ToString());
|
|
|
|
}
|
|
else
|
|
cm.CommandText=GetInsertSQL(dr,drTable["TABLE_NAME"].ToString());
|
|
SetParameters(ref cm,dr);
|
|
while(dr.Read())
|
|
{
|
|
InsertRow(ref cm,dr);
|
|
//pgCurrentOp.PerformStep();
|
|
}
|
|
|
|
dr.Close();
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
Report(100, -1, "Finished", "Copying table data");
|
|
|
|
}
|
|
|
|
private void InsertRow(ref SqlCommand cm,FbDataReader dr)
|
|
{
|
|
foreach(DataRow drTable in dr.GetSchemaTable().Rows)
|
|
{
|
|
if ((drTable["ProviderType"].ToString() == "3" || drTable["ProviderType"].ToString() == "4" /*case 649 changed provider type?*/)&& drTable["ColumnSize"].ToString() == "38")
|
|
{//it's a guid
|
|
object o=dr[drTable["ColumnName"].ToString()];
|
|
if (o == System.DBNull.Value)
|
|
cm.Parameters["@p" + drTable["ColumnName"].ToString()].Value = System.DBNull.Value;
|
|
else
|
|
{
|
|
//case 3157
|
|
//swapped this line for everything in this else block below to handle and properly report bad Guid's
|
|
//cm.Parameters["@p" + drTable["ColumnName"].ToString()].Value = new Guid(dr[drTable["ColumnName"].ToString()].ToString());
|
|
|
|
|
|
Guid newGuid;
|
|
String stringGuid = dr[drTable["ColumnName"].ToString()].ToString();
|
|
if (Guid.TryParse(stringGuid, out newGuid))
|
|
{ //success
|
|
cm.Parameters["@p" + drTable["ColumnName"].ToString()].Value = newGuid;
|
|
}
|
|
else
|
|
{
|
|
//FAIL, report all info possible:
|
|
System.Text.StringBuilder sb = new StringBuilder();
|
|
sb.AppendLine("Fatal error during import in stage \"Copying table data::InsertRow\"");
|
|
sb.AppendLine("Bad GUID value can't be interpreted");
|
|
sb.AppendLine("===================================");
|
|
sb.AppendLine("Bad value: '"+stringGuid + "'");
|
|
sb.AppendLine("In column: '" + drTable["ColumnName"].ToString() + "'");
|
|
sb.AppendLine("In table: '" + drTable["BaseTableName"].ToString() + "'");
|
|
sb.AppendLine("===================================");
|
|
sb.AppendLine("SQL import command would have been:");
|
|
sb.AppendLine(cm.CommandText);
|
|
sb.AppendLine("===================================");
|
|
throw new ApplicationException(sb.ToString());
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
}
|
|
else if (drTable["DataType"].ToString() == "System.DateTime")
|
|
{
|
|
//case 1831
|
|
object o=dr[drTable["ColumnName"].ToString()];
|
|
|
|
DateTime dt = DateTime.MinValue;
|
|
if (o != System.DBNull.Value)
|
|
{
|
|
dt = (DateTime)o;
|
|
if (dt.Year < 1754 || dt.Year > 9999)
|
|
dt = new DateTime(1966, 1, 1);
|
|
cm.Parameters["@p" + drTable["ColumnName"].ToString()].Value = dt;
|
|
}
|
|
else
|
|
cm.Parameters["@p" + drTable["ColumnName"].ToString()].Value = o;
|
|
|
|
|
|
}
|
|
else
|
|
cm.Parameters["@p"+drTable["ColumnName"].ToString()].Value=dr[drTable["ColumnName"].ToString()];
|
|
|
|
}
|
|
try
|
|
{
|
|
cm.ExecuteNonQuery();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
System.Text.StringBuilder sb = new StringBuilder();
|
|
sb.AppendLine("Fatal error during import in stage \"Copying table data\"");
|
|
sb.AppendLine("Insert command that failed was: ");
|
|
sb.AppendLine("===================================");
|
|
sb.AppendLine(cm.CommandText);
|
|
sb.AppendLine("===================================");
|
|
sb.AppendLine("PARAMETERS ARE:");
|
|
foreach (SqlParameter p in cm.Parameters)
|
|
sb.AppendLine(p.ParameterName + " - " + p.Value.ToString());
|
|
sb.AppendLine("===================================");
|
|
throw new ApplicationException(sb.ToString(), ex);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
//Create the paramaters collection
|
|
private void SetParameters(ref SqlCommand cm,FbDataReader dr)
|
|
{
|
|
cm.Parameters.Clear();
|
|
foreach(DataRow drTable in dr.GetSchemaTable().Rows)
|
|
{
|
|
string sName="@p"+drTable["ColumnName"];
|
|
switch(drTable["DataType"].ToString())
|
|
{
|
|
case "System.Decimal":
|
|
cm.Parameters.Add(sName,SqlDbType.Decimal);
|
|
break;
|
|
case "System.String":
|
|
if (drTable["ProviderType"].ToString() == "15" || drTable["ProviderType"].ToString() == "16")
|
|
{
|
|
//ordinary string
|
|
cm.Parameters.Add(sName,SqlDbType.NVarChar);
|
|
}
|
|
else if (drTable["ProviderType"].ToString() == "12" || drTable["ProviderType"].ToString() == "13")
|
|
{
|
|
//Ntext
|
|
cm.Parameters.Add(sName,SqlDbType.NText);
|
|
}
|
|
else if (drTable["ProviderType"].ToString() == "3" || drTable["ProviderType"].ToString() == "4")//case 649
|
|
{
|
|
if(drTable["ColumnSize"].ToString()=="38")//guid are always 38
|
|
cm.Parameters.Add(sName,SqlDbType.UniqueIdentifier);//Guid
|
|
else//it's a standard char field (i.e. login and password hashes in user table
|
|
cm.Parameters.Add(sName,SqlDbType.Char);
|
|
}
|
|
break;
|
|
case "System.DateTime":
|
|
cm.Parameters.Add(sName,SqlDbType.DateTime);
|
|
break;
|
|
case "System.Int16":
|
|
cm.Parameters.Add(sName,SqlDbType.SmallInt);
|
|
break;
|
|
case "System.Int32":
|
|
cm.Parameters.Add(sName,SqlDbType.Int);
|
|
break;
|
|
case "System.Int64":
|
|
cm.Parameters.Add(sName,SqlDbType.BigInt);
|
|
break;
|
|
case "System.Byte[]":
|
|
cm.Parameters.Add(sName,SqlDbType.Image);
|
|
break;
|
|
|
|
default:
|
|
throw new ApplicationException("SetParameters UKNOWN TYPE: " + sName + " - " + drTable["DataType"].ToString());
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
//Inserts a row into the target table
|
|
private string GetInsertSQL(FbDataReader dr, string sTableName)
|
|
{
|
|
StringBuilder q=new StringBuilder();
|
|
q.Append("INSERT INTO ");
|
|
q.Append(sTableName);
|
|
q.Append(" (");
|
|
//Field names
|
|
foreach(DataRow drTable in dr.GetSchemaTable().Rows)
|
|
{
|
|
q.Append(drTable["ColumnName"].ToString());
|
|
q.Append(",");
|
|
|
|
}
|
|
q.Length=q.Length-1;//ditch the comma
|
|
q.Append(") VALUES (");
|
|
foreach(DataRow drTable in dr.GetSchemaTable().Rows)
|
|
{
|
|
q.Append("@p");
|
|
q.Append(drTable["ColumnName"].ToString());
|
|
q.Append(",");
|
|
|
|
}
|
|
q.Length=q.Length-1;//ditch the comma
|
|
q.Append(")");
|
|
|
|
return q.ToString();
|
|
|
|
}
|
|
|
|
#endregion copy data
|
|
|
|
#region primary keys
|
|
private void MigratePK()
|
|
{
|
|
SqlCommand cm = new SqlCommand();
|
|
cm.Connection=mscn;
|
|
StringBuilder q=new StringBuilder();
|
|
|
|
DataTable t=fbcn.GetSchema("PrimaryKeys");
|
|
bool bDoneLocalizedText=false;
|
|
//this.pgCurrentOp.Value=0;
|
|
//pgCurrentOp.Maximum=t.Rows.Count;
|
|
double nTotalRows = t.Rows.Count;
|
|
double nCurrentRow = 0;
|
|
int nProgress = 0;
|
|
|
|
|
|
foreach(DataRow drTable in t.Rows)
|
|
{
|
|
//this.pgCurrentOp.Text="Create primary key "+ drTable["TABLE_NAME"].ToString() + "." + drTable["COLUMN_NAME"].ToString()+ " [Formatted]";
|
|
|
|
nCurrentRow++;
|
|
nProgress = (int)((nCurrentRow / nTotalRows) * 100);
|
|
Report(nProgress, -1, "Key " + drTable["TABLE_NAME"].ToString() + "." + drTable["COLUMN_NAME"].ToString(), "");
|
|
|
|
q.Length=0;
|
|
|
|
q.Append("ALTER TABLE ");
|
|
q.Append(drTable["TABLE_NAME"].ToString());
|
|
q.Append(" ADD PRIMARY KEY NONCLUSTERED (");
|
|
if( drTable["TABLE_NAME"].ToString()=="ALOCALIZEDTEXT")
|
|
{
|
|
if(bDoneLocalizedText) continue;
|
|
q.Append("AKEY, ALOCALE");
|
|
bDoneLocalizedText=true;
|
|
}
|
|
else
|
|
q.Append(drTable["COLUMN_NAME"].ToString());
|
|
|
|
|
|
q.Append(" )");
|
|
cm.CommandText=q.ToString();
|
|
cm.ExecuteNonQuery();
|
|
//pgCurrentOp.PerformStep();
|
|
}
|
|
|
|
Report(100, -1, "Finished", "");
|
|
}
|
|
|
|
#endregion primary keys
|
|
|
|
#region Regular indexes
|
|
private void MigrateIndexes()
|
|
{
|
|
SqlCommand cm = new SqlCommand();
|
|
cm.Connection=mscn;
|
|
StringBuilder q=new StringBuilder();
|
|
|
|
//StringBuilder q2 = new StringBuilder();//Testing case 378
|
|
|
|
DataTable t = fbcn.GetSchema("IndexColumns");//changed case 649 new provider
|
|
|
|
//this.pgCurrentOp.Value=0;
|
|
//pgCurrentOp.Maximum=t.Rows.Count;
|
|
|
|
double nTotalRows = t.Rows.Count;
|
|
double nCurrentRow = 0;
|
|
int nProgress = 0;
|
|
|
|
|
|
foreach(DataRow drTable in t.Rows)
|
|
{
|
|
|
|
q.Length=0;
|
|
//pgCurrentOp.PerformStep();
|
|
q.Append("CREATE INDEX ");
|
|
q.Append(drTable["INDEX_NAME"].ToString());
|
|
q.Append(" ON ");
|
|
|
|
//Weed out undesireables such as compound indexes
|
|
//because they are processed through here as two separate calls for the
|
|
//same index throwing a sqlexecption and must be added later down
|
|
if (drTable["INDEX_NAME"].ToString().StartsWith("IDX6_") ||//case 1303 v6 indexes which are now created separately below
|
|
drTable["INDEX_NAME"].ToString().StartsWith("RDB$") ||//system index
|
|
drTable["INDEX_NAME"].ToString().StartsWith("PK") ||
|
|
drTable["INDEX_NAME"].ToString().StartsWith("FK") ||
|
|
drTable["TABLE_NAME"].ToString()=="ALOCALIZEDTEXT" ||
|
|
drTable["TABLE_NAME"].ToString()=="ANOTIFYSUBSCRIPTION" ||
|
|
drTable["INDEX_NAME"].ToString()=="USERCREDS" ||
|
|
drTable["INDEX_NAME"].ToString()=="IDX_AINTEGRATIONMAP2"
|
|
)//
|
|
continue;
|
|
|
|
q.Append(drTable["TABLE_NAME"].ToString());
|
|
q.Append(" ( ");
|
|
q.Append(drTable["COLUMN_NAME"].ToString());
|
|
q.Append(" ) ");
|
|
|
|
|
|
//this.pgCurrentOp.Text="Create Index "+ drTable["TABLE_NAME"].ToString() + "." + drTable["INDEX_NAME"].ToString()+ " [Formatted]";
|
|
|
|
nCurrentRow++;
|
|
nProgress = (int)((nCurrentRow / nTotalRows) * 100);
|
|
Report(nProgress, -1, "Index " + drTable["TABLE_NAME"].ToString() + "." + drTable["INDEX_NAME"].ToString(), "");
|
|
|
|
|
|
cm.CommandText=q.ToString();
|
|
cm.ExecuteNonQuery();
|
|
|
|
//q2.Append("DDL(\"IF NOT EXISTS (SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[dbo].[" + drTable["TABLE_NAME"].ToString() + "]') AND name = N'" + drTable["INDEX_NAME"].ToString() + "') \" +\r\n" +
|
|
// "\""+q+"\");\r\n"); //testing for case 378
|
|
}
|
|
|
|
Report(0, -1, "Starting", "Migrating compound indexes");
|
|
//Add the compound indexes that couldn't be added before
|
|
cm.CommandText="CREATE UNIQUE INDEX IX_ANOTIFYSUBSCRIPTIONMUSTBEUNI ON ANOTIFYSUBSCRIPTION (AUSERID, AROOTOBJECTTYPE, AEVENTTYPE, AGUIDVALUE)";
|
|
cm.ExecuteNonQuery();
|
|
|
|
cm.CommandText="CREATE UNIQUE INDEX USERCREDS ON AUSER (ALOGIN, APASSWORD)";
|
|
cm.ExecuteNonQuery();
|
|
|
|
try
|
|
{
|
|
//bug bug
|
|
//case 329 got missed here reared it's ugly head 10 years later
|
|
//cm.CommandText="CREATE UNIQUE INDEX IDX_AINTEGRATIONMAP2 ON AINTEGRATIONMAP(AROOTOBJECTID,AROOTOBJECTTYPE)";
|
|
cm.CommandText = "CREATE UNIQUE INDEX IDX_AINTEGRATIONMAP2 ON AINTEGRATIONMAP(AROOTOBJECTID,AROOTOBJECTTYPE,AINTEGRATIONID)";
|
|
cm.ExecuteNonQuery();
|
|
}
|
|
catch
|
|
{}
|
|
|
|
//case 1303 v6 indexes
|
|
//in a try block in case they already exist somehow which should be impossible but who friggin knows
|
|
//what users will do
|
|
//ONLY run this on a schema that is 92 or higher. Anything older will get these in the AyaNova schema update
|
|
//this means we need to determine the schema early on here
|
|
if (mDBSchemaVersion > 91)
|
|
{
|
|
try
|
|
{
|
|
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
DDL(cm, "CREATE CLUSTERED INDEX IDX6_ASERVICEBANK_CREAT ON dbo.ASERVICEBANK (ACREATED) ");
|
|
DDL(cm, "CREATE NONCLUSTERED INDEX IDX6_AVENDOR_CVR ON dbo.AVENDOR (AID)INCLUDE (ANAME) ");
|
|
DDL(cm, "CREATE NONCLUSTERED INDEX IDX6_AUSRREGION ON dbo.AUSER (AID) INCLUDE ( AREGIONID) ");
|
|
DDL(cm, "CREATE NONCLUSTERED INDEX IDX6_APROJECTIDNAME ON dbo.APROJECT (AID) INCLUDE (ANAME) ");
|
|
DDL(cm, "CREATE NONCLUSTERED INDEX IDX6_ACLIENT_CLIENTSELECTOR ON dbo.ACLIENT (ANAME) INCLUDE ( AID, AACTIVE, AREGIONID) ");
|
|
DDL(cm, "CREATE NONCLUSTERED INDEX IDX6_ACLIENTDISPZN ON dbo.ACLIENT (AID,ADISPATCHZONEID) INCLUDE (ANAME) ");
|
|
DDL(cm, "CREATE CLUSTERED INDEX IDX6_AWO ON dbo.AWORKORDER (ACREATED) ");
|
|
DDL(cm, "CREATE NONCLUSTERED INDEX IDX6_AWORKORDER_CVR ON dbo.AWORKORDER " +
|
|
"( " +
|
|
" AWORKORDERTYPE, " +
|
|
" AID, " +
|
|
" APROJECTID, " +
|
|
" AFROMPMID, " +
|
|
" AFROMQUOTEID, " +
|
|
" AWORKORDERCATEGORYID, " +
|
|
" ACLIENTID " +
|
|
") " +
|
|
"INCLUDE ( ACREATED, " +
|
|
"AMODIFIED, " +
|
|
"AINTERNALREFERENCENUMBER, " +
|
|
"ACUSTOMERREFERENCENUMBER, " +
|
|
"AONSITE, " +
|
|
"ACUSTOMERCONTACTNAME, " +
|
|
"ASUMMARY, " +
|
|
"ACLOSED, " +
|
|
"ASERVICECOMPLETED) ");
|
|
DDL(cm, "CREATE NONCLUSTERED INDEX IDX6_AUNITMODEL_CVR2 ON dbo.AUNITMODEL (AUNITMODELCATEGORYID, AID, AVENDORID) INCLUDE ( ANAME) ");
|
|
DDL(cm, "CREATE NONCLUSTERED INDEX IDX6_AUNITMODELIDVEND ON dbo.AUNITMODEL (AID,AVENDORID) INCLUDE (ANAME,AMODELNUMBER) ");
|
|
DDL(cm, "CREATE NONCLUSTERED INDEX IDX6_AUNIT_CVR ON dbo.AUNIT (AID,AUNITMODELID) INCLUDE (ASERIAL,APURCHASEDDATE,ATEXT1,ATEXT2,ATEXT3,ATEXT4) ");
|
|
DDL(cm, "CREATE CLUSTERED INDEX IDX6_AWOITEM ON dbo.AWORKORDERITEM (ACREATED) ");
|
|
DDL(cm, "CREATE CLUSTERED INDEX IDX6_ALOCALIZEDTEXT_CL ON dbo.ALOCALIZEDTEXT (ALOCALE,AKEY) ");
|
|
DDL(cm, "CREATE NONCLUSTERED INDEX IDX6_ACLIENTNOTIFYEVENT_CREAT ON dbo.ACLIENTNOTIFYEVENT (ACREATED) ");
|
|
DDL(cm, "CREATE NONCLUSTERED INDEX IDX6_AADDRESS_CVR ON dbo.AADDRESS (AROOTOBJECTID,AADDRESSTYPE) " +
|
|
"INCLUDE ( ADELIVERYADDRESS,ACITY,ASTATEPROV,ACOUNTRYCODE,ACOUNTRY,APOSTAL,ALONGITUDE,ALATITUDE) ");
|
|
DDL(cm, "CREATE NONCLUSTERED INDEX IDX6_AGRIDFILTER_NAME ON dbo.AGRIDFILTER (ANAME) ");
|
|
DDL(cm, "CREATE NONCLUSTERED INDEX IDX6_ASEARCHKEY ON dbo.ASEARCHKEY (AWORDID,ASOURCEOBJECTTYPE,ASOURCEOBJECTID) ");
|
|
DDL(cm, "CREATE CLUSTERED INDEX IDX6_ASEARCHDICTIONARY ON dbo.ASEARCHDICTIONARY (AWORD) ");
|
|
DDL(cm, "CREATE NONCLUSTERED INDEX IDX6_ASEARCHDICTIONARY_NONCLUST ON dbo.ASEARCHDICTIONARY (AWORD) ");
|
|
DDL(cm, "CREATE CLUSTERED INDEX IDX6_ASCHEDULEMARKER_CVR ON dbo.ASCHEDULEMARKER (ASTARTDATE,ASTOPDATE) ");
|
|
DDL(cm, "CREATE CLUSTERED INDEX IDX6_AWOIMISCEXP ON dbo.AWORKORDERITEMMISCEXPENSE (ACREATED) ");
|
|
DDL(cm, "CREATE CLUSTERED INDEX IDX6_AWOILOA ON dbo.AWORKORDERITEMLOAN (ACREATED) ");
|
|
DDL(cm, "CREATE CLUSTERED INDEX IDX6_AWOSVC ON dbo.AWORKORDERSERVICE (ACREATED) ");
|
|
DDL(cm, "CREATE NONCLUSTERED INDEX IDX6_AWORKORDERSERVICE_CVR ON dbo.AWORKORDERSERVICE (AWORKORDERID) " +
|
|
"INCLUDE ( AWORKORDERSTATUSID,ASERVICEDATE,AINVOICENUMBER,ASERVICENUMBER,ACLOSEBYDATE) ");
|
|
DDL(cm, "CREATE CLUSTERED INDEX IDX6_AWOIOUT ON dbo.AWORKORDERITEMOUTSIDESERVICE (ACREATED) ");
|
|
DDL(cm, "CREATE NONCLUSTERED INDEX IDX6_AWOIOUTSIDESERVICECVR ON dbo.AWORKORDERITEMOUTSIDESERVICE (AWORKORDERITEMID,AVENDORSENTTOID,AVENDORSENTVIAID) " +
|
|
"INCLUDE ( ARMANUMBER,ATRACKINGNUMBER,AREPAIRCOST,AREPAIRPRICE,ASHIPPINGCOST,ASHIPPINGPRICE,ADATESENT,ASENDERUSERID,ADATEETA,ADATERETURNED) ");
|
|
DDL(cm, "CREATE NONCLUSTERED INDEX IDX6_ANOTIFYEVENT_APPLIESTO ON dbo.ANOTIFYEVENT (AAPPLIESTOUSERID) ");
|
|
DDL(cm, "CREATE NONCLUSTERED INDEX IDX6_APART_4INVENT ON dbo.APART " +
|
|
"(AID,APARTASSEMBLYID,APARTCATEGORYID,AALTERNATIVEWHOLESALERID,AWHOLESALERID,AMANUFACTURERID,APARTNUMBER,AACTIVE,ARETAIL,ACOST) " +
|
|
"INCLUDE (ANAME,AUPC) ");
|
|
DDL(cm, "CREATE NONCLUSTERED INDEX IDX6_APART_CVR ON dbo.APART (AID,APARTASSEMBLYID,APARTCATEGORYID,AMANUFACTURERID) " +
|
|
"INCLUDE (ANAME,APARTNUMBER,AUPC) ");
|
|
DDL(cm, "CREATE CLUSTERED INDEX IDX6_AWOIPRTRQST ON dbo.AWORKORDERITEMPARTREQUEST (ACREATED) ");
|
|
DDL(cm, "CREATE CLUSTERED INDEX IDX6_AWOIPRT ON dbo.AWORKORDERITEMPART (ACREATED) ");
|
|
DDL(cm, "CREATE NONCLUSTERED INDEX IDX6_AWORKORDERITEMPARTCVR ON dbo.AWORKORDERITEMPART (AWORKORDERITEMID,APARTSERIALID,APARTWAREHOUSEID,APARTID) " +
|
|
"INCLUDE (AID,AQUANTITY,ACOST,APRICE,ADISCOUNT,ADESCRIPTION,AUSED,ATAXPARTSALEID,AQUANTITYRESERVED) ");
|
|
DDL(cm, "CREATE CLUSTERED INDEX IDX6_AWOITRVL ON dbo.AWORKORDERITEMTRAVEL (ACREATED) ");
|
|
DDL(cm, "CREATE NONCLUSTERED INDEX IDX6_AWORKORDERITEMTRAVEL_CVR ON dbo.AWORKORDERITEMTRAVEL (AWORKORDERITEMID) " +
|
|
"INCLUDE (AID,AUSERID,ATRAVELSTARTDATE,ATRAVELSTOPDATE,ATRAVELRATEID,ATRAVELDETAILS,ATRAVELRATEQUANTITY,ANOCHARGEQUANTITY,ADISTANCE,ATAXRATESALEID) ");
|
|
DDL(cm, "CREATE CLUSTERED INDEX IDX6_AWOISCHEDUSR ON dbo.AWORKORDERITEMSCHEDULEDUSER (ACREATED) ");
|
|
DDL(cm, "CREATE NONCLUSTERED INDEX IDX6_AWORKORDERITEMSCHEDULEDUSER_CVR ON dbo.AWORKORDERITEMSCHEDULEDUSER (AWORKORDERITEMID) " +
|
|
"INCLUDE ( AID,AUSERID,AESTIMATEDQUANTITY,ASTARTDATE,ASTOPDATE,ASERVICERATEID) ");
|
|
DDL(cm, "CREATE NONCLUSTERED INDEX IDX6_AWOISCHEDULEDUSER_CVR2 ON dbo.AWORKORDERITEMSCHEDULEDUSER (ASTOPDATE,ASTARTDATE,AWORKORDERITEMID) " +
|
|
"INCLUDE ( AID,AUSERID) ");
|
|
DDL(cm, "CREATE CLUSTERED INDEX IDX6_AWOILAB ON dbo.AWORKORDERITEMLABOR (ACREATED) ");
|
|
DDL(cm, "CREATE NONCLUSTERED INDEX IDX6_APARTBYWAREHOUSEINVENTORY_APARTID ON dbo.APARTBYWAREHOUSEINVENTORY (APARTID) ");
|
|
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
|
|
}
|
|
catch
|
|
{ }
|
|
|
|
}
|
|
Report(100, -1, "Finished", "");
|
|
|
|
}
|
|
|
|
/// <summary>
|
|
/// execute DDL statement
|
|
/// </summary>
|
|
/// <param name="sDDL"></param>
|
|
public void DDL(SqlCommand cm, string sDDL)
|
|
{
|
|
cm.CommandText = sDDL;
|
|
cm.ExecuteNonQuery();
|
|
|
|
}
|
|
#endregion regular indexes
|
|
|
|
#region Foreign keys
|
|
private void MigrateFK()
|
|
{
|
|
SqlCommand cm = new SqlCommand();
|
|
cm.Connection=mscn;
|
|
StringBuilder q=new StringBuilder();
|
|
|
|
//case 1401
|
|
DataTable t = GetForeignKeyColumns(fbcn);
|
|
|
|
// DataTable t = fbcn.GetSchema("ForeignKeyColumns");//Case 649
|
|
|
|
double nTotalRows = t.Rows.Count;
|
|
double nCurrentRow = 0;
|
|
int nProgress = 0;
|
|
|
|
foreach(DataRow drTable in t.Rows)
|
|
{
|
|
//Case 649 this block all column names in drTable new
|
|
q.Length=0;
|
|
|
|
nCurrentRow++;
|
|
nProgress = (int)((nCurrentRow / nTotalRows) * 100);
|
|
Report(nProgress, -1, "Foreign key " + drTable["COLUMN_NAME"].ToString() + "-" +
|
|
drTable["REFERENCED_COLUMN_NAME"].ToString(), "");
|
|
|
|
|
|
q.Append("ALTER TABLE ");
|
|
q.Append(drTable["TABLE_NAME"].ToString());
|
|
q.Append(" ADD CONSTRAINT ");
|
|
q.Append(drTable["CONSTRAINT_NAME"].ToString());
|
|
q.Append(" FOREIGN KEY (");
|
|
q.Append(drTable["COLUMN_NAME"].ToString());
|
|
q.Append(") REFERENCES ");
|
|
q.Append(drTable["REFERENCED_TABLE_NAME"].ToString());
|
|
q.Append(" (");
|
|
q.Append(drTable["REFERENCED_COLUMN_NAME"].ToString());
|
|
q.Append(")");
|
|
cm.CommandText=q.ToString();
|
|
cm.ExecuteNonQuery();
|
|
|
|
}
|
|
Report(100, -1, "Finished", "");
|
|
}
|
|
|
|
|
|
public DataTable GetForeignKeyColumns(FbConnection connection)
|
|
{
|
|
System.Text.StringBuilder sb = new StringBuilder();
|
|
DataTable dt = new DataTable();
|
|
dt.Columns.Add("TABLE_NAME", typeof(System.String));
|
|
dt.Columns.Add("CONSTRAINT_NAME", typeof(System.String));
|
|
dt.Columns.Add("COLUMN_NAME", typeof(System.String));
|
|
dt.Columns.Add("REFERENCED_TABLE_NAME", typeof(System.String));
|
|
dt.Columns.Add("REFERENCED_COLUMN_NAME", typeof(System.String));
|
|
|
|
foreach (DataRow row in connection.GetSchema("ForeignKeys").Rows)
|
|
{
|
|
var constraintName = (string)row["CONSTRAINT_NAME"];
|
|
var tableName = (string)row["TABLE_NAME"];
|
|
var referencedTableName = (string)row["REFERENCED_TABLE_NAME"];
|
|
|
|
// use this instead of connection.GetSchema("ForeignKeyColumns") until the bug has been corrected
|
|
string commandText = @"
|
|
SELECT null AS CONSTRAINT_CATALOG,null AS CONSTRAINT_SCHEMA,co.rdb$constraint_name AS CONSTRAINT_NAME,
|
|
null AS TABLE_CATALOG,null AS TABLE_SCHEMA,co.rdb$relation_name AS TABLE_NAME,
|
|
coidxseg.rdb$field_name AS COLUMN_NAME,
|
|
null as REFERENCED_TABLE_CATALOG,null as REFERENCED_TABLE_SCHEMA,refco.rdb$relation_name AS REFERENCED_TABLE_NAME,
|
|
refidxseg.rdb$field_name AS REFERENCED_COLUMN_NAME,
|
|
coidxseg.rdb$field_position AS ORDINAL_POSITION
|
|
FROM rdb$ref_constraints ref
|
|
INNER JOIN rdb$relation_constraints co ON ref.rdb$constraint_name=co.rdb$constraint_name
|
|
INNER JOIN rdb$index_segments coidxseg ON co.rdb$index_name=coidxseg.rdb$index_name
|
|
INNER JOIN rdb$relation_constraints refco ON ref.rdb$const_name_uq=refco.rdb$constraint_name
|
|
INNER JOIN rdb$index_segments refidxseg ON refco.rdb$index_name=refidxseg.rdb$index_name AND coidxseg.rdb$field_position=refidxseg.rdb$field_position
|
|
WHERE co.rdb$relation_name=@p0 AND co.rdb$constraint_name=@p1
|
|
ORDER BY ref.rdb$constraint_name,coidxseg.rdb$field_position"
|
|
;
|
|
// AND coidxseg.rdb$field_name = @p3",
|
|
using (var cmd = connection.CreateCommand())
|
|
{
|
|
cmd.CommandText = commandText;
|
|
cmd.Parameters.Add(
|
|
"@p0", FbDbType.Char, 31).Value = tableName;
|
|
cmd.Parameters.Add(
|
|
"@p1", FbDbType.Char, 31).Value = constraintName;
|
|
//cmd.Parameters.Add("@p3", FbDbType.Char, 31).Value = fieldName;
|
|
using (var reader = cmd.ExecuteReader())
|
|
while (reader.Read())
|
|
{
|
|
DataRow dr = dt.NewRow();
|
|
dr["CONSTRAINT_NAME"] = reader.GetString(2);
|
|
dr["TABLE_NAME"] = reader.GetString(5);
|
|
dr["COLUMN_NAME"] = reader.GetString(6);
|
|
dr["REFERENCED_TABLE_NAME"] = reader.GetString(9);
|
|
dr["REFERENCED_COLUMN_NAME"] = reader.GetString(10);
|
|
dt.Rows.Add(dr);
|
|
|
|
|
|
// Debug.Assert(constraintName == reader.GetString(2 /*"CONSTRAINT_NAME"*/).TrimEnd());
|
|
//Debug.Assert(tableName == reader.GetString(5 /*"TABLE_NAME"*/).TrimEnd());
|
|
//6=COLUMN_NAME
|
|
//Debug.Assert(referencedTableName == reader.GetString(9/*"REFERENCED_TABLE_NAME"*/).TrimEnd());
|
|
//10=REFERENCED_COLUMN_NAME
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return dt;
|
|
}
|
|
|
|
#endregion foreign keys
|
|
|
|
#region Test connections
|
|
|
|
private bool TestSQLConnection(string sConnection)
|
|
{
|
|
if(this.edMSConnect.Text=="")
|
|
{
|
|
MessageBox.Show("A Microsoft SQL database connection string is required.\r\n");
|
|
|
|
return false;
|
|
}
|
|
|
|
if(this.edMSConnect.Text.IndexOf("master")==-1)
|
|
{
|
|
MessageBox.Show("The SQL server connection string doesn't appear to have the\r\n" +
|
|
"required initial catalog set to the \"master\" database.");
|
|
|
|
return false;
|
|
}
|
|
try
|
|
{
|
|
System.Data.SqlClient.SqlConnection cn=new SqlConnection(sConnection);
|
|
cn.Open();
|
|
cn.Close();
|
|
}
|
|
catch(Exception ex)
|
|
{
|
|
MessageBox.Show("SQL Connection failed\r\nCheck your connection string\r\nFull error was:\r\n" + ex.Message);
|
|
return false;
|
|
}
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
private int mDBSchemaVersion=9999;
|
|
private bool TestFBConnection(string sConnection)
|
|
{
|
|
|
|
if(this.edFBConnect.Text=="")
|
|
{
|
|
MessageBox.Show("A Firebird connection string is required.\r\n" +
|
|
"(See AyaNova.Exe.Config file)");
|
|
return false;
|
|
}
|
|
|
|
try
|
|
{
|
|
FbConnection cn=new FbConnection(FixupFBConnectionString(sConnection));
|
|
cn.Open();
|
|
|
|
FbDataReader dr = new FbCommand("SELECT ADBSCHEMA FROM AGLOBALEX", cn).ExecuteReader();
|
|
if (dr.Read())
|
|
{
|
|
mDBSchemaVersion = (int)dr[0];
|
|
dr.Close();
|
|
|
|
}
|
|
cn.Close();
|
|
}
|
|
catch(Exception ex)
|
|
{
|
|
MessageBox.Show("Firebird Connection failed\r\nCheck your connection string\r\nFull error was:\r\n" + ex.Message);
|
|
return false;
|
|
}
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
private void btnTest_Click(object sender, System.EventArgs e)
|
|
{
|
|
MessageBox.Show("ToMSSQL will now attempt to open the databases\r\n" +
|
|
"based on the connection strings you provided\r\n" +
|
|
"If they are correct this should take less than a few seconds\r\n" +
|
|
"If it takes longer the connection string is likely incorrect\r\n" +
|
|
"wait for the error message to display which will indicate the problem");
|
|
Cursor.Current=Cursors.WaitCursor;
|
|
if(TestSQLConnection(this.edMSConnect.Text) &&
|
|
TestFBConnection(FixupFBConnectionString(this.edFBConnect.Text)))
|
|
{
|
|
MessageBox.Show("Connections are good, you can now migrate data");
|
|
edFBConnect.ReadOnly=true;
|
|
edMSConnect.ReadOnly=true;
|
|
this.btnImport.Visible=true;
|
|
this.btnTest.Visible=false;
|
|
}
|
|
|
|
}
|
|
|
|
#endregion test connections
|
|
|
|
private void edFBConnect_ValueChanged(object sender, System.EventArgs e)
|
|
{
|
|
this.btnImport.Visible=false;
|
|
this.btnTest.Visible=true;
|
|
}
|
|
|
|
private void edMSConnect_ValueChanged(object sender, System.EventArgs e)
|
|
{
|
|
this.btnImport.Visible=false;
|
|
this.btnTest.Visible=true;
|
|
}
|
|
|
|
|
|
|
|
private void bw_DoWork(object sender, DoWorkEventArgs e)
|
|
{
|
|
|
|
try
|
|
{
|
|
Report(0,0,"Connecting","Overall");
|
|
|
|
//bw.ReportProgress(0,
|
|
//this.pgOverall.Text = "Overall [Formatted]";
|
|
//this.pgOverall.Value = 0;
|
|
|
|
fbcn = new FbConnection(FixupFBConnectionString(this.edFBConnect.Text));
|
|
fbcn.Open();
|
|
//this.pgOverall.Value=1;
|
|
|
|
CreateSQLDatabase(this.edMSConnect.Text, true);
|
|
// this.pgOverall.Value = 2;
|
|
Report(0, 1, "Switching to AyaNova on MSSQL", "");
|
|
mscn = new SqlConnection(this.edMSConnect.Text.Replace("master", "AyaNova"));
|
|
mscn.Open();
|
|
//this.pgOverall.Value = 3;
|
|
Report(100, 2, "Switched to AyaNova on MSSQL", "");
|
|
|
|
Report(0, 3, "Starting", "Migrating table structure");
|
|
MigrateTables();
|
|
//this.pgOverall.Value = 4;
|
|
|
|
Report(0, 10, "Starting", "Copying table data");
|
|
CopyData();
|
|
|
|
//this.pgOverall.Value = 5;
|
|
Report(0, 65, "Starting", "Migrating primary keys");
|
|
MigratePK();
|
|
|
|
//this.pgOverall.Value = 6;
|
|
Report(0, 85, "Starting", "Migrating indexes");
|
|
MigrateIndexes();
|
|
|
|
//this.pgOverall.Value = 7;
|
|
Report(0, 95, "Starting", "Migrating foreign keys");
|
|
MigrateFK();
|
|
|
|
Report(100, 100, "Finished", "Finished");
|
|
|
|
//this.pgOverall.Text = "Finished [Formatted]";
|
|
//this.pgOverall.Value = 8;// done!
|
|
|
|
//this.pgCurrentOp.Value = pgCurrentOp.Maximum;
|
|
//this.pgCurrentOp.Text = "Finished [Formatted]";
|
|
|
|
|
|
}
|
|
catch(Exception ex)
|
|
{
|
|
throw ex;
|
|
}
|
|
finally
|
|
{
|
|
if (fbcn != null)
|
|
fbcn.Close();
|
|
if (mscn != null)
|
|
mscn.Close();
|
|
}
|
|
}
|
|
|
|
#region progress reporting
|
|
public struct ProgressStruct
|
|
{
|
|
public string sCurrent;
|
|
public int nCurrent;
|
|
public string sOverall;
|
|
public int nOverall;
|
|
|
|
|
|
}
|
|
private void Report(int current, int overall, string scurrent, string soverall)
|
|
{
|
|
ProgressStruct ps;
|
|
ps.nCurrent = current;
|
|
ps.nOverall = overall;
|
|
ps.sCurrent = scurrent;
|
|
ps.sOverall = soverall;
|
|
bw.ReportProgress(1, ps);
|
|
}
|
|
private void bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
|
|
{
|
|
ProgressStruct ps = (ProgressStruct)e.UserState;
|
|
if(ps.sOverall!="")
|
|
this.pgOverall.Text = ps.sOverall + " [Formatted]";
|
|
if(ps.nOverall!=-1)
|
|
this.pgOverall.Value = ps.nOverall;
|
|
|
|
this.pgCurrentOp.Text = ps.sCurrent + " [Formatted]";
|
|
this.pgCurrentOp.Value = ps.nCurrent;
|
|
|
|
}
|
|
#endregion progress reporting
|
|
|
|
|
|
|
|
private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
|
|
{
|
|
if (e.Error != null)
|
|
{
|
|
System.Text.StringBuilder sb = new StringBuilder();
|
|
sb.AppendLine(e.Error.Message);
|
|
sb.AppendLine(e.Error.StackTrace);
|
|
if (e.Error.InnerException != null)
|
|
{
|
|
sb.AppendLine("Inner exception:");
|
|
sb.AppendLine(e.Error.InnerException.Message);
|
|
sb.AppendLine(e.Error.InnerException.StackTrace);
|
|
}
|
|
|
|
|
|
CopyableMessageBox d = new CopyableMessageBox(sb.ToString());
|
|
d.ShowDialog();
|
|
|
|
}
|
|
}
|
|
|
|
|
|
//case 1400
|
|
private static string FixupFBConnectionString(string sConnect)
|
|
{
|
|
Regex regex = new Regex("User\\s*=", RegexOptions.IgnoreCase | RegexOptions.Multiline | RegexOptions.Compiled);
|
|
if (!regex.IsMatch(sConnect))
|
|
sConnect = sConnect + "User=SYSDBA;";
|
|
return sConnect;
|
|
}
|
|
|
|
}
|
|
}
|