You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
docs(AC0031, AC0032): document DataTransfer CopyFields/CopyRows as table operations (#157)
CopyFields counts as r on the source and m on the destination, CopyRows as r and i,
with the tables taken from every SetTables(Database::X, Database::Y) call on the same
variable (bare or this.-qualified) in the same procedure — provided every one of them
resolves. Unresolvable SetTables: AC0031 reports nothing; AC0032 is disabled for the
object, like the RecordRef case.
Companion to ALCops/Analyzers#491.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: content/docs/analyzers/ApplicationCop/AC0031.md
+34Lines changed: 34 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -87,6 +87,40 @@ XmlPort `tableelement` nodes require permissions based on the `Direction` proper
87
87
88
88
Setting `AutoSave`, `AutoReplace`, or `AutoUpdate` to `false` suppresses the corresponding requirement.
89
89
90
+
### DataTransfer operations
91
+
92
+
A `DataTransfer` variable performs its database work in a single bulk statement when `CopyFields` or `CopyRows` is called. The tables involved are the ones named in `SetTables`:
93
+
94
+
| Method | Source table | Destination table |
95
+
|---|---|---|
96
+
|`CopyFields`| Read (`r`) | Modify (`m`) |
97
+
|`CopyRows`| Read (`r`) | Insert (`i`) |
98
+
99
+
The other `DataTransfer` methods (`SetTables`, `AddFieldValue`, `AddConstantValue`, `AddJoin`, `AddSourceFilter`, `AddDestinationFilter`, `UpdateAuditFields`) only configure the transfer in memory and do not require permissions. The diagnostic is reported on the `CopyFields` or `CopyRows` call.
PurchCrMemoLineDataTransfer.CopyFields(); // Table data access requires explicit object permissions [AC0031]
116
+
end;
117
+
}
118
+
{{< /highlight >}}
119
+
120
+
The tables are resolved from every `SetTables` call on the same `DataTransfer` variable **in the same procedure or trigger** as the `CopyFields`/`CopyRows` call, and only when both arguments are `Database::"Table Name"` literals. When several `SetTables` calls exist in that body, all of their tables are considered — provided every one of them resolves; a single `SetTables` with a non-literal argument makes the whole call unresolvable. The variable itself may be a local, a global (also when addressed as `this.MyDataTransfer`), or a parameter.
121
+
122
+
When the tables cannot be determined — no `SetTables` in the same body (for example, configured in another procedure or by the caller), or an argument that is a variable, parameter, or expression instead of a `Database::` literal — no diagnostic is reported for that call.
123
+
90
124
### Exceptions
91
125
92
126
The diagnostic is suppressed when any of the following conditions apply:
Note that this also suppresses genuinely unused entries in the same object. This trade-off is deliberate: a false "unused" report combined with the code fix would remove permissions that are required at runtime.
136
137
138
+
### DataTransfer operations
139
+
140
+
A `DataTransfer` variable touches the database only when `CopyFields` or `CopyRows` is called, and the tables involved are the ones named in `SetTables`. These calls count as using the following permissions:
141
+
142
+
| Method | Source table | Destination table |
143
+
|---|---|---|
144
+
|`CopyFields`| Read (`r`) | Modify (`m`) |
145
+
|`CopyRows`| Read (`r`) | Insert (`i`) |
146
+
147
+
The other `DataTransfer` methods (`SetTables`, `AddFieldValue`, `AddConstantValue`, `AddJoin`, `AddSourceFilter`, `AddDestinationFilter`, `UpdateAuditFields`) configure the transfer in memory and do not count as usage. Chars beyond what the executor needs are still reported: `tabledata X = rimd` with only a same-table `CopyFields` reports `id` as unused.
148
+
149
+
{{< highlight al >}}
150
+
codeunit 50100 "Upgrade Purch. Cr. Memo Line"
151
+
{
152
+
Subtype = Upgrade;
153
+
// Not reported: CopyFields reads and modifies "Purch. Cr. Memo Line"
The tables are resolved from every `SetTables` call on the same `DataTransfer` variable **in the same procedure or trigger** as the `CopyFields`/`CopyRows` call, and only when both arguments are `Database::"Table Name"` literals. When several `SetTables` calls exist in that body, all of their tables count as used — provided every one of them resolves; a single `SetTables` with a non-literal argument makes the whole call unresolvable. The variable may be a local, a global (also when addressed as `this.MyDataTransfer`), or a parameter.
170
+
171
+
When the tables cannot be determined — no `SetTables` in the same body (for example, configured in another procedure or by the caller), or an argument that is a variable, parameter, or expression instead of a `Database::` literal — the operation may target any table, and AC0032 is disabled for the entire object, exactly as for `RecordRef` operations above.
172
+
137
173
### Temporary tables
138
174
139
175
Access through a temporary table does **not** count as using a permission. Temporary tables never touch the database, so a `Permissions` entry for a table that is accessed **only** through temporary records is dead code and **is reported** as unused. This applies to every way a temporary table can be implemented: the `temporary` keyword on a record variable, a table object with `TableType = Temporary`, a page with `SourceTableTemporary = true`, and report data items or XMLPort table elements with `UseTemporary = true`.
0 commit comments