Skip to content

Commit

Permalink
more features
Browse files Browse the repository at this point in the history
  • Loading branch information
anatoliy-savchak committed Jun 10, 2024
1 parent 472d2d1 commit a955e5e
Show file tree
Hide file tree
Showing 8 changed files with 360 additions and 17 deletions.
8 changes: 6 additions & 2 deletions SQL Format/FormSQLFormat.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,17 @@ public FormSQLFormat()
AddItemByClass(new SQLTranslatorUpdate());
AddItemByClass(new SQLTranslatorMerge());
AddItemByClass(new SQLTranslatorCopy());
AddItemByClass(new SQLTranslatorCopySingle());
AddItemByClass(new SQLTranslatorInsert());
AddItemByClass(new SQLTranslatorSame());
AddItemByClass(new SQLTranslatorXmlSelect());
AddItemByClass(new TabTranslatorJson());
//AddItemByClass(new TabTranslatorJson());
#if DEBUG
AddItemByClass(new SQLTranslatorMyScript());
#endif
}

void AddItemByClass(SQLTranslator t)
void AddItemByClass(SQLTranslator t)
{
int idx = TabCtrl.TabPages.Count;
TabCtrl.TabPages.Add(t.GetCaption());
Expand Down
2 changes: 1 addition & 1 deletion SQL Format/Helpers/SqlBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ public SqlBuilder AppendIf(string lineCondition)
public SqlBuilder AppendCatchTypicalRollback()
{
AppendBegin(BEGIN_CATCH);
AppendLine($"if @@trancount > 0 rollback;");
AppendLine($"if @@trancount > 0 begin print('rollback'); rollback; end");
AppendLine($";throw;");
AppendEnd(BEGIN_END);
return this;
Expand Down
113 changes: 113 additions & 0 deletions SQL Format/Helpers/SqlDomBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,31 @@ public void ProduceFullTableRenameScript(TSqlScript script, string suffix, bool
objType = OBJECT;
_sqlBuilder.AppendSpRename(objName, newName, objType, "constraint").NL();
}

foreach (var colDef in createTableStatement.Definition.ColumnDefinitions)
{
foreach (var constraint in colDef.Constraints)
{
if (constraint.ConstraintIdentifier == null) continue;
var conName = TSQLHelper.Identifier2Value(constraint.ConstraintIdentifier);
objName = !reverse ? $"{schemaName}.{conName}" : $"{schemaName}.{conName + suffix}";
newName = reverse ? conName : conName + suffix;
objType = OBJECT;
_sqlBuilder.AppendSpRename(objName, newName, objType, "constraint").NL();
}

{
var constraint = colDef.DefaultConstraint;
if (constraint == null || constraint.ConstraintIdentifier == null) continue;
var conName = TSQLHelper.Identifier2Value(constraint.ConstraintIdentifier);
objName = !reverse ? $"{schemaName}.{conName}" : $"{schemaName}.{conName + suffix}";
newName = reverse ? conName : conName + suffix;
objType = OBJECT;
_sqlBuilder.AppendSpRename(objName, newName, objType, "constraint").NL();
}

}

}
if (statement is CreateIndexStatement createIndexStatement)
{
Expand Down Expand Up @@ -382,5 +407,93 @@ public void ProduceCopytableVerify(CreateTableStatement createTableStatement, st
Print($"Success comparing {sourceTableNameFull} with {destTableNameFull}");
_sqlBuilder.Unindent();
}

public void ProduceCopyTableSingle(CreateTableStatement createTableStatement, string varSuffix, string targetTableNameFull = null)
{
string sourceTableNameFull = TSQLHelper.Identifiers2Value(createTableStatement.SchemaObjectName.Identifiers);
string destTableNameFull = targetTableNameFull != null ? targetTableNameFull : TSQLHelper.Identifiers2Value(createTableStatement.SchemaObjectName.Identifiers);

UniqueConstraintDefinition clusteredKey = createTableStatement.Definition.TableConstraints.Where(c => c is UniqueConstraintDefinition uni && uni.Clustered == true).SingleOrDefault() as UniqueConstraintDefinition;
if (clusteredKey is null)
{
_sqlBuilder.AppendLine("Error: No clustered index!");
return;
}
ColInfo keyColumn = new ColInfo();
{
var colName = TSQLHelper.Identifiers2Value(clusteredKey.Columns[0].Column.MultiPartIdentifier.Identifiers);
ColumnDefinition column = createTableStatement.Definition.ColumnDefinitions.Where(c => TSQLHelper.Identifier2Value(c.ColumnIdentifier).ToLowerInvariant() == colName.ToLowerInvariant()).Single();
keyColumn.Index = 0;
keyColumn.ColumnName = colName;
keyColumn.ColumnDefinition = column;
keyColumn.ColumnTypeStr = TSQLHelper.Column2TypeStr(column);
keyColumn.VarNameLastValue = $"@Key{varSuffix}";
}

string AffectedIterationName = $"@AffectedIteration{varSuffix}";
_sqlBuilder.AppendLine($"declare {AffectedIterationName} int;");

string numName = $"@i{varSuffix}";
_sqlBuilder.AppendLine($"declare {numName} int = 0;");

string totalCountName = $"@TotalCount{varSuffix}";
_sqlBuilder.AppendLine($"declare {totalCountName} int = (select count(*) from {sourceTableNameFull} with (nolock));").NL();


// last column via table
string keysTableName = $"#keys{varSuffix}";
_sqlBuilder.AppendLine($"drop table if exists {keysTableName};")
.AppendLine($"create table {keysTableName}(")
.Indent()
.AppendLine($"{keyColumn.ColumnName} {keyColumn.ColumnTypeStr} not null primary key clustered")
.Unindent()
.AppendLine(");").NL();


_sqlBuilder.AppendLine($"declare {keyColumn.VarNameLastValue} {keyColumn.ColumnTypeStr};");

_sqlBuilder.NL();
_sqlBuilder.AppendLine($"insert into {keysTableName}({keyColumn.ColumnName})");
_sqlBuilder.AppendLine($"select distinct t.{keyColumn.ColumnName}");
_sqlBuilder.AppendLine($"from {sourceTableNameFull} t with (nolock);").NL();

string loopCountName = $"@LoopCount{varSuffix}";
_sqlBuilder.AppendLine($"declare {loopCountName} int = @@rowcount;");

Print($"concat('Total count:', {totalCountName}, ', loop count: ', {loopCountName}, ' in {sourceTableNameFull}.')", false);
_sqlBuilder.NL();

_sqlBuilder.AppendLine($"while 1=1").AppendBegin();
{
_sqlBuilder.AppendLine($"set {numName} += 1;").NL();

_sqlBuilder.AppendLine($"set {keyColumn.VarNameLastValue} = (").Indent()
.AppendLine($"select top (1) t.{keyColumn.ColumnName}")
.AppendLine($"from {keysTableName} t")
.AppendLine($"where {keyColumn.VarNameLastValue} is null or t.{keyColumn.ColumnName} > {keyColumn.VarNameLastValue}")
.AppendLine($"order by 1 asc")
.Unindent().AppendLine(");").NL();

_sqlBuilder.AppendLine($"if {keyColumn.VarNameLastValue} is null").AppendBegin().AppendLine("break;").AppendEnd().NL();


Print($"concat('Processing ', {numName},' / ', {loopCountName}, ', {keyColumn.ColumnName}: ', {keyColumn.VarNameLastValue}, ' ...')", false);

_sqlBuilder.AppendLine($"insert into {destTableNameFull}(")
.Indent()
.AppendLines(createTableStatement.Definition.ColumnDefinitions.Select(c => TSQLHelper.Identifier2Value(c.ColumnIdentifier)), ",")
.Unindent()
.AppendLine(")")
.AppendLine($"select ")
.Indent()
.AppendLines(createTableStatement.Definition.ColumnDefinitions.Select(c => $"t.{TSQLHelper.Identifier2Value(c.ColumnIdentifier)}"), ",")
.Unindent()
.AppendLine($"from {sourceTableNameFull} t")
.AppendLine($"where t.{keyColumn.ColumnName} = {keyColumn.VarNameLastValue};").NL();

}
_sqlBuilder.AppendEnd($"end");
}

}
}
2 changes: 2 additions & 0 deletions SQL Format/SQLFormat.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,8 @@
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="SQLTranslator.cs" />
<Compile Include="SQLTranslatorCopySingle.cs" />
<Compile Include="SQLTranslatorMyScript.cs" />
<Compile Include="SQLTranslatorInsert.cs" />
<Compile Include="SQLTranslatorCopy.cs" />
<Compile Include="SQLTranslatorMerge.cs" />
Expand Down
101 changes: 101 additions & 0 deletions SQL Format/SQLTranslatorCopySingle.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Microsoft.SqlServer.TransactSql.ScriptDom;
using SQL_Format.Helpers;

namespace SQL_Format
{
public class SQLTranslatorCopySingle : SQLTranslator
{
public override string GetCaption()
{
return "Copy Table Sinlge";
}

public override void SetupOptionsContent(Control Parent, EventHandler changedHandler)
{
this.AddOptionTextBox("Var Suffix", "varSuffix", "11245U1", Parent, changedHandler);
this.AddOptionCheckBox("Use Transaction", "useTransaction", true, Parent, changedHandler);
this.AddOptionCheckBox("Rollback", "useRollback", true, Parent, changedHandler);
}

public override string TranslateExt2(CreateTableStatement createTableStatement, object options, string content, TSqlScript sqlScript)
{
string varSuffix = this.GetOptionString("varSuffix", options) ?? "";
bool useTransaction = this.GetOptionBoolDef("useTransaction", options, false);
bool useRollback = this.GetOptionBoolDef("useRollback", options, false);

SqlBuilder result = new SqlBuilder();
SqlDomBuilder sqlDomBuilder = new SqlDomBuilder(sqlScript, result);


string tableSuffix = "_new";
result.TableNameFull = TSQLHelper.Identifiers2Value(createTableStatement.SchemaObjectName.Identifiers);
result.TableName = TSQLHelper.Identifiers2ValueLast(createTableStatement.SchemaObjectName.Identifiers);
string tableNameNew = result.TableName + tableSuffix;
string tableNameFullNew = result.TableNameFull + tableSuffix;
{
result.AppendBegin(SqlBuilder.BEGIN_TRY);
{
if (useTransaction) result.AppendLine($"begin tran;").NL();

string messageVarName = $"@msg{varSuffix}";
result.AppendLine($"declare {messageVarName} nvarchar(2024);").NL();
sqlDomBuilder.VarMsgName = messageVarName;
sqlDomBuilder.Print($"Running Script{varSuffix}.{result.TableNameFull}...").NL();

result.AppendIf($"object_id('{tableNameFullNew}') is null").AppendBegin();
{
result.AppendLine("-- create new table");
sqlDomBuilder.ProduceFullTableRenameContent(sqlScript, tableSuffix, content);

result.AppendEnd();
}

sqlDomBuilder.ProduceCopyTableSingle(createTableStatement, varSuffix, targetTableNameFull: tableNameFullNew);

result.AppendBegin();
{
result.AppendLine("-- rename source table to _old");
sqlDomBuilder.ProduceFullTableRenameScript(sqlScript, "_old");
result.AppendEnd();
}

result.AppendBegin();
{
result.AppendLine("-- rename new table to current");
sqlDomBuilder.ProduceFullTableRenameScript(sqlScript, tableSuffix, reverse: true);

result.AppendEnd();
}

sqlDomBuilder.ProduceCopytableVerify(createTableStatement, varSuffix, targetTableNameFull: result.TableNameFull + "_old");

result.NL();
sqlDomBuilder.Print("Dropping table {result.TableNameFull}_old...");
result.AppendLine($"drop table if exists {result.TableNameFull}_old;").NL();

if (useTransaction)
{
if (useRollback)
result.AppendLine($"rollback;").NL();
else
{
result.AppendLine($"commit;").NL();
sqlDomBuilder.Print("Committed.");
}
}

result.AppendEnd(SqlBuilder.END_TRY, false);
}
result.AppendCatchTypicalRollback();
}
return result.ToString();
}
}
}
74 changes: 74 additions & 0 deletions SQL Format/SQLTranslatorMyScript.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Microsoft.SqlServer.TransactSql.ScriptDom;
using SQL_Format.Helpers;

namespace SQL_Format
{
public class SQLTranslatorMyScript: SQLTranslator
{
public override string GetCaption()
{
return "My Script";
}

public override void SetupOptionsContent(Control Parent, EventHandler changedHandler)
{
}

public override string TranslateExt2(CreateTableStatement createTableStatement, object options, string content, TSqlScript sqlScript)
{
SqlBuilder result = new SqlBuilder();
SqlDomBuilder sqlDomBuilder = new SqlDomBuilder(sqlScript, result);
result.TableNameFull = TSQLHelper.Identifiers2Value(createTableStatement.SchemaObjectName.Identifiers);
result.TableName = TSQLHelper.Identifiers2ValueLast(createTableStatement.SchemaObjectName.Identifiers);

int[] precs = new int[] { 18, 26, 20};

result.AppendLine($"----------------- {result.TableNameFull} -----------------");
result.AppendLine($"raiserror('Altering {result.TableNameFull}...', 10, 1) with nowait;");

int addedCount = 0;
foreach (var c in createTableStatement.Definition.ColumnDefinitions)
{
string colType = TSQLHelper.Column2TypeStr(c).ToUpperInvariant();
if (colType.StartsWith("DECIMAL"))
{
int prec = TSQLHelper.ColumnDecimalPrecision(c);
if (precs.Contains(prec))
{
addedCount++;
bool isNullable = TSQLHelper.ColumnIsNullable(c);
string null_ = isNullable ? " NULL" : " NOT NULL";
string colName = TSQLHelper.Identifier2Value(c.ColumnIdentifier);
string subalterColumn = $"column {colName} {colType}{null_}";
result.AppendIf($"not exists(select * from INFORMATION_SCHEMA.COLUMNS c where c.TABLE_NAME = '{result.TableName}' and c.COLUMN_NAME = '{colName}' and c.NUMERIC_PRECISION = {prec})").AppendBegin();
{
string alterColumn = $"alter {subalterColumn}";
result.AppendLine($"raiserror('{alterColumn}...', 10, 1) with nowait;");
if (isNullable)
result.AppendLine($"update {result.TableNameFull} set {colName} = try_cast({colName} as {colType});");
result.AppendLine($"alter table {result.TableNameFull}").Indent();
result.AppendLine($"{alterColumn};").Unindent();
result.AppendEnd(addSpaceafterwards: false);
}
result.AppendLine("else").Indent();
{
result.AppendLine($"raiserror('already {subalterColumn}.', 10, 1) with nowait;");
result.Unindent();
}

result.AppendLine("GO");
}
}
}
result.AppendLine($"----------------------------------");
return result.ToString();
}
}
}
Loading

0 comments on commit a955e5e

Please sign in to comment.