/// <summary>
        /// Extracts measure names from database object.
        /// </summary>
        /// <param name="tableName">Specifies a table that will limit measure names to that specific one.</param>
        /// <returns>Returns list of measure names specific to a table or all of them if tableName is empty.</returns>
        /// <exception cref="System.InvalidOperationException">Thrown when database object is null.</exception>
        public IEnumerable <string> GetMeasureNames(string tableName)
        {
            if (null == this._database)
            {
                throw new InvalidOperationException("Current database is NULL. GetMeasureNames function cannot be called when database object is NULL");
            }

            var measureNames = new List <string>();

            if (this._database.Cubes.Count > 0)
            {
                var cube = this._database.Cubes[0];
                if (cube.MdxScripts.Count > 0)
                {
                    var mdxScrit = cube.MdxScripts[0];
                    foreach (Command mdxCommand in mdxScrit.Commands)
                    {
                        if (!string.IsNullOrEmpty(mdxCommand.Text))
                        {
                            var measures = MeasuresContainer.ParseDaxScript(mdxCommand.Text).Measures;
                            if (string.IsNullOrEmpty(tableName))
                            {
                                measureNames.AddRange(measures.Select(i => i.TableName + i.Name));
                            }
                            else
                            {
                                measureNames.AddRange(measures.Where(i => string.Equals(i.TableName, tableName, StringComparison.CurrentCultureIgnoreCase)).Select(i => i.TableName + i.Name));
                            }
                        }
                    }
                }
            }

            return(measureNames);
        }
        internal string GetMeasuresText()
        {
            if (this._database == null)
            {
                if (_isConnecting)
                {
                    return("-- Reading metadata from the database.  Please retry operation later.");
                }

                return("-- Not connected to the database.");
            }

            var sb           = new StringBuilder();
            var restrictions = new AdomdRestrictionCollection();

            restrictions.Add("DatabaseID", _database.ID);
            var dataSet = _adomdConn.GetSchemaDataSet("DISCOVER_XML_METADATA", restrictions);

            Debug.Assert(dataSet.Tables.Count == 1);
            var table = dataSet.Tables[0];

            Debug.Assert(table.Columns.Count == 1);
            Debug.Assert(table.Rows.Count == 1);
            var script = table.Rows[0][0] as string;

            Debug.Assert(!string.IsNullOrEmpty(script));

            var mc = MeasuresContainer.ParseText(script);

            sb.Append(mc.GetDaxText());

            return(sb.ToString());
        }
        void BackgroundWorker_SaveMeasuresAndCalcColumns(object sender, DoWorkEventArgs e)
        {
            var cmdProducer = new ServerCommandProducer(_database.Name, _database.CompatibilityLevel, _database.Cubes[0].Name);

            try
            {
                var bw = sender as BackgroundWorker;
                bw.DoWork -= new DoWorkEventHandler(BackgroundWorker_SaveMeasuresAndCalcColumns);

                LogLine("Begin saving measures.");

                string viewText = e.Argument as string;
                var    mc       = MeasuresContainer.ParseDaxScript(viewText);

                LogLine("Begin transaction.");
                using (var cmd = new AdomdCommand("@CommandText", _adomdConn))
                {
                    cmd.Parameters.Add(new AdomdParameter("CommandText", cmdProducer.ProduceBeginTransaction()));
                    cmd.ExecuteNonQuery();
                }

                LogLine("Alter MDX script.");
                using (var cmd = new AdomdCommand("@CommandText", _adomdConn))
                {
                    cmd.Parameters.Add(new AdomdParameter("CommandText", cmdProducer.ProduceAlterMdxScript(mc.Measures)));
                    cmd.ExecuteNonQuery();
                }

                LogLine("Run ProcessRecalc.");
                using (var cmd = new AdomdCommand("@CommandText", _adomdConn))
                {
                    cmd.Parameters.Add(new AdomdParameter("CommandText", cmdProducer.ProduceProcessRecalc()));
                    cmd.ExecuteNonQuery();
                }


                LogLine("Commit transaction.");
                using (var cmd = new AdomdCommand("@CommandText", _adomdConn))
                {
                    cmd.Parameters.Add(new AdomdParameter("CommandText", cmdProducer.ProduceCommitTransaction()));
                    cmd.ExecuteNonQuery();
                }

                LogLine("End saving measures.");
            }
            catch (Exception ex)
            {
                using (var cmd = new AdomdCommand("@CommandText", _adomdConn))
                {
                    cmd.Parameters.Add(new AdomdParameter("CommandText", cmdProducer.ProduceRollbackTransaction()));
                    cmd.ExecuteNonQuery();
                }

                LogError("Error while saving measures. " + ex.ToString());
            }
        }
 /// <summary>
 /// Gets Measures section of BIM file
 /// </summary>
 internal static string GetMeasuresFromBimFile(string bimFilePath)
 {
     try
     {
         if (!File.Exists(bimFilePath))
         {
             throw new FileNotFoundException(string.Format("Model file {0} doesn't exist.", bimFilePath));
         }
         string bimScript = File.ReadAllText(bimFilePath);
         var    mc        = MeasuresContainer.ParseText(bimScript);
         return(mc.GetDaxText());
     }
     catch (Exception e)
     {
         throw new DaxException(string.Format("Error while reading measures from file '{0}'", bimFilePath), e);
     }
 }
        /// <summary>
        /// Saves DAX file to Measures section of BIM file
        /// </summary>
        internal static void SaveMeasuresToBimFile(string daxFilePath)
        {
            string daxFileContent = File.ReadAllText(daxFilePath);
            string customScript   = null;

            //TL: If DAX file includes custom MDX script, remove it to avoid interference with parser
            if (daxFileContent.Contains(BeginCustomScript))
            {
                // read custom script
                customScript = daxFileContent.Substring(daxFileContent.IndexOf(BeginCustomScript, StringComparison.InvariantCultureIgnoreCase), daxFileContent.IndexOf(EndCustomScript, EndCustomScript.Length, StringComparison.InvariantCultureIgnoreCase) + EndCustomScript.Length);
                // remove custom script
                daxFileContent = daxFileContent.Replace(customScript, String.Empty);
            }

            var    mc          = MeasuresContainer.ParseDaxScript(daxFileContent);
            string bimFilePath = ConvertDaxPathToBimPath(daxFilePath);

            if (!File.Exists(bimFilePath))
            {
                throw new FileNotFoundException(string.Format("Model file {0} doesn't exist", bimFilePath));
            }
            if (new FileInfo(bimFilePath).IsReadOnly)
            {
                throw new InvalidOperationException(string.Format("Model file {0} is read only", bimFilePath));
            }

            // TL -- injecting custom MDX script verbatum to the bim file
            if (!string.IsNullOrEmpty(customScript))
            {
                // insert customScript as first measure so it gets serialized first
                DaxMeasure m = new DaxMeasure();
                m.Name     = "CustomMDXScript";
                m.FullText = customScript;
                mc.Measures.Insert(0, m);
            }

            string bimScript     = System.IO.File.ReadAllText(bimFilePath);
            var    updatedScript = mc.UpdateMeasures(bimScript);

            File.WriteAllText(bimFilePath, updatedScript);
        }
Example #6
0
        public string ProduceAlterScriptElement(MeasuresContainer container)
        {
            var stream = new MemoryStream();
            var writer = new XmlTextWriter(stream, Encoding.UTF8);
            var obj    = container.ToMdxScript(_dbCompatibilityLevel);

            Utils.Serialize(writer, obj, true);
            stream.Position = 0;

            var text = new StreamReader(stream).ReadToEnd();

            //Delete default nodes
            var document = XDocument.Parse(text);

            document.Descendants(MeasuresContainer.NS + "CreatedTimestamp").Remove();
            document.Descendants(MeasuresContainer.NS + "LastSchemaUpdate").Remove();
            document.Descendants(MeasuresContainer.NS + "Value").Where(i => i.IsEmpty).Remove();
            document.Element(MeasuresContainer.NS + "MdxScript").RemoveAttributes();

            return(document.ToString(SaveOptions.OmitDuplicateNamespaces));
        }
        /// <summary>
        /// Constructs declarations cache based on database object
        /// </summary>
        private void ConstructSchemaBasedDeclarations()
        {
            LogLine("Begin constructing schema based declarations.");
            List <Declaration> tableDeclarations   = new List <Declaration>();
            List <Declaration> measureDeclarations = new List <Declaration>();
            Dictionary <string, List <Declaration> > tableMembersDeclarations = new Dictionary <string, List <Declaration> >();

            List <string> tableList   = new List <string>();
            List <string> columnList  = new List <string>();
            List <string> measureList = new List <string>();

            if (null == this._database)
            {
                ClearDeclarationsCache();
                LogLine("ERROR: Database is not defined.");
                return;
            }

            foreach (Microsoft.AnalysisServices.Dimension dim in _database.Dimensions)
            {
                // Set table declarations
                tableDeclarations.Add(new Babel.Declaration(dim.Description, dim.Name, Babel.LanguageService.TABLE_GLYPH_INDEX, dim.Name));
                tableList.AddRange(GenerateValidTableNames(dim.Name));

                // Obtain column declarations for current table
                List <Declaration> columnDeclarationsCurrentTable = new List <Declaration>();
                foreach (DimensionAttribute dimAttr in dim.Attributes)
                {
                    // Skip RowNumber columns
                    if (_rowNumberColumnNames.Any(i => { return(string.Equals(i, dimAttr.Name, StringComparison.CurrentCultureIgnoreCase)); }))
                    {
                        continue;
                    }

                    var columnShortName = "[" + dimAttr.Name + "]";

                    if (dimAttr.Source is ExpressionBinding)
                    {
                        // use calc column glyph
                        columnDeclarationsCurrentTable.Add(new Babel.Declaration(dimAttr.Description, dimAttr.Name, Babel.LanguageService.CALC_COLUMN_GLYPH_INDEX, columnShortName));
                    }
                    else
                    {
                        // use base column glyph
                        columnDeclarationsCurrentTable.Add(new Babel.Declaration(dimAttr.Description, dimAttr.Name, Babel.LanguageService.BASE_COLUMN_GLYPH_INDEX, columnShortName));
                    }

                    GenerateValidTableNames(dim.Name).ForEach(i => columnList.Add(string.Format("{0}{1}", i, columnShortName)));
                }

                tableMembersDeclarations.Add(dim.Name, columnDeclarationsCurrentTable);
            }

            // Obtain measure declarations and distribute them in table member declarations
            if (this._database.Cubes.Count > 0)
            {
                var cube = this._database.Cubes[0];
                if (cube.MdxScripts.Count > 0)
                {
                    var mdxScript = cube.MdxScripts[0];
                    foreach (Command mdxCommand in mdxScript.Commands)
                    {
                        if (!string.IsNullOrEmpty(mdxCommand.Text))
                        {
                            var measures = MeasuresContainer.ParseDaxScript(mdxCommand.Text).Measures;
                            foreach (var measure in measures)
                            {
                                // Add measure declaration to the global collection
                                var measureShortName = "[" + measure.Name + "]";
                                measureDeclarations.Add(new Babel.Declaration(measure.Expression, measure.Name, Babel.LanguageService.MEASURE_GLYPH_INDEX, measureShortName));

                                GenerateValidTableNames(measure.TableName).ForEach(i => measureList.Add(string.Format("{0}{1}", i, measureShortName)));

                                // Add the measure declaration to the table member declaration list
                                if (tableMembersDeclarations.ContainsKey(measure.TableName))
                                {
                                    tableMembersDeclarations[measure.TableName].Add(new Babel.Declaration(measure.Expression, measure.Name, Babel.LanguageService.MEASURE_GLYPH_INDEX, measureShortName));
                                }
                            }
                        }
                    }
                }
            }
            // Create HTML table
            string htmlSchemaTemplate;

            using (var textStreamReader = new StreamReader(System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream("DaxEditor.Resources.ScemaTemplate.htm")))
            {
                htmlSchemaTemplate = textStreamReader.ReadToEnd();
            }
            var htmlSchemaBuilder = new StringBuilder();

            foreach (var td in tableMembersDeclarations)
            {
                htmlSchemaBuilder.AppendFormat(BeginTableTemplate, HtmlEncode(td.Key));
                foreach (var decl in td.Value)
                {
                    if (_rowNumberColumnNames.Any(i => { return(string.Equals(i, decl.Name, StringComparison.CurrentCultureIgnoreCase)); }))
                    {
                        continue;
                    }

                    switch (decl.Glyph)
                    {
                    case Babel.LanguageService.BASE_COLUMN_GLYPH_INDEX:
                        htmlSchemaBuilder.AppendFormat(RowTemplate, "column", HtmlEncode(decl.Name));
                        break;

                    case Babel.LanguageService.CALC_COLUMN_GLYPH_INDEX:
                        htmlSchemaBuilder.AppendFormat(RowTemplate, "calcolumn", HtmlEncode(decl.Name));
                        break;

                    case Babel.LanguageService.MEASURE_GLYPH_INDEX:
                        htmlSchemaBuilder.AppendFormat(RowTemplate, "measure", HtmlEncode(decl.Name));
                        break;
                    }
                }
                htmlSchemaBuilder.Append(EndTableTemplate);
            }
            htmlSchemaTemplate = htmlSchemaTemplate.Replace(TablesPlaceholder, htmlSchemaBuilder.ToString());

            // Commit the newly created declarations into the cache
            lock (this)
            {
                this._tableDeclarations        = tableDeclarations;
                this._measureDeclarations      = measureDeclarations;
                this._tableMembersDeclarations = tableMembersDeclarations;
                this._htmlSchema = htmlSchemaTemplate;

                _completionDataSnapshot = new CompletionDataSnapshot(_completionDataSnapshot, tableList, columnList, measureList);
            }

            LogLine("End constructing schema based declarations.");
        }