Skip to content

Commit 99ac1af

Browse files
committed
Combined rules
1 parent cd7b865 commit 99ac1af

File tree

1 file changed

+99
-3
lines changed

1 file changed

+99
-3
lines changed

BPARules-standard.json

Lines changed: 99 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,16 @@
11
[
2+
{
3+
"ID": "DAX_COLUMNS_FULLY_QUALIFIED",
4+
"Name": "Column references should be fully qualified",
5+
"Category": "DAX Expressions",
6+
"Description": "Using fully qualified column references makes it easier to distinguish between column and measure references, and also helps avoid certain errors.",
7+
"Severity": 2,
8+
"Scope": "Measure, CalculatedColumn, CalculatedTable, KPI",
9+
"Expression": "DependsOn.Any(Key.ObjectType = \"Column\" and Value.Any(not FullyQualified))",
10+
"FixExpression": null,
11+
"CompatibilityLevel": 1200,
12+
"Source": "standard\\DAX Expressions"
13+
},
214
{
315
"ID": "DAX_DIVISION_COLUMNS",
416
"Name": "Avoid division (use DIVIDE function instead)",
@@ -10,6 +22,18 @@
1022
"Remarks": "This rule may flag false positives, if a slash (/) is used in an object name or in a comment. To fix this, we need access to the tokens from lexing the expression.",
1123
"Source": "standard\\DAX Expressions"
1224
},
25+
{
26+
"ID": "DAX_MEASURES_UNQUALIFIED",
27+
"Name": "Measure references should be unqualified",
28+
"Category": "DAX Expressions",
29+
"Description": "Using unqualified measure references makes it easier to distinguish between column and measure references, and also helps avoid certain errors.",
30+
"Severity": 2,
31+
"Scope": "Measure, CalculatedColumn, CalculatedTable, KPI",
32+
"Expression": "DependsOn.Any(Key.ObjectType = \"Measure\" and Value.Any(FullyQualified))",
33+
"FixExpression": null,
34+
"CompatibilityLevel": 1200,
35+
"Source": "standard\\DAX Expressions"
36+
},
1337
{
1438
"ID": "DAX_TODO",
1539
"Name": "Revisit TODO expressions",
@@ -20,13 +44,25 @@
2044
"Expression": "Expression.IndexOf(\"TODO\", StringComparison.OrdinalIgnoreCase) \u003e= 0",
2145
"Source": "standard\\DAX Expressions"
2246
},
47+
{
48+
"ID": "APPLY_FORMAT_STRING_MEASURES",
49+
"Name": "Provide format string for all visible measures",
50+
"Category": "Formatting",
51+
"Description": "Visible measures should have their Format String property assigned",
52+
"Severity": 3,
53+
"Scope": "Measure",
54+
"Expression": "not IsHidden \nand string.IsNullOrWhitespace(FormatString)",
55+
"FixExpression": null,
56+
"CompatibilityLevel": 1200,
57+
"Source": "standard\\Formatting"
58+
},
2359
{
2460
"ID": "META_AVOID_FLOAT",
2561
"Name": "Do not use floating point data types",
2662
"Category": "Metadata",
27-
"Description": "Floating point datatypes can cause unexpected results when evaluating values close to 0. Use Decimal instead.",
63+
"Description": "Floating point datatypes can cause unexpected results when evaluating values close to 0. Use Currency / Fixed Decimal Number (decimal) instead.",
2864
"Severity": 3,
29-
"Scope": "Measure, DataColumn, CalculatedColumn, CalculatedTableColumn",
65+
"Scope": "DataColumn, CalculatedColumn, CalculatedTableColumn",
3066
"Expression": "DataType = \"Double\"",
3167
"FixExpression": "DataType = DataType.Decimal",
3268
"Source": "standard\\Metadata"
@@ -38,7 +74,7 @@
3874
"Description": "Set the SummarizeBy property of all visible numeric columns to \"None\", to avoid unintentional summarization in client tools. Create measures for columns that are supposed to be summarized.",
3975
"Severity": 1,
4076
"Scope": "DataColumn, CalculatedColumn, CalculatedTableColumn",
41-
"Expression": "IsHidden = false and SummarizeBy \u003c\u003e \"None\"",
77+
"Expression": "IsHidden = false and Table.IsHidden = false and SummarizeBy \u003c\u003e \"None\" and (DataType = \"Double\" or DataType = \"Decimal\" or DataType = \"Int64\")",
4278
"FixExpression": "SummarizeBy = AggregateFunction.None",
4379
"Source": "standard\\Metadata"
4480
},
@@ -94,6 +130,66 @@
94130
"Expression": "not IsHidden and Measures.Count(not IsHidden and string.IsNullOrEmpty(DisplayFolder)) \u003e 10",
95131
"Source": "standard\\Model Layout"
96132
},
133+
{
134+
"ID": "NO_CAMELCASE_COLUMNS_HIERARCHIES",
135+
"Name": "Avoid CamelCase on visible columns and hierarchies",
136+
"Category": "Naming Conventions",
137+
"Description": "Visible columns and hierarchies should not use CamelCase in their names, unless translations are applied",
138+
"Severity": 3,
139+
"Scope": "Hierarchy, DataColumn, CalculatedColumn, CalculatedTableColumn",
140+
"Expression": "not (IsHidden or Table.IsHidden) \nand RegEx.IsMatch(Name, \"[A-Z]([A-Z0-9]*[a-z][a-z0-9]*[A-Z]|[a-z0-9]*[A-Z][A-Z0-9]*[a-z])[A-Za-z0-9]*\") \nand not Name.Contains(\" \") \nand (Model.Cultures.Count = 0 or TranslatedNames.Any(it = \"\" or it = outerIt.Name))",
141+
"FixExpression": null,
142+
"CompatibilityLevel": 1200,
143+
"Source": "standard\\Naming"
144+
},
145+
{
146+
"ID": "NO_CAMELCASE_MEASURES_TABLES",
147+
"Name": "Avoid CamelCase on visible measures and tables",
148+
"Category": "Naming Conventions",
149+
"Description": "Visible measures and tables should not use CamelCase in their names, unless translations are applied",
150+
"Severity": 3,
151+
"Scope": "Measure, Table, CalculatedTable",
152+
"Expression": "not (IsHidden or Table.IsHidden) \nand RegEx.IsMatch(Name, \"[A-Z]([A-Z0-9]*[a-z][a-z0-9]*[A-Z]|[a-z0-9]*[A-Z][A-Z0-9]*[a-z])[A-Za-z0-9]*\") \nand not Name.Contains(\" \") \nand (Model.Cultures.Count = 0 or TranslatedNames.Any(it = \"\" or it = outerIt.Name))",
153+
"FixExpression": null,
154+
"CompatibilityLevel": 1200,
155+
"Source": "standard\\Naming"
156+
},
157+
{
158+
"ID": "RELATIONSHIP_COLUMN_NAMES",
159+
"Name": "Names of columns in relationships should be the same",
160+
"Category": "Naming Conventions",
161+
"Description": "When a single relationship exists between two tables, the columns on both sides of the relationship must have the same name. When multiple relationships exist between two tables, the name of the FromColumn must end with the name of the ToColumn (for example OrderDateKey, ShipDateKey, DueDateKey, etc.)",
162+
"Severity": 3,
163+
"Scope": "Relationship",
164+
"Expression": "(Model.Relationships.Count(FromTable = OuterIt.FromTable and ToTable = OuterIt.ToTable) = 1 and FromColumn.Name \u003c\u003e ToColumn.Name) or\n(Model.Relationships.Count(FromTable = OuterIt.FromTable and ToTable = OuterIt.ToTable) \u003e 1 and not FromColumn.Name.EndsWith(ToColumn.Name))",
165+
"FixExpression": null,
166+
"CompatibilityLevel": 1200,
167+
"Source": "standard\\Naming"
168+
},
169+
{
170+
"ID": "UPPERCASE_FIRST_LETTER_COLUMNS_HIERARCHIES",
171+
"Name": "Column and hierarchy names must start with uppercase letter",
172+
"Category": "Naming Conventions",
173+
"Description": "Avoid using prefixes and camelCasing. Use \"Sales\" instead of \"dimSales\" or \"mSales\".",
174+
"Severity": 3,
175+
"Scope": "DataColumn, CalculatedColumn, CalculatedTableColumn",
176+
"Expression": "not (IsHidden or Table.IsHidden) and\nchar.IsLower(Name[0])\nand (Model.Cultures.Count = 0 or TranslatedNames.Any(it = \"\" or it = outerIt.Name))\n",
177+
"FixExpression": null,
178+
"CompatibilityLevel": 1200,
179+
"Source": "standard\\Naming"
180+
},
181+
{
182+
"ID": "UPPERCASE_FIRST_LETTER_MEASURES_TABLES",
183+
"Name": "Measure and table names must start with uppercase letter",
184+
"Category": "Naming Conventions",
185+
"Description": "Avoid using prefixes and camelCasing. Use \"Sales\" instead of \"dimSales\" or \"mSales\".",
186+
"Severity": 3,
187+
"Scope": "Table, Measure, CalculatedTable",
188+
"Expression": "not IsHidden\nand char.IsLower(Name[0])\nand (Model.Cultures.Count = 0 or TranslatedNames.Any(it = \"\" or it = outerIt.Name))\n",
189+
"FixExpression": null,
190+
"CompatibilityLevel": 1200,
191+
"Source": "standard\\Naming"
192+
},
97193
{
98194
"ID": "PERF_UNUSED_COLUMNS",
99195
"Name": "Remove unused columns",

0 commit comments

Comments
 (0)