示例#1
0
 public TableNode(
     DotIdentifier identifier,
     string tableName,
     IEnumerable <string> columnNames,
     IEnumerable <string> columnTypes,
     IEnumerable <string> keyColumnNames,
     uint children,
     uint parents,
     ulong rows,
     IEnumerable <NodeAttribute> nodeAttrs,
     IEnumerable <TableConstraint> constraints,
     TableNodeOptions options
     )
     : base(identifier)
 {
     if (tableName.IsNullOrWhiteSpace())
     {
         throw new ArgumentNullException(nameof(tableName));
     }
     _tableName      = tableName;
     _columnNames    = columnNames?.ToList() ?? throw new ArgumentNullException(nameof(columnNames));
     _columnTypes    = columnTypes?.ToList() ?? throw new ArgumentNullException(nameof(columnTypes));
     _keyColumnNames = keyColumnNames?.ToList() ?? throw new ArgumentNullException(nameof(keyColumnNames));
     _children       = children;
     _parents        = parents;
     _rows           = rows;
     _nodeAttrs      = nodeAttrs ?? throw new ArgumentNullException(nameof(nodeAttrs));
     _constraints    = constraints ?? throw new ArgumentNullException(nameof(constraints));
     _options        = options ?? throw new ArgumentNullException(nameof(options));
 }
示例#2
0
        /// <summary>
        /// Renders the tables as a DOT graph.
        /// </summary>
        /// <param name="tables">The tables.</param>
        /// <param name="rowCounts">Row counts for each of the provided tables.</param>
        /// <param name="options">Options to configure how the DOT graph is rendered.</param>
        /// <returns>A string containing a dot representation of the table relationship graph.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="tables"/> or <paramref name="rowCounts"/> or <paramref name="options"/></exception>
        public string RenderTables(IEnumerable <IRelationalDatabaseTable> tables, IReadOnlyDictionary <Identifier, ulong> rowCounts, DotRenderOptions options)
        {
            if (tables == null)
            {
                throw new ArgumentNullException(nameof(tables));
            }
            if (rowCounts == null)
            {
                throw new ArgumentNullException(nameof(rowCounts));
            }
            if (options == null)
            {
                throw new ArgumentNullException(nameof(options));
            }

            var tableNames = tables.Select(t => t.Name).ToList();

            var tableNodes = new Dictionary <DotIdentifier, DotNode>();
            var edges      = new List <DotEdge>();

            foreach (var table in tables)
            {
                var tableIdentifier = table.Name.ToSafeKey();
                var tableName       = table.Name.ToVisibleName();
                var nodeIdentifier  = new DotIdentifier(tableIdentifier);

                var tableColumns = table.Columns;
                var columnNames  = tableColumns.Select(c => c.Name.LocalName).ToList();
                var columnTypes  = tableColumns.Select(c => c.Type.Definition).ToList();

                var primaryKey = table.PrimaryKey;
                var uniqueKeys = table.UniqueKeys;
                var childKeys  = table.ChildKeys;
                var parentKeys = table.ParentKeys;

                var keyColumnNames = uniqueKeys
                                     .Concat(parentKeys.Select(fk => fk.ChildKey))
                                     .Concat(primaryKey.Match(pk => new[] { pk }, Array.Empty <IDatabaseKey>))
                                     .SelectMany(key => key.Columns.Select(c => c.Name.LocalName))
                                     .Distinct()
                                     .ToList();

                var childKeysCount  = childKeys.ToList().UCount();
                var parentKeysCount = parentKeys.ToList().UCount();

                if (!rowCounts.TryGetValue(table.Name, out var rowCount))
                {
                    rowCount = 0;
                }

                var tableNodeAttrs   = new[] { NodeAttribute.Tooltip(tableName) };
                var tableNodeOptions = new TableNodeOptions
                {
                    IsReducedColumnSet = options.IsReducedColumnSet,
                    ShowColumnDataType = options.ShowColumnDataType,
                    IsHighlighted      = table.Name == options.HighlightedTable,
                    ShowRowCounts      = options.ShowRowCounts
                };

                var tableConstraints = new List <TableConstraint>();

                primaryKey.IfSome(pk =>
                {
                    var primaryKeyNameText = pk.Name.Match(
                        pkName => pkName.LocalName,
                        () => pk.GetKeyHash(table.Name).ToString()
                        );
                    var primaryKeyName = pk.Name.Match(pkName => pkName.LocalName, () => string.Empty);

                    var primaryKeyConstraint = new TableConstraint(
                        primaryKeyNameText,
                        pk.KeyType,
                        primaryKeyName,
                        pk.Columns.Select(c => c.Name.LocalName).ToList(),
                        pk.Columns.Select(c => c.Type.Definition).ToList()
                        );
                    tableConstraints.Add(primaryKeyConstraint);
                });

                foreach (var uniqueKey in uniqueKeys)
                {
                    var uniqueKeyNameText = uniqueKey.Name.Match(
                        ukName => ukName.LocalName,
                        () => uniqueKey.GetKeyHash(table.Name).ToString()
                        );
                    var uniqueKeyName = uniqueKey.Name.Match(pkName => pkName.LocalName, () => string.Empty);

                    var uniqueKeyConstraint = new TableConstraint(
                        uniqueKeyNameText,
                        uniqueKey.KeyType,
                        uniqueKeyName,
                        uniqueKey.Columns.Select(c => c.Name.LocalName).ToList(),
                        uniqueKey.Columns.Select(c => c.Type.Definition).ToList()
                        );
                    tableConstraints.Add(uniqueKeyConstraint);
                }

                foreach (var relationalKey in parentKeys)
                {
                    var childKey  = relationalKey.ChildKey;
                    var parentKey = relationalKey.ParentKey;

                    var hasParentKey = tableNames.Contains(relationalKey.ParentTable);
                    if (!hasParentKey)
                    {
                        continue;
                    }

                    var childKeyTableName = relationalKey.ChildTable.ToSafeKey();
                    var childKeyName      = childKey.Name.Match(
                        ckName => ckName.LocalName,
                        () => childKey.GetKeyHash(relationalKey.ChildTable).ToString()
                        );

                    var parentKeyTableName = relationalKey.ParentTable.ToSafeKey();
                    var parentKeyName      = parentKey.Name.Match(
                        fkName => fkName.LocalName,
                        () => parentKey.GetKeyHash(relationalKey.ParentTable).ToString()
                        );

                    var childKeyToParentKeyEdge = new DotEdge(
                        new DotIdentifier(childKeyTableName),
                        new DotIdentifier(childKeyName),
                        new DotIdentifier(parentKeyTableName),
                        new DotIdentifier(parentKeyName),
                        Array.Empty <EdgeAttribute>()
                        );
                    edges.Add(childKeyToParentKeyEdge);

                    var childKeyConstraintName = childKey.Name.Match(name => name.LocalName, () => string.Empty);
                    var tableConstraint        = new TableConstraint(
                        childKeyName,
                        childKey.KeyType,
                        childKeyConstraintName,
                        childKey.Columns.Select(c => c.Name.LocalName).ToList(),
                        childKey.Columns.Select(c => c.Type.Definition).ToList()
                        );
                    tableConstraints.Add(tableConstraint);
                }

                tableNodes[nodeIdentifier] = new TableNode(
                    nodeIdentifier,
                    tableName,
                    columnNames,
                    columnTypes,
                    keyColumnNames,
                    childKeysCount,
                    parentKeysCount,
                    rowCount,
                    tableNodeAttrs,
                    tableConstraints,
                    tableNodeOptions
                    );
            }

            var recordNodes = tableNodes.Values
                              .OrderBy(node => node.Identifier.ToString())
                              .ToList();

            var graphName = !IdentifierDefaults.Database.IsNullOrWhiteSpace()
                ? IdentifierDefaults.Database
                : "unnamed graph";
            var graphAttrs = _globalGraphAttrs.ToList();

            graphAttrs.Add(GraphAttribute.BackgroundColor(options.Theme.BackgroundColor));

            var graph = new DotGraph(
                new DotIdentifier(graphName),
                graphAttrs,
                _globalNodeAttrs,
                _globalEdgeAttrs,
                recordNodes,
                edges
                );

            return(graph.ToString());
        }