This commit is contained in:
m-kovalsky 2023-02-14 14:17:23 +02:00 committed by GitHub
parent b0673d2c8b
commit 0cb344ae73
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -17,7 +17,7 @@
"Description": "To speed up processing time and conserve memory after processing, attribute hierarchies should not be built for columns that are never used for slicing by MDX clients. In other words, all hidden columns that are not used as a Sort By Column or referenced in user hierarchies should have their IsAvailableInMdx property set to false.\r\nReference: https://blog.crossjoin.co.uk/2018/07/02/isavailableinmdx-ssas-tabular/", "Description": "To speed up processing time and conserve memory after processing, attribute hierarchies should not be built for columns that are never used for slicing by MDX clients. In other words, all hidden columns that are not used as a Sort By Column or referenced in user hierarchies should have their IsAvailableInMdx property set to false.\r\nReference: https://blog.crossjoin.co.uk/2018/07/02/isavailableinmdx-ssas-tabular/",
"Severity": 2, "Severity": 2,
"Scope": "DataColumn, CalculatedColumn, CalculatedTableColumn", "Scope": "DataColumn, CalculatedColumn, CalculatedTableColumn",
"Expression": "IsAvailableInMDX\r\nand\r\n\n(IsHidden or Table.IsHidden)\r\nand\r\n\nnot UsedInSortBy.Any() \r\nand\r\n\nnot UsedInHierarchies.Any()\r\nand\r\nnot UsedInVariations.Any()","Expression": "IsAvailableInMDX\r\nand\r\n\n(IsHidden or Table.IsHidden)\r\nand\r\n\nnot UsedInSortBy.Any() \r\nand\r\n\nnot UsedInHierarchies.Any()\r\nand\r\nnot UsedInVariations.Any()\r\nand\r\nSortByColumn = null", "Expression": "IsAvailableInMDX\r\nand\r\n\n(IsHidden or Table.IsHidden)\r\nand\r\n\nnot UsedInSortBy.Any() \r\nand\r\n\nnot UsedInHierarchies.Any()\r\nand\r\nnot UsedInVariations.Any()\r\nand\r\nSortByColumn = null",
"FixExpression": "IsAvailableInMDX = false", "FixExpression": "IsAvailableInMDX = false",
"CompatibilityLevel": 1200 "CompatibilityLevel": 1200
}, },
@ -334,7 +334,7 @@
"ID": "AVOID_USING_'1-(X/Y)'_SYNTAX", "ID": "AVOID_USING_'1-(X/Y)'_SYNTAX",
"Name": "[DAX Expressions] Avoid using '1-(x/y)' syntax", "Name": "[DAX Expressions] Avoid using '1-(x/y)' syntax",
"Category": "DAX Expressions", "Category": "DAX Expressions",
"Description": "Instead of using the '1-(x/y)' or '1+(x/y)' syntax to achieve a percentage calculation, use the basic DAX functions (as shown below). Using the improved syntax will generally improve the performance. The '1+/-...' syntax always returns a value whereas the solution without the '1+/-...' does not (as the value may be 'blank'). Therefore the '1+/-...' syntax may return more rows/columns which may result in a slower query speed.\r\n\r\nLet's clarify with an example:\r\n\r\nAvoid this: 1 - SUM ( 'Sales'[CostAmount] ) / SUM( 'Sales'[SalesAmount] )\r\nBetter: SUM ( 'Sales'[SalesAmount] ) - DIVIDE ( SUM ( 'Sales'[CostAmount] ), SUM ( 'Sales'[SalesAmount] ) )\r\nBest: VAR x = SUM ( 'Sales'[SalesAmount] ) RETURN x - DIVIDE ( SUM ( 'Sales'[CostAmount] ), x )", "Description": "Instead of using the '1-(x/y)' or '1+(x/y)' syntax to achieve a percentage calculation, use the basic DAX functions (as shown below). Using the improved syntax will generally improve the performance. The '1+/-...' syntax always returns a value whereas the solution without the '1+/-...' does not (as the value may be 'blank'). Therefore the '1+/-...' syntax may return more rows/columns which may result in a slower query speed.\r\n\r\nLet's clarify with an example:\r\n\r\nAvoid this: 1 - SUM ( 'Sales'[CostAmount] ) / SUM( 'Sales'[SalesAmount] )\r\nBetter: DIVIDE ( SUM ( 'Sales'[SalesAmount] ) - SUM ( 'Sales'[CostAmount] ), SUM ( 'Sales'[SalesAmount] ) )\r\nBest: VAR x = SUM ( 'Sales'[SalesAmount] ) RETURN DIVIDE ( x - SUM ( 'Sales'[CostAmount] ), x )",
"Severity": 2, "Severity": 2,
"Scope": "Measure, CalculatedColumn, CalculationItem", "Scope": "Measure, CalculatedColumn, CalculationItem",
"Expression": "RegEx.IsMatch(Expression,\"[0-9]+\\s*[-+]\\s*[\\(]*\\s*(?i)SUM\\s*\\(\\s*\\'*[A-Za-z0-9 _]+\\'*\\s*\\[[A-Za-z0-9 _]+\\]\\s*\\)\\s*\\/\")\r\nor\r\nRegEx.IsMatch(Expression,\"[0-9]+\\s*[-+]\\s*(?i)DIVIDE\\s*\\(\")", "Expression": "RegEx.IsMatch(Expression,\"[0-9]+\\s*[-+]\\s*[\\(]*\\s*(?i)SUM\\s*\\(\\s*\\'*[A-Za-z0-9 _]+\\'*\\s*\\[[A-Za-z0-9 _]+\\]\\s*\\)\\s*\\/\")\r\nor\r\nRegEx.IsMatch(Expression,\"[0-9]+\\s*[-+]\\s*(?i)DIVIDE\\s*\\(\")",
@ -400,6 +400,28 @@
"Expression": "FromColumn.DataType != ToColumn.DataType", "Expression": "FromColumn.DataType != ToColumn.DataType",
"CompatibilityLevel": 1200 "CompatibilityLevel": 1200
}, },
{
"ID": "AVOID_INVALID_NAME_CHARACTERS",
"Name": "[Error Prevention] Avoid invalid characters in names",
"Category": "Error Prevention",
"Description": "This rule identifies if a name for a given object in your model (i.e. table/column/measure) which contains an invalid character. Invalid characters will cause an error when deploying the model (and failure to deploy). This rule has a fix expression which converts the invalid character into a space, resolving the issue.",
"Severity": 3,
"Scope": "Table, Measure, Hierarchy, Level, Perspective, Partition, DataColumn, CalculatedColumn, CalculatedTable, CalculatedTableColumn, KPI, ModelRole, CalculationGroup, CalculationItem",
"Expression": "Name.ToCharArray().Any(char.IsControl(it) and !char.IsWhiteSpace(it))",
"FixExpression": "Name = string.Concat( it.Name.ToCharArray().Select( c => (char.IsControl(c) && !char.IsWhiteSpace(c)) ? ' ': c ))",
"CompatibilityLevel": 1200
},
{
"ID": "AVOID_INVALID_DESCRIPTION_CHARACTERS",
"Name": "[Error Prevention] Avoid invalid characters in descriptions",
"Category": "Error Prevention",
"Description": "This rule identifies if a description for a given object in your model (i.e. table/column/measure) which contains an invalid character. Invalid characters will cause an error when deploying the model (and failure to deploy). This rule has a fix expression which converts the invalid character into a space, resolving the issue.",
"Severity": 3,
"Scope": "Table, Measure, Hierarchy, Level, Perspective, Partition, DataColumn, CalculatedColumn, CalculatedTable, CalculatedTableColumn, KPI, ModelRole, CalculationGroup, CalculationItem",
"Expression": "Description.ToCharArray().Any(char.IsControl(it) and !char.IsWhiteSpace(it))",
"FixExpression": "Description = string.Concat( it.Description.ToCharArray().Select( c => (char.IsControl(c) && !char.IsWhiteSpace(c)) ? ' ': c ))",
"CompatibilityLevel": 1200
},
{ {
"ID": "UNNECESSARY_COLUMNS", "ID": "UNNECESSARY_COLUMNS",
"Name": "[Maintenance] Remove unnecessary columns", "Name": "[Maintenance] Remove unnecessary columns",
@ -439,7 +461,7 @@
"Description": "Data sources which are not referenced by any partitions may be removed.", "Description": "Data sources which are not referenced by any partitions may be removed.",
"Severity": 1, "Severity": 1,
"Scope": "ProviderDataSource, StructuredDataSource", "Scope": "ProviderDataSource, StructuredDataSource",
"Expression": "UsedByPartitions.Count() == 0", "Expression": "UsedByPartitions.Count() == 0\r\nand not Model.Tables.Any(SourceExpression.Contains(OuterIt.Name))\r\nand not Model.AllPartitions.Any(Query.Contains(OuterIt.Name))",
"FixExpression": "Delete()", "FixExpression": "Delete()",
"CompatibilityLevel": 1200 "CompatibilityLevel": 1200
}, },
@ -516,6 +538,16 @@
"Expression": "Name.IndexOf(char(9)) > -1\r\nor\r\n\nName.IndexOf(char(10)) > -1 \r\nor\r\n\nName.IndexOf(char(13)) > -1", "Expression": "Name.IndexOf(char(9)) > -1\r\nor\r\n\nName.IndexOf(char(10)) > -1 \r\nor\r\n\nName.IndexOf(char(13)) > -1",
"CompatibilityLevel": 1200 "CompatibilityLevel": 1200
}, },
{
"ID": "TRIM_OBJECT_NAMES",
"Name": "[Naming Conventions] Trim object names",
"Category": "Naming Conventions",
"Description": "Unintentionally leaving a trailing space in an object name is a common occurrence when copying/duplicating objects in Tabular Editor.",
"Severity": 1,
"Scope": "Model, Table, Measure, Hierarchy, Level, Perspective, Partition, ProviderDataSource, DataColumn, CalculatedColumn, CalculatedTable, CalculatedTableColumn, StructuredDataSource, NamedExpression, ModelRole, CalculationGroup, CalculationItem",
"Expression": "Name.StartsWith(\" \") or Name.EndsWith(\" \")",
"CompatibilityLevel": 1200
},
{ {
"ID": "FORMAT_FLAG_COLUMNS_AS_YES/NO_VALUE_STRINGS", "ID": "FORMAT_FLAG_COLUMNS_AS_YES/NO_VALUE_STRINGS",
"Name": "[Formatting] Format flag columns as Yes/No value strings", "Name": "[Formatting] Format flag columns as Yes/No value strings",