protected override IRuleMessage BuildMessage(Option <Identifier> foreignKeyName, Identifier childTableName) { if (childTableName == null) { throw new ArgumentNullException(nameof(childTableName)); } var builder = StringBuilderCache.Acquire(); builder.Append("A foreign key"); foreignKeyName.IfSome(fkName => { builder.Append(" <code>") .Append(HttpUtility.HtmlEncode(fkName.LocalName)) .Append("</code>"); }); var childTableUrl = UrlRouter.GetTableUrl(childTableName); var childTableLink = $"<a href=\"{ childTableUrl }\">{ HttpUtility.HtmlEncode(childTableName.ToVisibleName()) }</a>"; builder.Append(" on ") .Append(childTableLink) .Append(" contains the same column set as the target key."); var message = builder.GetStringAndRelease(); return(new RuleMessage(RuleId, RuleTitle, Level, message)); }
private Option <Uri> GetSynonymTargetUrl(Identifier identifier, SynonymTargets targets) { if (targets.Tables.ContainsKey(identifier)) { return(new Uri(UrlRouter.GetTableUrl(identifier), UriKind.Relative)); } if (targets.Views.ContainsKey(identifier)) { return(new Uri(UrlRouter.GetViewUrl(identifier), UriKind.Relative)); } if (targets.Sequences.ContainsKey(identifier)) { return(new Uri(UrlRouter.GetSequenceUrl(identifier), UriKind.Relative)); } if (targets.Synonyms.ContainsKey(identifier)) { return(new Uri(UrlRouter.GetSynonymUrl(identifier), UriKind.Relative)); } if (targets.Routines.ContainsKey(identifier)) { return(new Uri(UrlRouter.GetRoutineUrl(identifier), UriKind.Relative)); } return(Option <Uri> .None); }
public TableColumn( Identifier tableName, int ordinalPosition, string columnName, string typeDefinition, bool isNullable, Option <string> defaultValue, bool isPrimaryKeyColumn, bool isUniqueKeyColumn, bool isForeignKeyColumn ) : base( tableName, ordinalPosition, columnName, typeDefinition, isNullable, defaultValue ) { TableUrl = UrlRouter.GetTableUrl(tableName); var isKey = isPrimaryKeyColumn || isUniqueKeyColumn || isForeignKeyColumn; ColumnClass = isKey ? @"class=""is-key-column""" : string.Empty; ColumnIcon = BuildColumnIcon(isPrimaryKeyColumn, isUniqueKeyColumn, isForeignKeyColumn); ColumnTitle = BuildColumnTitle(isPrimaryKeyColumn, isUniqueKeyColumn, isForeignKeyColumn); }
public Sequence( Identifier sequenceName, decimal start, decimal increment, Option <decimal> minValue, Option <decimal> maxValue, int cache, bool cycle ) { if (sequenceName == null) { throw new ArgumentNullException(nameof(sequenceName)); } Name = sequenceName.ToVisibleName(); SequenceUrl = UrlRouter.GetSequenceUrl(sequenceName); Start = start; Increment = increment; MinValueText = minValue.Match(mv => mv.ToString(), () => string.Empty); MaxValueText = maxValue.Match(mv => mv.ToString(), () => string.Empty); Cache = cache; CycleText = cycle ? "✓" : "✗"; }
public ChildKey(string constraintName, Identifier childTableName, string childColumnName, string qualifiedParentColumnName, string rootPath) { if (childTableName == null) { throw new ArgumentNullException(nameof(childTableName)); } if (childColumnName.IsNullOrWhiteSpace()) { throw new ArgumentNullException(nameof(childColumnName)); } if (qualifiedParentColumnName.IsNullOrWhiteSpace()) { throw new ArgumentNullException(nameof(qualifiedParentColumnName)); } if (rootPath == null) { throw new ArgumentNullException(nameof(rootPath)); } ChildTableName = childTableName.ToVisibleName(); ChildTableUrl = rootPath + UrlRouter.GetTableUrl(childTableName); ChildColumnName = childColumnName; var qualifiedChildColumnName = ChildTableName + "." + ChildColumnName; var description = qualifiedChildColumnName + " references " + qualifiedParentColumnName; if (!constraintName.IsNullOrWhiteSpace()) { description += " via " + constraintName; } ConstraintDescription = description; }
protected override IRuleMessage BuildMessage(string columnName, Identifier tableName, Identifier targetTableName) { if (columnName.IsNullOrWhiteSpace()) { throw new ArgumentNullException(nameof(columnName)); } if (tableName == null) { throw new ArgumentNullException(nameof(tableName)); } if (targetTableName == null) { throw new ArgumentNullException(nameof(targetTableName)); } var builder = StringBuilderCache.Acquire(); var tableUrl = UrlRouter.GetTableUrl(tableName); var tableLink = $"<a href=\"{ tableUrl }\">{ HttpUtility.HtmlEncode(tableName.ToVisibleName()) }</a>"; var targetTableUrl = UrlRouter.GetTableUrl(targetTableName); var targetTableLink = $"<a href=\"{ targetTableUrl }\">{ HttpUtility.HtmlEncode(targetTableName.ToVisibleName()) }</a>"; builder.Append("The table ") .Append(tableLink) .Append(" has a column <code>") .Append(columnName) .Append("</code> implying a relationship to ") .Append(targetTableLink) .Append(" which is missing a foreign key constraint."); var messageText = builder.GetStringAndRelease(); return(new RuleMessage(RuleId, RuleTitle, Level, messageText)); }
public Routine(Identifier routineName) { if (routineName == null) { throw new ArgumentNullException(nameof(routineName)); } Name = routineName.ToVisibleName(); RoutineUrl = UrlRouter.GetRoutineUrl(routineName); }
protected TableConstraint(Identifier tableName, string constraintName) { if (tableName == null) { throw new ArgumentNullException(nameof(tableName)); } TableName = tableName.ToVisibleName(); TableUrl = UrlRouter.GetTableUrl(tableName); ConstraintName = constraintName ?? string.Empty; }
public Table(Identifier tableName, uint columnCount, ulong rowCount) { if (tableName == null) { throw new ArgumentNullException(nameof(tableName)); } Name = tableName.ToVisibleName(); TableUrl = UrlRouter.GetTableUrl(tableName); ColumnCount = columnCount; RowCount = rowCount; }
private IReadOnlyCollection <Link> GetReferenceTargetLinks(string rootPath, Identifier objectName, Identifier referenceName) { if (rootPath == null) { throw new ArgumentNullException(nameof(rootPath)); } if (objectName == null) { throw new ArgumentNullException(nameof(objectName)); } if (referenceName == null) { throw new ArgumentNullException(nameof(referenceName)); } var qualifiedReference = QualifyReferenceName(objectName, referenceName); var isSelfReference = string.Equals(objectName.Schema, qualifiedReference.Schema, StringComparison.OrdinalIgnoreCase) && string.Equals(objectName.LocalName, qualifiedReference.LocalName, StringComparison.OrdinalIgnoreCase); if (isSelfReference) { return(Array.Empty <Link>()); } var result = new List <Link>(); var matchingTables = GetMatchingObjects(TableNames, qualifiedReference) .Select(name => new Link(name, new Uri(rootPath + UrlRouter.GetTableUrl(name), UriKind.Relative))); result.AddRange(matchingTables); var matchingViews = GetMatchingObjects(ViewNames, qualifiedReference) .Select(name => new Link(name, new Uri(rootPath + UrlRouter.GetViewUrl(name), UriKind.Relative))); result.AddRange(matchingViews); var matchingSequences = GetMatchingObjects(SequenceNames, qualifiedReference) .Select(name => new Link(name, new Uri(rootPath + UrlRouter.GetSequenceUrl(name), UriKind.Relative))); result.AddRange(matchingSequences); var matchingSynonyms = GetMatchingObjects(SynonymNames, qualifiedReference) .Select(name => new Link(name, new Uri(rootPath + UrlRouter.GetSynonymUrl(name), UriKind.Relative))); result.AddRange(matchingSynonyms); var matchingRoutines = GetMatchingObjects(RoutineNames, qualifiedReference) .Select(name => new Link(name, new Uri(rootPath + UrlRouter.GetRoutineUrl(name), UriKind.Relative))); result.AddRange(matchingRoutines); return(result); }
public View(Identifier viewName, uint columnCount, bool isMaterialized) { if (viewName == null) { throw new ArgumentNullException(nameof(viewName)); } Name = viewName.ToVisibleName(); ViewUrl = UrlRouter.GetViewUrl(viewName); ColumnCount = columnCount; MaterializedText = isMaterialized ? "✓" : "✗"; }
protected override IRuleMessage BuildMessage(Identifier tableName, int columnCount) { if (tableName == null) { throw new ArgumentNullException(nameof(tableName)); } var tableUrl = UrlRouter.GetTableUrl(tableName); var tableLink = $"<a href=\"{ tableUrl }\">{ HttpUtility.HtmlEncode(tableName.ToVisibleName()) }</a>"; var messageText = $"The table { tableLink } has too many columns. It has { columnCount } columns."; return(new RuleMessage(RuleId, RuleTitle, Level, messageText)); }
protected override IRuleMessage BuildMessage(Identifier tableName) { if (tableName == null) { throw new ArgumentNullException(nameof(tableName)); } var tableUrl = UrlRouter.GetTableUrl(tableName); var tableLink = $"<a href=\"{ tableUrl }\">{ HttpUtility.HtmlEncode(tableName.ToVisibleName()) }</a>"; var messageText = $"The table { tableLink } has a multi-column primary key. Consider introducing a surrogate primary key."; return(new RuleMessage(RuleId, RuleTitle, Level, messageText)); }
protected override IRuleMessage BuildDisabledUniqueKeyMessage(Identifier tableName, Option <Identifier> uniqueKeyName) { var messageKeyName = uniqueKeyName.Match( name => " <code>" + HttpUtility.HtmlEncode(name.LocalName) + "</code>", () => string.Empty ); var tableUrl = UrlRouter.GetTableUrl(tableName); var tableLink = $"<a href=\"{ tableUrl }\">{ HttpUtility.HtmlEncode(tableName.ToVisibleName()) }</a>"; var messageText = $"The table { tableLink } contains a disabled unique key{ messageKeyName }. Consider enabling or removing the unique key."; return(new RuleMessage(RuleId, RuleTitle, Level, messageText)); }
protected override IRuleMessage BuildMessage(Identifier tableName) { if (tableName == null) { throw new ArgumentNullException(nameof(tableName)); } var tableUrl = UrlRouter.GetTableUrl(tableName); var tableLink = $"<a href=\"{ tableUrl }\">{ HttpUtility.HtmlEncode(tableName.ToVisibleName()) }</a>"; var messageText = $"The table { tableLink } has a primary key whose column is not the first column in the table."; return(new RuleMessage(RuleId, RuleTitle, Level, messageText)); }
protected override IRuleMessage BuildMessage(Identifier tableName) { if (tableName == null) { throw new ArgumentNullException(nameof(tableName)); } var tableUrl = UrlRouter.GetTableUrl(tableName); var tableLink = $"<a href=\"{ tableUrl }\">{ HttpUtility.HtmlEncode(tableName.ToVisibleName()) }</a>"; var messageText = $"The table { tableLink } has no candidate (primary or unique) keys. Consider adding one to ensure records are unique."; return(new RuleMessage(RuleId, RuleTitle, Level, messageText)); }
protected override IRuleMessage BuildSequenceMessage(Identifier sequenceName) { if (sequenceName == null) { throw new ArgumentNullException(nameof(sequenceName)); } var sequenceUrl = UrlRouter.GetSequenceUrl(sequenceName); var sequenceLink = $"<a href=\"{ sequenceUrl }\">{ HttpUtility.HtmlEncode(sequenceName.ToVisibleName()) }</a>"; var messageText = $"The sequence { sequenceLink } is also a database keyword and may require quoting to be used. Consider renaming to a non-keyword name."; return(new RuleMessage(RuleId, RuleTitle, Level, messageText)); }
protected override IRuleMessage BuildMessage(Identifier tableName) { if (tableName == null) { throw new ArgumentNullException(nameof(tableName)); } var tableUrl = UrlRouter.GetTableUrl(tableName); var tableLink = $"<a href=\"{ tableUrl }\">{ HttpUtility.HtmlEncode(tableName.ToVisibleName()) }</a>"; var messageText = $"The table { tableLink } has no not-nullable columns present. Consider adding one to ensure that each record contains data."; return(new RuleMessage(RuleId, RuleTitle, Level, messageText)); }
protected override IRuleMessage BuildMessage(Identifier tableName) { if (tableName == null) { throw new ArgumentNullException(nameof(tableName)); } var tableUrl = UrlRouter.GetTableUrl(tableName); var tableLink = $"<a href=\"{ tableUrl }\">{ HttpUtility.HtmlEncode(tableName.ToVisibleName()) }</a>"; var messageText = $"The table { tableLink } is not related to any other table. Consider adding relations or removing the table."; return(new RuleMessage(RuleId, RuleTitle, Level, messageText)); }
protected override IRuleMessage BuildMessage(Identifier viewName) { if (viewName == null) { throw new ArgumentNullException(nameof(viewName)); } var viewUrl = UrlRouter.GetViewUrl(viewName); var viewLink = $"<a href=\"{ viewUrl }\">{ HttpUtility.HtmlEncode(viewName.ToVisibleName()) }</a>"; var messageText = $"The view { viewLink } was unable to be queried. This may indicate an incorrect view definition."; return(new RuleMessage(RuleId, RuleTitle, Level, messageText)); }
protected override IRuleMessage BuildMessage(Identifier tableName) { if (tableName == null) { throw new ArgumentNullException(nameof(tableName)); } var tableUrl = UrlRouter.GetTableUrl(tableName); var tableLink = $"<a href=\"{ tableUrl }\">{ HttpUtility.HtmlEncode(tableName.ToVisibleName()) }</a>"; var messageText = $"The table { tableLink } does not have any indexes present, requiring table scans to access records. Consider introducing an index or a primary key or a unique key constraint."; return(new RuleMessage(RuleId, RuleTitle, Level, messageText)); }
protected override IRuleMessage BuildSynonymMessage(Identifier synonymName) { if (synonymName == null) { throw new ArgumentNullException(nameof(synonymName)); } var synonymUrl = UrlRouter.GetSynonymUrl(synonymName); var synonymLink = $"<a href=\"{ synonymUrl }\">{ HttpUtility.HtmlEncode(synonymName.ToVisibleName()) }</a>"; var messageText = $"The synonym { synonymLink } contains whitespace and requires quoting to be used. Consider renaming to remove any whitespace."; return(new RuleMessage(RuleId, RuleTitle, Level, messageText)); }
protected override IRuleMessage BuildMessage(Identifier tableName, string indexName, IEnumerable <string> redundantIndexColumnNames, string otherIndexName, IEnumerable <string> otherIndexColumnNames) { if (tableName == null) { throw new ArgumentNullException(nameof(tableName)); } if (indexName.IsNullOrWhiteSpace()) { throw new ArgumentNullException(nameof(indexName)); } if (redundantIndexColumnNames == null || redundantIndexColumnNames.Empty()) { throw new ArgumentNullException(nameof(redundantIndexColumnNames)); } if (otherIndexName.IsNullOrWhiteSpace()) { throw new ArgumentNullException(nameof(otherIndexName)); } if (otherIndexColumnNames == null || otherIndexColumnNames.Empty()) { throw new ArgumentNullException(nameof(otherIndexColumnNames)); } var tableUrl = UrlRouter.GetTableUrl(tableName); var tableLink = $"<a href=\"{ tableUrl }\">{ HttpUtility.HtmlEncode(tableName.ToVisibleName()) }</a>"; var columnNames = redundantIndexColumnNames .Select(columnName => "<code>" + HttpUtility.HtmlEncode(columnName) + "</code>"); var otherColumnNames = otherIndexColumnNames .Select(columnName => "<code>" + HttpUtility.HtmlEncode(columnName) + "</code>"); var builder = StringBuilderCache.Acquire(); builder.Append("The table ") .Append(tableLink) .Append(" has an index <code>") .Append(HttpUtility.HtmlEncode(indexName)) .Append("</code> which may be redundant, as its column set (") .AppendJoin(", ", columnNames) .Append(") is the prefix of another index <code>") .Append(HttpUtility.HtmlEncode(otherIndexName)) .Append("</code> (") .AppendJoin(", ", otherColumnNames) .Append(")."); var messageText = builder.GetStringAndRelease(); return(new RuleMessage(RuleId, RuleTitle, Level, messageText)); }
protected override IRuleMessage BuildTableColumnMessage(Identifier tableName, string columnName) { if (tableName == null) { throw new ArgumentNullException(nameof(tableName)); } if (columnName.IsNullOrWhiteSpace()) { throw new ArgumentNullException(nameof(columnName)); } var tableUrl = UrlRouter.GetTableUrl(tableName); var tableLink = $"<a href=\"{ tableUrl }\">{ HttpUtility.HtmlEncode(tableName.ToVisibleName()) }</a>"; var messageText = $"The table { tableLink } contains a column <code>{ HttpUtility.HtmlEncode(columnName) }</code> which is also a database keyword and may require quoting to be used. Consider renaming to a non-keyword name."; return(new RuleMessage(RuleId, RuleTitle, Level, messageText)); }
protected override IRuleMessage BuildMessage(Identifier tableName, string columnName) { if (tableName == null) { throw new ArgumentNullException(nameof(tableName)); } if (columnName.IsNullOrWhiteSpace()) { throw new ArgumentNullException(nameof(columnName)); } var tableUrl = UrlRouter.GetTableUrl(tableName); var tableLink = $"<a href=\"{ tableUrl }\">{ HttpUtility.HtmlEncode(tableName.ToVisibleName()) }</a>"; var messageText = $"The table { tableLink } has a column <code>{ HttpUtility.HtmlEncode(columnName) }</code> with a numeric suffix, indicating denormalization."; return(new RuleMessage(RuleId, RuleTitle, Level, messageText)); }
protected override IRuleMessage BuildViewColumnMessage(Identifier viewName, string columnName) { if (viewName == null) { throw new ArgumentNullException(nameof(viewName)); } if (columnName.IsNullOrWhiteSpace()) { throw new ArgumentNullException(nameof(columnName)); } var viewUrl = UrlRouter.GetViewUrl(viewName); var viewLink = $"<a href=\"{ viewUrl }\">{ HttpUtility.HtmlEncode(viewName.ToVisibleName()) }</a>"; var messageText = $"The view { viewLink } contains a column <code>{ HttpUtility.HtmlEncode(columnName) }</code> which contains whitespace and requires quoting to be used. Consider renaming to remove any whitespace."; return(new RuleMessage(RuleId, RuleTitle, Level, messageText)); }
protected override IRuleMessage BuildMessage(Identifier tableName, string columnName) { if (tableName == null) { throw new ArgumentNullException(nameof(tableName)); } if (columnName.IsNullOrWhiteSpace()) { throw new ArgumentNullException(nameof(columnName)); } var tableUrl = UrlRouter.GetTableUrl(tableName); var tableLink = $"<a href=\"{ tableUrl }\">{ HttpUtility.HtmlEncode(tableName.ToVisibleName()) }</a>"; var messageText = $"The table { tableLink } has a column <code>{ HttpUtility.HtmlEncode(columnName) }</code> whose default value is <code>NULL</code>. Consider removing the default value on the column."; return(new RuleMessage(RuleId, RuleTitle, Level, messageText)); }
public ViewColumn( Identifier viewName, int ordinalPosition, string columnName, string typeDefinition, bool isNullable ) : base( viewName, ordinalPosition, columnName, typeDefinition, isNullable, string.Empty ) { TableUrl = UrlRouter.GetViewUrl(viewName); }
protected override IRuleMessage BuildDisabledTriggerMessage(Identifier tableName, string?triggerName) { if (tableName == null) { throw new ArgumentNullException(nameof(tableName)); } var messageTriggerName = !triggerName.IsNullOrWhiteSpace() ? " <code>" + HttpUtility.HtmlEncode(triggerName) + "</code>" : string.Empty; var tableUrl = UrlRouter.GetTableUrl(tableName); var tableLink = $"<a href=\"{ tableUrl }\">{ HttpUtility.HtmlEncode(tableName.ToVisibleName()) }</a>"; var messageText = $"The table { tableLink } contains a disabled trigger{ messageTriggerName }. Consider enabling or removing the trigger."; return(new RuleMessage(RuleId, RuleTitle, Level, messageText)); }
public ForeignKey( string constraintName, IEnumerable <string> columnNames, Identifier parentTableName, string parentConstraintName, IEnumerable <string> parentColumnNames, ReferentialAction deleteAction, ReferentialAction updateAction, string rootPath ) : base(constraintName) { if (columnNames == null || columnNames.Empty()) { throw new ArgumentNullException(nameof(columnNames)); } if (parentTableName == null) { throw new ArgumentNullException(nameof(parentTableName)); } if (parentColumnNames == null || parentColumnNames.Empty()) { throw new ArgumentNullException(nameof(parentColumnNames)); } if (!deleteAction.IsValid()) { throw new ArgumentException($"The { nameof(ReferentialAction) } provided must be a valid enum.", nameof(deleteAction)); } if (!updateAction.IsValid()) { throw new ArgumentException($"The { nameof(ReferentialAction) } provided must be a valid enum.", nameof(updateAction)); } if (rootPath == null) { throw new ArgumentNullException(nameof(rootPath)); } ChildColumnNames = columnNames.Join(", "); ParentConstraintName = parentConstraintName; ParentTableName = parentTableName.ToVisibleName(); ParentTableUrl = rootPath + UrlRouter.GetTableUrl(parentTableName); ParentColumnNames = parentColumnNames.Join(", "); DeleteActionDescription = _actionDescription[deleteAction]; UpdateActionDescription = _actionDescription[updateAction]; }