/// <summary>
        /// Gets the <see cref="ClusterSymbol"/> that contains the <see cref="DatabaseSymbol"/>.
        /// </summary>
        public ClusterSymbol GetCluster(DatabaseSymbol database)
        {
            if (database == null)
            {
                return(null);
            }

            if (this.reverseClusterMap == null)
            {
                var map = new Dictionary <Symbol, ClusterSymbol>();

                foreach (var cluster in this.Clusters)
                {
                    foreach (var member in cluster.Members)
                    {
                        map[member] = cluster;
                    }
                }

                Interlocked.CompareExchange(ref this.reverseClusterMap, map, null);
            }

            this.reverseClusterMap.TryGetValue(database, out var result);
            return(result);
        }
 private GlobalState(
     IReadOnlyList <ClusterSymbol> clusters,
     ClusterSymbol cluster,
     DatabaseSymbol database,
     IReadOnlyList <FunctionSymbol> functions,
     Dictionary <string, FunctionSymbol> functionMap,
     IReadOnlyList <FunctionSymbol> aggregates,
     Dictionary <string, FunctionSymbol> aggregateMap,
     IReadOnlyList <FunctionSymbol> plugins,
     Dictionary <string, FunctionSymbol> pluginMap,
     IReadOnlyList <OperatorSymbol> operators,
     Dictionary <OperatorKind, OperatorSymbol> operatorMap,
     IReadOnlyList <CommandSymbol> commands,
     Dictionary <string, CommandSymbol> commandMap,
     Dictionary <string, IReadOnlyList <CommandSymbol> > commandListMap,
     IReadOnlyList <ParameterSymbol> parameters,
     IReadOnlyList <OptionSymbol> options)
 {
     this.Clusters       = clusters;
     this.Cluster        = cluster ?? new ClusterSymbol("", databases: null, isOpen: true);
     this.Database       = database ?? new DatabaseSymbol("", members: null, isOpen: true);
     this.Functions      = functions;
     this.Aggregates     = aggregates;
     this.PlugIns        = plugins;
     this.Operators      = operators;
     this.Commands       = commands;
     this.commandMap     = commandMap;
     this.commandListMap = commandListMap;
     this.Parameters     = parameters.ToReadOnly();
     this.Options        = options;
 }
        /// <summary>
        /// Constructs a new <see cref="GlobalState"/> with the specified default database.
        /// </summary>
        public GlobalState WithDatabase(DatabaseSymbol database)
        {
            database = database ?? DatabaseSymbol.Unknown;

            if (this.Database == database)
            {
                return(this);
            }
            else if (database == DatabaseSymbol.Unknown ||
                     this.Cluster.Databases.Contains(database))
            {
                // same cluster, just change database
                return(With(database: database));
            }
            else
            {
                // check if it is a database of some other known cluster
                var knownCluster = GetCluster(database);
                if (knownCluster != null)
                {
                    // changing the current database changes the current cluster too
                    return(With(cluster: knownCluster, database: database));
                }
                else
                {
                    // the database must be part of a known cluster, so add a cluster for it to be part of
                    var cluster = new ClusterSymbol(database.Name + ":cluster", database);
                    return(WithCluster(cluster).WithDatabase(database));
                }
            }
        }
 private GlobalState(
     IReadOnlyList <ClusterSymbol> clusters,
     ClusterSymbol cluster,
     DatabaseSymbol database,
     IReadOnlyList <FunctionSymbol> functions,
     Dictionary <string, FunctionSymbol> functionMap,
     IReadOnlyList <FunctionSymbol> aggregates,
     Dictionary <string, FunctionSymbol> aggregateMap,
     IReadOnlyList <FunctionSymbol> plugins,
     Dictionary <string, FunctionSymbol> pluginMap,
     IReadOnlyList <OperatorSymbol> operators,
     Dictionary <OperatorKind, OperatorSymbol> operatorMap,
     IReadOnlyList <CommandSymbol> commands,
     Dictionary <string, CommandSymbol> commandMap,
     Dictionary <string, IReadOnlyList <CommandSymbol> > commandListMap,
     IReadOnlyList <ParameterSymbol> parameters,
     IReadOnlyList <OptionSymbol> options)
 {
     this.Clusters       = clusters ?? EmptyReadOnlyList <ClusterSymbol> .Instance;
     this.Cluster        = cluster ?? ClusterSymbol.Unknown;
     this.Database       = database ?? DatabaseSymbol.Unknown;
     this.Functions      = functions ?? EmptyReadOnlyList <FunctionSymbol> .Instance;
     this.Aggregates     = aggregates ?? EmptyReadOnlyList <FunctionSymbol> .Instance;
     this.PlugIns        = plugins ?? EmptyReadOnlyList <FunctionSymbol> .Instance;
     this.Operators      = operators ?? EmptyReadOnlyList <OperatorSymbol> .Instance;
     this.Commands       = commands ?? EmptyReadOnlyList <CommandSymbol> .Instance;
     this.commandMap     = commandMap;
     this.commandListMap = commandListMap;
     this.Parameters     = parameters ?? EmptyReadOnlyList <ParameterSymbol> .Instance;
     this.Options        = options ?? EmptyReadOnlyList <OptionSymbol> .Instance;
 }
        /// <summary>
        /// Constructs a new <see cref="GlobalState"/> instance.
        /// </summary>
        private GlobalState(
            IReadOnlyList <ClusterSymbol> clusters,
            ClusterSymbol cluster,
            DatabaseSymbol database,
            IReadOnlyList <FunctionSymbol> functions,
            IReadOnlyList <FunctionSymbol> aggregates,
            IReadOnlyList <FunctionSymbol> plugins,
            IReadOnlyList <OperatorSymbol> operators,
            IReadOnlyList <CommandSymbol> commands,
            IReadOnlyList <ParameterSymbol> parameters,
            IReadOnlyList <OptionSymbol> options,
            KustoCache cache,
            Dictionary <Symbol, ClusterSymbol> reverseClusterMap,
            Dictionary <Symbol, DatabaseSymbol> reverseDatabaseMap,
            Dictionary <Symbol, TableSymbol> reverseTableMap,
            Dictionary <string, FunctionSymbol> functionsMap,
            Dictionary <string, FunctionSymbol> aggregatesMap,
            Dictionary <string, FunctionSymbol> pluginMap,
            Dictionary <OperatorKind, OperatorSymbol> operatorMap,
            Dictionary <string, CommandSymbol> commandMap,
            Dictionary <string, OptionSymbol> optionMap)
        {
            this.Clusters   = clusters ?? EmptyReadOnlyList <ClusterSymbol> .Instance;
            this.Cluster    = cluster ?? ClusterSymbol.Unknown;
            this.Database   = database ?? DatabaseSymbol.Unknown;
            this.Functions  = functions ?? EmptyReadOnlyList <FunctionSymbol> .Instance;
            this.Aggregates = aggregates ?? EmptyReadOnlyList <FunctionSymbol> .Instance;
            this.PlugIns    = plugins ?? EmptyReadOnlyList <FunctionSymbol> .Instance;
            this.Operators  = operators ?? EmptyReadOnlyList <OperatorSymbol> .Instance;
            this.Commands   = commands ?? EmptyReadOnlyList <CommandSymbol> .Instance;
            this.Parameters = parameters ?? EmptyReadOnlyList <ParameterSymbol> .Instance;
            this.Options    = options ?? EmptyReadOnlyList <OptionSymbol> .Instance;
            this.Cache      = cache != null?cache.WithGlobals(this) : null;

            this.reverseClusterMap  = reverseClusterMap;
            this.reverseDatabaseMap = reverseDatabaseMap;
            this.reverseTableMap    = reverseTableMap;
            this.functionsMap       = functionsMap;
            this.aggregatesMap      = aggregatesMap;
            this.pluginMap          = pluginMap;
            this.operatorMap        = operatorMap;
            this.commandMap         = commandMap;
            this.optionMap          = optionMap;
        }
 /// <summary>
 /// Constructs a new <see cref="GlobalState"/> with the specified default database.
 /// </summary>
 public GlobalState WithDatabase(DatabaseSymbol database)
 {
     if (this.Cluster != null && this.Cluster.Databases.Contains(database))
     {
         // same cluster, just change database
         return(With(database: database));
     }
     else
     {
         var existingCluster = GetCluster(database);
         if (existingCluster != null)
         {
             // changing the current database changes the current cluster too
             return(With(cluster: existingCluster, database: database));
         }
         else
         {
             // no existing cluster for this database, so make a new one
             var cluster = new ClusterSymbol(database.Name + ":cluster", database);
             return(WithCluster(cluster).With(database: database));
         }
     }
 }
Example #7
0
        /// <summary>
        /// Loads the schema for the specified database into a <see cref="DatabaseSymbol"/>.
        /// </summary>
        public async Task <DatabaseSymbol> LoadDatabaseAsync(string databaseName, string clusterName = null, bool throwOnError = false, CancellationToken cancellationToken = default)
        {
            var connection = GetClusterConnection(clusterName);

            var tables = await LoadTablesAsync(connection, databaseName, throwOnError, cancellationToken).ConfigureAwait(false);

            var externalTables = await LoadExternalTablesAsync(connection, databaseName, throwOnError, cancellationToken).ConfigureAwait(false);

            var materializedViews = await LoadMaterializedViewsAsync(connection, databaseName, throwOnError, cancellationToken).ConfigureAwait(false);

            var functions = await LoadFunctionsAsync(connection, databaseName, throwOnError, cancellationToken).ConfigureAwait(false);

            var members = new List <Symbol>();

            members.AddRange(tables);
            members.AddRange(externalTables);
            members.AddRange(materializedViews);
            members.AddRange(functions);

            var databaseSymbol = new DatabaseSymbol(databaseName, members);

            return(databaseSymbol);
        }
Example #8
0
        /// <summary>
        /// Create tools for the shape toolbox and sort them into custom categories
        /// </summary>
        private void CreateTools()
        {
            toolSetPresenter.ToolSetController.Clear();
            toolSetPresenter.ToolSetController.AddTool(new SelectionTool(), true);

            string         category      = "Database Entities";
            DatabaseSymbol databaseShape = (DatabaseSymbol)project.ShapeTypes["Database"].CreateInstance();

            databaseShape.Width          = 120;
            databaseShape.Height         = 120;
            databaseShape.FillStyle      = project.Design.FillStyles.Yellow;
            databaseShape.CharacterStyle = project.Design.CharacterStyles.Heading3;
            databaseShape.Text           = "Database";
            CreateTemplateAndTool("Database", category, databaseShape);

            EntitySymbol tableShape = (EntitySymbol)project.ShapeTypes["Entity"].CreateInstance();

            tableShape.Width                = 100;
            tableShape.Height               = 160;
            tableShape.FillStyle            = project.Design.FillStyles.Red;
            tableShape.CharacterStyle       = project.Design.CharacterStyles.Heading3;
            tableShape.ParagraphStyle       = project.Design.ParagraphStyles.Title;
            tableShape.ColumnCharacterStyle = project.Design.CharacterStyles.Caption;
            tableShape.ColumnParagraphStyle = project.Design.ParagraphStyles.Label;
            CreateTemplateAndTool("Entity", category, tableShape);

            RectangularLine line;
            ShapeType       relationShapeType = project.ShapeTypes["RectangularLine"];

            line           = (RectangularLine)relationShapeType.CreateInstance();
            line.LineStyle = project.Design.LineStyles.Thick;
            CreateTemplateAndTool("Relationship", category, line);

            line             = (RectangularLine)relationShapeType.CreateInstance();
            line.LineStyle   = project.Design.LineStyles.Thick;
            line.EndCapStyle = project.Design.CapStyles.ClosedArrow;
            CreateTemplateAndTool("1:n Relationship", category, line);

            line               = (RectangularLine)relationShapeType.CreateInstance();
            line.LineStyle     = project.Design.LineStyles.Thick;
            line.StartCapStyle = project.Design.CapStyles.ClosedArrow;
            line.EndCapStyle   = project.Design.CapStyles.ClosedArrow;
            CreateTemplateAndTool("n:m Relationship", category, line);

            CloudSymbol cloudShape = (CloudSymbol)project.ShapeTypes["Cloud"].CreateInstance();

            cloudShape.FillStyle      = project.Design.FillStyles.Blue;
            cloudShape.CharacterStyle = project.Design.CharacterStyles.Heading1;
            cloudShape.Width          = 300;
            cloudShape.Height         = 160;
            cloudShape.Text           = "WAN / LAN";
            CreateTemplateAndTool("Cloud", category, cloudShape);

            category = "Description";
            Text text = (Text)project.ShapeTypes["Text"].CreateInstance();

            text.CharacterStyle = project.Design.CharacterStyles.Normal;
            text.Width          = 100;
            CreateTemplateAndTool("Text", category, text);

            AnnotationSymbol annotationShape = (AnnotationSymbol)project.ShapeTypes["Annotation"].CreateInstance();

            annotationShape.FillStyle      = project.Design.FillStyles.White;
            annotationShape.CharacterStyle = project.Design.CharacterStyles.Caption;
            annotationShape.ParagraphStyle = project.Design.ParagraphStyles.Text;
            annotationShape.Width          = 120;
            annotationShape.Height         = 120;
            CreateTemplateAndTool("Annotation", category, annotationShape);

            category = "Miscellaneous";
            RoundedBox roundedRectangle = (RoundedBox)project.ShapeTypes["RoundedBox"].CreateInstance();

            roundedRectangle.FillStyle = project.Design.FillStyles.Green;
            roundedRectangle.Width     = 120;
            roundedRectangle.Height    = 80;
            CreateTemplateAndTool("Box", category, roundedRectangle);

            Ellipse ellipse = (Ellipse)project.ShapeTypes["Ellipse"].CreateInstance();

            ellipse.FillStyle = project.Design.FillStyles.Yellow;
            ellipse.Width     = 120;
            ellipse.Height    = 80;
            CreateTemplateAndTool("Ellipse", category, ellipse);

            Picture picture = (Picture)project.ShapeTypes["Picture"].CreateInstance();

            picture.FillStyle = project.Design.FillStyles.Transparent;
            picture.Width     = 120;
            picture.Height    = 120;
            CreateTemplateAndTool("Picture", category, picture);

            ShapeType   arcShapeType = project.ShapeTypes["CircularArc"];
            CircularArc arc;

            arc           = (CircularArc)arcShapeType.CreateInstance();
            arc.LineStyle = project.Design.LineStyles.Thick;
            CreateTemplateAndTool("Arc", category, arc);

            arc             = (CircularArc)arcShapeType.CreateInstance();
            arc.LineStyle   = project.Design.LineStyles.Thick;
            arc.EndCapStyle = project.Design.CapStyles.ClosedArrow;
            CreateTemplateAndTool("Bowed Arrow", category, arc);

            arc               = (CircularArc)arcShapeType.CreateInstance();
            arc.LineStyle     = project.Design.LineStyles.Thick;
            arc.StartCapStyle = project.Design.CapStyles.ClosedArrow;
            arc.EndCapStyle   = project.Design.CapStyles.ClosedArrow;
            CreateTemplateAndTool("Bowed Double Arrow", category, arc);
        }
        private void GetDatabaseReferences(SyntaxNode root, SyntaxNode location, ClusterSymbol defaultCluster, DatabaseSymbol defaultDatabase, List <DatabaseReference> refs, CancellationToken cancellationToken)
        {
            root.WalkElements(element =>
            {
                cancellationToken.ThrowIfCancellationRequested();

                if (element is FunctionCallExpression fc && fc.ReferencedSymbol is FunctionSymbol fs)
                {
                    if (fs == Functions.Database)
                    {
                        var dbref = GetDatabaseReference(fc, location, defaultCluster);
                        if (dbref != null)
                        {
                            refs.Add(dbref);
                        }
                    }
                    else if (fs.Signatures[0].HasDatabaseCall)
                    {
                        var expansion = fc.GetExpansion();
                        if (expansion != null)
                        {
                            var db      = defaultDatabase;
                            var cluster = defaultCluster;

                            db      = this.globals.GetDatabase(fs) ?? defaultDatabase;
                            cluster = this.globals.GetCluster(db) ?? defaultCluster;

                            GetDatabaseReferences(expansion, location ?? fc.Name, cluster, db, refs, cancellationToken);
                        }
                    }
                }
            });
        }