Skip to content

Commit

Permalink
add: parse pivot for tsql and plsql
Browse files Browse the repository at this point in the history
  • Loading branch information
victor committed May 14, 2020
1 parent a0731d9 commit 2beedfc
Show file tree
Hide file tree
Showing 12 changed files with 186 additions and 87 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -78,17 +78,20 @@ private async Task InternalConvert(SchemaInfo schemaInfo = null)
{
DbInterpreter sourceInterpreter = this.Source.DbInterpreter;
sourceInterpreter.Option.BulkCopy = this.Option.BulkCopy;
sourceInterpreter.Subscribe(this.observer);

if (sourceInterpreter.DatabaseType == DatabaseType.Oracle)
{
sourceInterpreter.Option.TreatBytesAsNullForExecuting = true;
}
sourceInterpreter.Subscribe(this.observer);

sourceInterpreter.Option.GetTableAllObjects = false;
sourceInterpreter.Option.ThrowExceptionWhenErrorOccurs = false;
this.Target.DbInterpreter.Option.ThrowExceptionWhenErrorOccurs = false;

if(string.IsNullOrEmpty(this.Target.DbOwner))
{
if(this.Target.DbInterpreter.DatabaseType == DatabaseType.Oracle)
{
this.Target.DbOwner = (this.Target.DbInterpreter as OracleInterpreter).GetDbOwner();
}
}

DatabaseObjectType databaseObjectType = (DatabaseObjectType)Enum.GetValues(typeof(DatabaseObjectType)).Cast<int>().Sum();

if (schemaInfo != null && !this.Source.DbInterpreter.Option.GetTableAllObjects
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public class ScriptTokenProcessor
{
private ColumnTranslator columnTranslator;
private Regex identifierRegex = new Regex($@"([`""\[][ _0-9a-zA-Z]+[`""\]])");
private Regex nameRegex = new Regex(@"\b(^[_a-zA-Z][ _0-9a-zA-Z]+$)\b");
private Regex nameRegex = new Regex(@"\b(^[_a-zA-Z][ _0-9a-zA-Z]*$)\b");
private bool removeDbOwner => this.TargetInterpreter.DatabaseType != DatabaseType.SqlServer;
private bool nameWithQuotation = SettingManager.Setting.DbObjectNameMode == DbObjectNameMode.WithQuotation;
public CommonScript Script { get; set; }
Expand Down
25 changes: 11 additions & 14 deletions DatabaseConverter/DatabaseConverter.Core/TranslateEngine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -118,20 +118,17 @@ private void ScriptTranslated(DatabaseType dbType, DatabaseObject dbObject, Tran

private void TranslateOwner()
{
if (!string.IsNullOrEmpty(this.targetDbOwner))
{
this.SetDatabaseObjectsOwner(this.targetSchemaInfo.UserDefinedTypes);
this.SetDatabaseObjectsOwner(this.targetSchemaInfo.Functions);
this.SetDatabaseObjectsOwner(this.targetSchemaInfo.Tables);
this.SetDatabaseObjectsOwner(this.targetSchemaInfo.TableColumns);
this.SetDatabaseObjectsOwner(this.targetSchemaInfo.TablePrimaryKeys);
this.SetDatabaseObjectsOwner(this.targetSchemaInfo.TableForeignKeys);
this.SetDatabaseObjectsOwner(this.targetSchemaInfo.TableIndexes);
this.SetDatabaseObjectsOwner(this.targetSchemaInfo.TableTriggers);
this.SetDatabaseObjectsOwner(this.targetSchemaInfo.TableConstraints);
this.SetDatabaseObjectsOwner(this.targetSchemaInfo.Views);
this.SetDatabaseObjectsOwner(this.targetSchemaInfo.Procedures);
}
this.SetDatabaseObjectsOwner(this.targetSchemaInfo.UserDefinedTypes);
this.SetDatabaseObjectsOwner(this.targetSchemaInfo.Functions);
this.SetDatabaseObjectsOwner(this.targetSchemaInfo.Tables);
this.SetDatabaseObjectsOwner(this.targetSchemaInfo.TableColumns);
this.SetDatabaseObjectsOwner(this.targetSchemaInfo.TablePrimaryKeys);
this.SetDatabaseObjectsOwner(this.targetSchemaInfo.TableForeignKeys);
this.SetDatabaseObjectsOwner(this.targetSchemaInfo.TableIndexes);
this.SetDatabaseObjectsOwner(this.targetSchemaInfo.TableTriggers);
this.SetDatabaseObjectsOwner(this.targetSchemaInfo.TableConstraints);
this.SetDatabaseObjectsOwner(this.targetSchemaInfo.Views);
this.SetDatabaseObjectsOwner(this.targetSchemaInfo.Procedures);
}

private void SetDatabaseObjectsOwner<T>(List<T> dbObjects) where T : DatabaseObject
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ public class JoinItem
public JoinType Type { get; set; }
public TableName TableName { get; set; }
public TokenInfo Condition { get; set; }
public TokenInfo Special { get; set; }
public TokenInfo Alias { get; set; }
}

public enum JoinType
Expand Down
8 changes: 5 additions & 3 deletions DatabaseConverter/SqlAnalyser.Core/Model/Token/TokenInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ public class TokenInfo
public virtual TokenType Type { get; set; }
public string Symbol { get; set; }
public int? StartIndex { get; set; }
public int? StopIndex { get; set; }
public int? StopIndex { get; set; }

public int Length => this.StartIndex.HasValue && this.StopIndex.HasValue ? (this.StopIndex - this.StartIndex + 1).Value : 0;

public List<TokenInfo> Tokens { get; set; } = new List<TokenInfo>();
public List<TokenInfo> Tokens { get; set; } = new List<TokenInfo>();

public TokenInfo(string symbol)
{
Expand Down Expand Up @@ -81,6 +81,8 @@ public enum TokenType
Option = 10,
JoinOn = 11,
CursorName = 12,
Alias = 13
Alias = 13,
Pivot = 14,
UnPivot = 15
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -935,6 +935,8 @@ public List<FromItem> ParseFormClause(From_clauseContext node)
fromItem.TableName = this.ParseTableName(table);

Join_clauseContext[] joins = table.join_clause();
Pivot_clauseContext pivot = table.pivot_clause();
Unpivot_clauseContext unpivot = table.unpivot_clause();

if (joins != null && joins.Length > 0)
{
Expand Down Expand Up @@ -966,6 +968,18 @@ public List<FromItem> ParseFormClause(From_clauseContext node)
fromItem.JoinItems.Add(joinItem);
}
}
else if (pivot != null)
{
JoinItem joinItem = new JoinItem() { Type = JoinType.PIVOT };
joinItem.Special = this.ParseToken(pivot, TokenType.Pivot);
fromItem.JoinItems.Add(joinItem);
}
else if (unpivot != null)
{
JoinItem joinItem = new JoinItem() { Type = JoinType.UNPIVOT };
joinItem.Special = this.ParseToken(unpivot, TokenType.UnPivot);
fromItem.JoinItems.Add(joinItem);
}

fromItems.Add(fromItem);
}
Expand Down Expand Up @@ -1251,7 +1265,7 @@ public override ColumnName ParseColumnName(ParserRuleContext node, bool strict =
if (ids != null && ids.Length > 0)
{
columnName = new ColumnName(ids[0]);
}
}
}
else if (node is Select_list_elementsContext ele)
{
Expand Down Expand Up @@ -1359,7 +1373,7 @@ public override List<TokenInfo> GetColumnNameTokens(IParseTree node)
}

return tokens;
}
}

private bool IsChildOfType<T>(RuleContext node)
{
Expand Down Expand Up @@ -1387,14 +1401,14 @@ public override List<TokenInfo> GetRoutineNameTokens(IParseTree node)
if (node is General_element_partContext gep && (node as General_element_partContext).children.Any(item => item is Function_argumentContext))
{
routineName = gep.id_expression().LastOrDefault();
}
}

if (routineName != null)
{
tokens.Add(new TokenInfo(routineName) { Type = TokenType.RoutineName });
}

return tokens;
}
}
}
}
73 changes: 48 additions & 25 deletions DatabaseConverter/SqlAnalyser.Core/RuleAnalyser/TSqlRuleAnalyser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -468,39 +468,39 @@ public List<FromItem> ParseTableScources(Table_sourcesContext node)
else
{
fromItem.TableName = this.ParseTableName(fromTable);
}

Join_partContext[] joins = tsi.join_part();
Join_partContext[] joins = tsi.join_part();

if (joins != null && joins.Length > 0)
if (joins != null && joins.Length > 0)
{
foreach (Join_partContext join in joins)
{
foreach (Join_partContext join in joins)
{
List<JoinItem> joinItems = this.ParseJoin(join);
List<JoinItem> joinItems = this.ParseJoin(join);

if (joinItems.Count > 1)
if (joinItems.Count > 1)
{
for (int i = joinItems.Count - 1; i > 0; i--)
{
for (int i = joinItems.Count - 1; i > 0; i--)
{
JoinItem currentJoinItem = joinItems[i];
JoinItem currentJoinItem = joinItems[i];

if (i - 1 > 0)
{
JoinItem previousJoinItem = joinItems[i - 1];
if (i - 1 > 0)
{
JoinItem previousJoinItem = joinItems[i - 1];

TableName previousJoinTableName = new TableName(previousJoinItem.TableName.Symbol);
ObjectHelper.CopyProperties(previousJoinItem.TableName, previousJoinTableName);
TableName previousJoinTableName = new TableName(previousJoinItem.TableName.Symbol);
ObjectHelper.CopyProperties(previousJoinItem.TableName, previousJoinTableName);

TableName currentJoinTableName = new TableName(currentJoinItem.TableName.Symbol);
ObjectHelper.CopyProperties(currentJoinItem.TableName, currentJoinTableName);
TableName currentJoinTableName = new TableName(currentJoinItem.TableName.Symbol);
ObjectHelper.CopyProperties(currentJoinItem.TableName, currentJoinTableName);

joinItems[i - 1].TableName = currentJoinTableName;
joinItems[i].TableName = previousJoinTableName;
}
joinItems[i - 1].TableName = currentJoinTableName;
joinItems[i].TableName = previousJoinTableName;
}
}

fromItem.JoinItems.AddRange(joinItems);
}

fromItem.JoinItems.AddRange(joinItems);
}
}

Expand Down Expand Up @@ -540,19 +540,34 @@ public List<JoinItem> ParseJoin(Join_partContext node)
case TSqlParser.CROSS:
joinItem.Type = JoinType.CROSS;
break;
case TSqlParser.PIVOT:
joinItem.Type = JoinType.PIVOT;
break;
case TSqlParser.UNPIVOT:
joinItem.Type = JoinType.UNPIVOT;
break;
}
}
}

Table_sourceContext tableSoure = node.table_source();
Pivot_clauseContext pivot = node.pivot_clause();
Unpivot_clauseContext unpivot = node.unpivot_clause();

joinItem.TableName = this.ParseTableName(tableSoure);
joinItem.Condition = this.ParseCondition(node.search_condition());
As_table_aliasContext alias = node.as_table_alias();

if (alias != null)
{
joinItem.Alias = new TokenInfo(alias.table_alias());
}

joinItems.Add(joinItem);

if (tableSoure != null)
{
joinItem.TableName = this.ParseTableName(tableSoure);
joinItem.Condition = this.ParseCondition(node.search_condition());

Table_source_item_joinedContext join = tableSoure.table_source_item_joined();

if (join != null)
Expand All @@ -564,6 +579,14 @@ public List<JoinItem> ParseJoin(Join_partContext node)
joinItems.AddRange(childJoinItems);
}
}
else if (pivot != null)
{
joinItem.Special = this.ParseToken(pivot, TokenType.Pivot);
}
else if (unpivot != null)
{
joinItem.Special = this.ParseToken(unpivot, TokenType.UnPivot);
}

return joinItems;
}
Expand Down Expand Up @@ -1315,12 +1338,12 @@ public override TableName ParseTableName(ParserRuleContext node, bool strict = f
{
tableName = new TableName(tn);
}
else if(node is Full_table_nameContext fullName)
else if (node is Full_table_nameContext fullName)
{
tableName = new TableName(fullName);

tableName.Name = new TokenInfo(fullName.table);

}
else if (node is Table_source_itemContext tsi)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,17 +106,12 @@ protected void BuildSelectStatementFromItems(SelectStatement selectStatement)

this.Append($"{fromItem.TableName}{(hasJoins ? Environment.NewLine : "")}", false);

if (fromItem.JoinItems.Count > 0)
{
foreach (JoinItem joinItem in fromItem.JoinItems)
{
string condition = joinItem.Condition == null ? "" : $" ON {joinItem.Condition}";
bool hasSubSelect = false;

this.AppendLine($"{joinItem.Type} JOIN {joinItem.TableName}{condition}");
}
}
else if (fromItem.SubSelectStatement != null)
if (fromItem.SubSelectStatement != null)
{
hasSubSelect = true;

this.AppendLine("");
this.AppendLine("(");
this.BuildSelectStatement(fromItem.SubSelectStatement, false);
Expand All @@ -126,7 +121,63 @@ protected void BuildSelectStatementFromItems(SelectStatement selectStatement)
{
this.Append($"{fromItem.Alias}", false);
}
}
}

if (fromItem.JoinItems.Count > 0)
{
if (hasSubSelect)
{
this.AppendLine("");
}

foreach (JoinItem joinItem in fromItem.JoinItems)
{
if (joinItem.Special != null)
{
if (joinItem.Type == JoinType.PIVOT || joinItem.Type == JoinType.UNPIVOT)
{
string symbol = joinItem.Special.Symbol;

if (symbol.Contains(joinItem.Type.ToString()))
{
this.AppendLine(symbol);
}
else
{
bool hasBracket = joinItem.Special.Symbol.StartsWith("(") && joinItem.Special.Symbol.EndsWith(")");
this.AppendLine($"{joinItem.Type}");

if (!hasBracket)
{
this.AppendLine("(");
}

this.AppendLine(symbol);

if (!hasBracket)
{
this.AppendLine(")");
}
}

if (joinItem.Alias != null)
{
this.AppendLine(joinItem.Alias.Symbol);
}
else
{
this.AppendLine(joinItem.Type.ToString() + "_");
}
}
}
else
{
string condition = joinItem.Condition == null ? "" : $" ON {joinItem.Condition}";

this.AppendLine($"{joinItem.Type} JOIN {joinItem.TableName}{condition}");
}
}
}

i++;
}
Expand Down
Loading

0 comments on commit 2beedfc

Please sign in to comment.