protected override void DoCompile() { var node = Schema.Source; m_All = new RDBMSEntity(null, node, RDBMSEntityType.Schema, node.AttrByName(NAME_ATTR).ValueAsString("schema")); TransformEntityName(m_All); base.DoCompile(); }
/// <summary> /// Override to map a name from schema into the name that should be used in the output (i.e. real table name) /// </summary> public virtual void TransformEntityName(RDBMSEntity entity) { var name = entity.OriginalName; var parentName = entity.ParentEntity != null ? "{0}_".Args(entity.ParentEntity.TransformedShortName) : string.Empty; if (entity.EntityType == RDBMSEntityType.PrimaryKey || entity.EntityType == RDBMSEntityType.Reference) { var parentParentName = entity.ParentEntity != null && entity.ParentEntity.ParentEntity != null ? "{0}_".Args(entity.ParentEntity.ParentEntity.TransformedShortName) : string.Empty; parentName = entity.ParentEntity.EntityType == RDBMSEntityType.Column ? parentParentName : parentName; } string result = entity.OriginalName; switch (entity.EntityType) { case RDBMSEntityType.Table: { result = "tbl_" + name; break; } case RDBMSEntityType.Column: { result = name; break; } case RDBMSEntityType.Domain: { result = name; break; } case RDBMSEntityType.PrimaryKey: { result = "pk_" + parentName + name; break; } case RDBMSEntityType.Index: { result = "idx_" + parentName + name; break; } case RDBMSEntityType.Trigger: { result = "trg_" + parentName + name; break; } case RDBMSEntityType.View: { result = "viw_" + name; break; } case RDBMSEntityType.StoreProc: { result = "sp_" + name; break; } case RDBMSEntityType.CheckConstraint: { result = "cc_" + name; break; } case RDBMSEntityType.Reference: { result = "fk_" + parentName + name; break; } } entity.TransformedName = result; entity.TransformedShortName = entity.OriginalShortName; if (entity.TransformedShortName.IsNullOrWhiteSpace()) { entity.TransformedShortName = entity.TransformedName; } if (NameCaseSensitivity == NameCaseSensitivity.ToUpper) { entity.TransformedName = entity.TransformedName.ToUpperInvariant(); entity.TransformedShortName = entity.TransformedShortName.ToUpperInvariant(); } else if (NameCaseSensitivity == NameCaseSensitivity.ToLower) { entity.TransformedName = entity.TransformedName.ToLowerInvariant(); entity.TransformedShortName = entity.TransformedShortName.ToLowerInvariant(); } }
public override void TransformEntityName(RDBMSEntity entity) { base.TransformEntityName(entity); if (entity.EntityType == RDBMSEntityType.Column) { entity.TransformedName = entity.TransformedName.ToUpperInvariant(); entity.TransformedShortName = entity.TransformedShortName.ToUpperInvariant(); } }
/// <summary> /// Override to read primary key definition form sub-section of table (not column level) /// </summary> protected virtual void DoReadPrimaryKeySection(IConfigSectionNode pkNode, RDBMSEntity table) { var keyName = pkNode.Value; if (keyName.IsNullOrWhiteSpace()) { keyName = "PRIMARY"; } var pKey = new RDBMSEntity(table, pkNode, RDBMSEntityType.PrimaryKey, keyName); TransformEntityName(pKey); }
/// <summary> /// Override to read primary key definition form sub-section of table (not column level) /// </summary> protected virtual void DoReadIndexSection(IConfigSectionNode idxNode, RDBMSEntity table) { var idxName = idxNode.Value; if (idxName.IsNullOrWhiteSpace()) { m_CompileErrors.Add(new SchemaCompilationException(idxNode.RootPath, "Table '{0}' declares an index without a name '{1}'".Args(table.OriginalName, idxNode.RootPath))); return; } var idx = new RDBMSEntity(table, idxNode, RDBMSEntityType.Index, idxName); TransformEntityName(idx); }
public RDBMSEntity(RDBMSEntity parentEntity, IConfigNode sourceNode, RDBMSEntityType entityType, string originalName, string originalShortName = null, string transformedName = null, string transformedShortName = null) { if (parentEntity != null) { parentEntity.Children.Add(this); } ParentEntity = parentEntity; SourceNode = sourceNode; EntityType = entityType; OriginalName = originalName; OriginalShortName = originalShortName; TransformedName = transformedName; TransformedShortName = transformedShortName; }
/// <summary> /// Override to outpur foreign keys /// </summary> protected virtual void DoForeignKeys(RDBMSEntity table, StringBuilder sb, ref bool firstItem, Outputs outputs) { var tableLevelKeys = table.Children.Where(c => c.EntityType == RDBMSEntityType.Reference); var columnLevelKeys = table.Children.Where(c => c.EntityType == RDBMSEntityType.Column) .SelectMany(col => col.Children) .Where(c => c.EntityType == RDBMSEntityType.Reference); var allKeys = tableLevelKeys.Concat(columnLevelKeys); foreach (var fke in allKeys) { var rt = ((IConfigSectionNode)fke.SourceNode).AttrByName(TABLE_SECTION).Value; var rc = ((IConfigSectionNode)fke.SourceNode).AttrByName(COLUMN_SECTION).Value; if (rt.IsNullOrWhiteSpace() || rc.IsNullOrWhiteSpace()) { m_CompileErrors.Add(new SchemaCompilationException(fke.SourceNode.RootPath, "Both table and column names are required for reference '{0}' table section '{1}'".Args(table.OriginalName, fke.SourceNode.Name))); continue; } var refTable = new RDBMSEntity(null, null, RDBMSEntityType.Table, rt); TransformEntityName(refTable); var refColumn = new RDBMSEntity(refTable, null, RDBMSEntityType.Column, rc); TransformEntityName(refColumn); var refTableWasAltreadyDeclared = m_All.Children.Any(t => t.EntityType == RDBMSEntityType.Table && refTable.OriginalName.Equals(t.OriginalName, NameComparison)); var useAlterStatement = !refTableWasAltreadyDeclared || m_SeparateForeignKeys; var constraint = TransformKeywordCase(" constraint {0} foreign key ({1}) references {2}({3})") .Args( GetQuotedIdentifierName(RDBMSEntityType.Reference, fke.TransformedName), GetQuotedIdentifierName(RDBMSEntityType.Column, fke.ParentEntity.TransformedName), GetQuotedIdentifierName(RDBMSEntityType.Table, refTable.TransformedName), GetQuotedIdentifierName(RDBMSEntityType.Column, refColumn.TransformedName) ); if (useAlterStatement) { var ksb = outputs[RDBMSCompiler.FOREIGN_KEYS_OUTPUT]; ksb.AppendLine(GetStatementDelimiterScript(RDBMSEntityType.Reference, true)); ksb.AppendLine(TransformKeywordCase(" alter table {0} add {1}") .Args( GetQuotedIdentifierName(RDBMSEntityType.Table, table.TransformedName), constraint ) ); ksb.AppendLine(GetStatementDelimiterScript(RDBMSEntityType.Reference, false)); } else { if (!firstItem) { sb.AppendLine(","); } sb.Append(constraint); firstItem = false; } } }
/// <summary> /// Override to output primary keys /// </summary> protected virtual void DoPrimaryKeys(RDBMSEntity table, StringBuilder sb, ref bool firstItem) { var tableLevelKeys = table.Children.Where(c => c.EntityType == RDBMSEntityType.PrimaryKey); var columnLevelKeys = table.Children.Where(c => c.EntityType == RDBMSEntityType.Column) .SelectMany(col => col.Children) .Where(c => c.EntityType == RDBMSEntityType.PrimaryKey); var allKeys = tableLevelKeys.Concat(columnLevelKeys); var pk = allKeys.FirstOrDefault(); if (pk == null) { return; } if (allKeys.Count() > 1) { m_CompileErrors.Add(new SchemaCompilationException(table.SourceNode.RootPath, "Table '{0}' defines more than one primary key. Only first on '{1}' is used" .Args(table.OriginalName, pk.ParentEntity.OriginalName))); } if (pk.ParentEntity.EntityType == RDBMSEntityType.Column) { if (!firstItem) { sb.AppendLine(","); } sb.Append(TransformKeywordCase(" constraint {0} primary key ({1})") .Args( GetQuotedIdentifierName(RDBMSEntityType.PrimaryKey, pk.TransformedName), GetQuotedIdentifierName(RDBMSEntityType.Column, pk.ParentEntity.TransformedName) ) ); } else //table { var colNames = new List <string>(); foreach (var col in ((ConfigSectionNode)pk.SourceNode).Children.Where(c => c.IsSameName(COLUMN_SECTION))) { var cn = col.Value; var column = table.Children.FirstOrDefault(c => c.EntityType == RDBMSEntityType.Column && c.OriginalName.Equals(cn, NameComparison)); if (column == null) { m_CompileErrors.Add(new SchemaCompilationException(table.SourceNode.RootPath, "Table '{0}' defines primary key which references column by name '{1}' which does not exist" .Args(table.OriginalName, cn))); return; } colNames.Add(GetQuotedIdentifierName(RDBMSEntityType.Column, column.TransformedName)); } var colNamesLine = string.Join(", ", colNames); if (!firstItem) { sb.AppendLine(","); } sb.Append(TransformKeywordCase(" constraint {0} primary key ({1})") .Args( GetQuotedIdentifierName(RDBMSEntityType.PrimaryKey, pk.TransformedName), colNamesLine ) ); } firstItem = false; }
/// <summary> /// Override to compile a RDBMS Table /// </summary> protected virtual void DoColumn(IConfigSectionNode columnNode, RDBMSEntity table, StringBuilder sb, ref bool firstColumn, Outputs outputs) { var colComment = columnNode.AttrByName(SCRIPT_COMMENT_ATTR).Value; if (colComment.IsNotNullOrWhiteSpace()) { sb.AppendLine(" -- {0}".Args(colComment)); } var columnName = columnNode.Value; if (columnName.IsNullOrWhiteSpace()) { m_CompileErrors.Add(new SchemaCompilationException(columnNode.RootPath, "Table '{0}' missing column name.".Args(table.OriginalName))); return; } var column = new RDBMSEntity(table, columnNode, RDBMSEntityType.Column, columnName, columnNode.AttrByName(SHORT_NAME_ATTR).Value ?? columnName); TransformEntityName(column); var typeNode = columnNode.Navigate(TYPE_ATTR + "|$" + TYPE_ATTR); if (typeNode == null || typeNode.VerbatimValue.IsNullOrWhiteSpace()) { m_CompileErrors.Add(new SchemaCompilationException(columnNode.RootPath, "Column '{0}' missing {1} attribute.".Args(columnName, TYPE_ATTR))); return; } var columnType = typeNode.Value; var type = new RDBMSEntity(column, typeNode, RDBMSEntityType.Domain, columnType); TransformEntityName(type); var domain = CreateDomain("{0}.{1}::{2}".Args(table.OriginalName, column.OriginalName, type.OriginalName), type.OriginalName, typeNode); if (domain == null) { m_CompileErrors.Add(new SchemaCompilationException(columnNode.RootPath, "Domain could not be created: " + type.TransformedName)); return; } domain.TransformColumnName(this, column); if (!firstColumn) { sb.AppendLine(","); } #region Column Line { var cn = GetQuotedIdentifierName(RDBMSEntityType.Column, column.TransformedName); var tn = GetQuotedIdentifierName(RDBMSEntityType.Domain, domain.GetTypeName(this)); var required = (domain.GetColumnRequirement(this) ?? false) || columnNode.AttrByName(REQUIRED_ATTR).ValueAsBool(); var nn = TransformKeywordCase(GetColumnNullNotNullClause(column, required)); var auto = domain.GetColumnAutoGeneratedScript(this, column, outputs); var dfltValue = columnNode.AttrByName(DEFAULT_ATTR).Value ?? domain.GetColumnDefaultScript(this, column, outputs); var dflt = dfltValue.IsNotNullOrWhiteSpace()? "{0} {1}".Args(TransformKeywordCase("default"), EscapeString(dfltValue)) : string.Empty; var chk = domain.GetColumnCheckScript(this, column, outputs); var cmntValue = columnNode.AttrByName(COMMENT_ATTR).Value; var cmnt = cmntValue.IsNotNullOrWhiteSpace()? "{0} {1}".Args(TransformKeywordCase("comment"), EscapeString(cmntValue)) : string.Empty; sb.Append(FormatColumnStatement(cn, tn, nn, auto, dflt, chk, cmnt)); } #endregion firstColumn = false; foreach (var colSubNode in columnNode.Children) { if (colSubNode.IsSameName(PRIMARY_KEY_SECTION) || colSubNode.IsSameName(REFERENCE_SECTION)) { var keyType = colSubNode.IsSameName(PRIMARY_KEY_SECTION) ? RDBMSEntityType.PrimaryKey : RDBMSEntityType.Reference; var keyName = colSubNode.Value; if (keyName.IsNullOrWhiteSpace()) { keyName = column.OriginalShortName; } var key = new RDBMSEntity(column, colSubNode, keyType, keyName, colSubNode.AttrByName(SHORT_NAME_ATTR).Value); TransformEntityName(key); } else if (colSubNode.IsSameName(TYPE_ATTR)) { } //type may be used as section as well else { m_CompileErrors.Add(new SchemaCompilationException(colSubNode.RootPath, "Unrecognized item inside '{0}.{1}' column, section '{2}'" .Args(table.OriginalName, columnName, colSubNode.Name))); } } }
/// <summary> /// Override to compile a indexes per table /// </summary> protected virtual void DoTableIndexes(RDBMSEntity table, Outputs outputs) { var sb = m_SeparateIndexes ? outputs[RDBMSCompiler.INDEXES_OUTPUT] : outputs[RDBMSCompiler.TABLES_OUTPUT]; var indexes = table.Children.Where(c => c.EntityType == RDBMSEntityType.Index); foreach (var idx in indexes) { var node = (IConfigSectionNode)idx.SourceNode; var unique = node.AttrByName(UNIQUE_ATTR).ValueAsBool(); var colNames = new List <string>(); foreach (var col in node.Children.Where(c => c.IsSameName(COLUMN_SECTION))) { var cn = col.Value; var column = table.Children.FirstOrDefault(c => c.EntityType == RDBMSEntityType.Column && c.OriginalName.Equals(cn, NameComparison)); if (column == null) { m_CompileErrors.Add(new SchemaCompilationException(table.SourceNode.RootPath, "Table '{0}' defines index '{1}' which references column by name '{2}' which does not exist" .Args(table.OriginalName, idx.OriginalName, cn))); return; } var colName = GetQuotedIdentifierName(RDBMSEntityType.Column, column.TransformedName); var colLen = col.AttrByName(LENGTH_ATTR).ValueAsInt(); if (colLen > 0) { colName += "({0})".Args(colLen); } var colOrder = col.AttrByName(ORDER_ATTR).ValueAsEnum <RDBMSSortOrder>(); var ord = TransformSortOrder(colOrder); if (ord.IsNotNullOrWhiteSpace()) { colName = "{0} {1}".Args(colName, ord); } colNames.Add(colName); } var colNamesLine = string.Join(", ", colNames); var comment = node.AttrByName(COMMENT_ATTR).Value; var commentClause = comment.IsNullOrWhiteSpace()? string.Empty : TransformKeywordCase(" comment {0}").Args(EscapeString(comment)); sb.AppendLine(GetStatementDelimiterScript(RDBMSEntityType.Index, true)); sb.Append(TransformKeywordCase(" create {0} index {1} on {2}({3}){4}") .Args( TransformKeywordCase(unique?"unique":string.Empty), GetQuotedIdentifierName(RDBMSEntityType.Index, idx.TransformedName), GetQuotedIdentifierName(RDBMSEntityType.Table, table.TransformedName), colNamesLine, commentClause ) ); sb.AppendLine(GetStatementDelimiterScript(RDBMSEntityType.Index, false)); } }
/// <summary> /// Override to compile a RDBMS Table /// </summary> protected virtual void DoTable(IConfigSectionNode tableNode, Outputs outputs) { var tname = tableNode.Value; if (tname.IsNullOrWhiteSpace()) { m_CompileErrors.Add(new SchemaCompilationException(tableNode.RootPath, "Table name missing")); return; } var table = new RDBMSEntity(m_All, tableNode, RDBMSEntityType.Table, tname, tableNode.AttrByName(SHORT_NAME_ATTR).Value); TransformEntityName(table); var sb = outputs[RDBMSCompiler.TABLES_OUTPUT]; sb.AppendLine(GetStatementDelimiterScript(RDBMSEntityType.Table, true)); sb.AppendLine("-- {0}".Args(tableNode.AttrByName(SCRIPT_COMMENT_ATTR).ValueAsString("Table " + table.TransformedName))); sb.AppendLine("{0} {1}".Args(TransformKeywordCase("create table"), GetQuotedIdentifierName(RDBMSEntityType.Table, table.TransformedName))); sb.AppendLine("("); var firstItem = true; foreach (var node in tableNode.Children) { if (node.IsSameName(COLUMN_SECTION)) { DoColumn(node, table, sb, ref firstItem, outputs); } else if (node.IsSameName(PRIMARY_KEY_SECTION)) { DoReadPrimaryKeySection(node, table); } else if (node.IsSameName(INDEX_SECTION)) { DoReadIndexSection(node, table); } else if (node.IsSameName(SCRIPT_INCLUDE_SECTION)) { IncludeScriptFile(node, outputs); sb.AppendLine(); } else if (node.IsSameName(SCRIPT_TEXT_SECTION)) { IncludeScriptText(node, outputs); sb.AppendLine(); } else { m_CompileErrors.Add(new SchemaCompilationException(node.RootPath, "Unrecognized item inside '{0}' table section '{1}'".Args(tname, node.Name))); } } DoPrimaryKeys(table, sb, ref firstItem); DoForeignKeys(table, sb, ref firstItem, outputs); sb.AppendLine(); sb.AppendLine(")"); var comment = tableNode.AttrByName(COMMENT_ATTR).Value; if (comment.IsNotNullOrWhiteSpace()) { sb.AppendLine(" {0} = {1}".Args(TransformKeywordCase("comment"), EscapeString(comment))); } sb.AppendLine(GetStatementDelimiterScript(RDBMSEntityType.Table, false)); sb.AppendLine(); DoTableIndexes(table, outputs); }
public virtual string GetColumnNullNotNullClause(RDBMSEntity column, bool required) { return(required ? "not null" : string.Empty); }