mirror of
https://github.com/microsoft/BCQuality.git
synced 2026-08-06 17:36:53 +01:00
Complete AL review knowledge readiness (#108)
* Complete AL review knowledge readiness Fill telemetry and Query coverage, strengthen thin review domains, correct audited content defects, and add deterministic cheap-model evaluation and reference-integrity safeguards. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 9825b012-e653-496a-9310-c1f4b6f8ac27 * Generalize review fixture discovery Derive smoke cases from the leaf, domain, and paired-sample conventions so new leaves require no scoring-contract changes. Keep only exceptional selection/context overrides and fail when retrieval metadata cannot rank the selected article. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 9825b012-e653-496a-9310-c1f4b6f8ac27 * Preserve published field IDs in sample Keep the existing Email and Contact Email field IDs unchanged, clarify that the sample represents an independent baseline, and use a local breaking-change rule for the generic smoke evaluation. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 9825b012-e653-496a-9310-c1f4b6f8ac27 * Clarify published field identity rules State explicitly that a published field keeps its ID, name, and type while a replacement is added as a separate field under an unused ID. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 9825b012-e653-496a-9310-c1f4b6f8ac27 * Align field obsoletion sample baselines Use Email field ID 3 as the shared baseline so the bad example demonstrates a same-ID rename while the good example retains the original field and adds a separate replacement. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 9825b012-e653-496a-9310-c1f4b6f8ac27 --------- Co-authored-by: Jesper Schulz-Wedde <jesper.schulzwedde@microsoft.com>
This commit is contained in:
parent
ae04938c03
commit
186d8a1314
105 changed files with 2229 additions and 212 deletions
|
|
@ -0,0 +1,28 @@
|
|||
query 50426 "Query Reuse Bad"
|
||||
{
|
||||
QueryType = Normal;
|
||||
|
||||
elements
|
||||
{
|
||||
dataitem(Customer; Customer)
|
||||
{
|
||||
column(CustomerNo; "No.") { }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
codeunit 50427 "Query Reuse Bad"
|
||||
{
|
||||
procedure ReadAgain(CustomerNoFilter: Code[20])
|
||||
var
|
||||
CustomerQuery: Query "Query Reuse Bad";
|
||||
begin
|
||||
CustomerQuery.SetRange(CustomerNo, CustomerNoFilter);
|
||||
CustomerQuery.Open();
|
||||
if CustomerQuery.Read() then;
|
||||
|
||||
// Reopening resets to the first row and retains CustomerNo.
|
||||
CustomerQuery.Open();
|
||||
if CustomerQuery.Read() then;
|
||||
end;
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
query 50424 "Query Reuse Good"
|
||||
{
|
||||
QueryType = Normal;
|
||||
|
||||
elements
|
||||
{
|
||||
dataitem(Customer; Customer)
|
||||
{
|
||||
column(CustomerNo; "No.") { }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
codeunit 50425 "Query Reuse Good"
|
||||
{
|
||||
procedure ReadTwoIndependentSets(FirstNo: Code[20]; SecondNo: Code[20])
|
||||
var
|
||||
CustomerQuery: Query "Query Reuse Good";
|
||||
begin
|
||||
CustomerQuery.SetRange(CustomerNo, FirstNo);
|
||||
ReadAll(CustomerQuery);
|
||||
|
||||
Clear(CustomerQuery);
|
||||
CustomerQuery.SetRange(CustomerNo, SecondNo);
|
||||
ReadAll(CustomerQuery);
|
||||
end;
|
||||
|
||||
local procedure ReadAll(var CustomerQuery: Query "Query Reuse Good")
|
||||
begin
|
||||
CustomerQuery.Open();
|
||||
while CustomerQuery.Read() do
|
||||
ProcessCustomer(CustomerQuery.CustomerNo);
|
||||
CustomerQuery.Close();
|
||||
end;
|
||||
|
||||
local procedure ProcessCustomer(CustomerNo: Code[20])
|
||||
begin
|
||||
end;
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
---
|
||||
bc-version: [all]
|
||||
domain: query
|
||||
keywords: [query, open, close, clear, cursor, filters, reuse]
|
||||
technologies: [al]
|
||||
countries: [w1]
|
||||
application-area: [all]
|
||||
---
|
||||
|
||||
# Reopening a Query resets its cursor but keeps its filters
|
||||
|
||||
## Description
|
||||
|
||||
Calling `Open()` on an already open query first closes the current dataset and opens it again. The next `Read()` starts at the first row; it does not continue from the previous cursor. Reopening also retains filters previously applied to the query variable. Only `Clear(QueryVariable)` resets those filters, so reuse can unexpectedly reread the first row or carry an old filter into a logically separate operation.
|
||||
|
||||
## Best Practice
|
||||
|
||||
Open once for one read pass. Close after the pass, and call `Clear(QueryVariable)` before reusing the variable for a logically independent query whose filters must start empty. Set the next pass's filters explicitly before reopening.
|
||||
|
||||
See sample: `reopening-query-resets-cursor-but-keeps-filters.good.al`.
|
||||
|
||||
## Anti Pattern
|
||||
|
||||
Calling `Open()` inside or between reads to "advance" or "start fresh", or reusing the same query variable for a new operation while assuming `Open()` cleared old filters. The code compiles but can repeatedly process the first row or silently omit rows behind a retained filter.
|
||||
|
||||
See sample: `reopening-query-resets-cursor-but-keeps-filters.bad.al`.
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
query 50422 "Query Customer Sales Bad"
|
||||
{
|
||||
QueryType = Normal;
|
||||
|
||||
elements
|
||||
{
|
||||
dataitem(Customer; Customer)
|
||||
{
|
||||
column(CustomerNo; "No.") { }
|
||||
column(CustomerName; Name) { }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
codeunit 50423 "Query Filter Order Bad"
|
||||
{
|
||||
procedure ReadCustomer(CustomerNoFilter: Code[20])
|
||||
var
|
||||
CustomerSales: Query "Query Customer Sales Bad";
|
||||
begin
|
||||
CustomerSales.Open();
|
||||
CustomerSales.SetRange(CustomerNo, CustomerNoFilter);
|
||||
while CustomerSales.Read() do
|
||||
ProcessCustomer(CustomerSales.CustomerNo);
|
||||
end;
|
||||
|
||||
local procedure ProcessCustomer(CustomerNo: Code[20])
|
||||
begin
|
||||
end;
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
query 50420 "Query Customer Sales Good"
|
||||
{
|
||||
QueryType = Normal;
|
||||
|
||||
elements
|
||||
{
|
||||
dataitem(Customer; Customer)
|
||||
{
|
||||
column(CustomerNo; "No.") { }
|
||||
column(CustomerName; Name) { }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
codeunit 50421 "Query Filter Order Good"
|
||||
{
|
||||
procedure ReadCustomer(CustomerNoFilter: Code[20])
|
||||
var
|
||||
CustomerSales: Query "Query Customer Sales Good";
|
||||
begin
|
||||
CustomerSales.SetRange(CustomerNo, CustomerNoFilter);
|
||||
CustomerSales.Open();
|
||||
while CustomerSales.Read() do
|
||||
ProcessCustomer(CustomerSales.CustomerNo);
|
||||
CustomerSales.Close();
|
||||
end;
|
||||
|
||||
local procedure ProcessCustomer(CustomerNo: Code[20])
|
||||
begin
|
||||
end;
|
||||
}
|
||||
26
microsoft/knowledge/query/set-query-filters-before-open.md
Normal file
26
microsoft/knowledge/query/set-query-filters-before-open.md
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
---
|
||||
bc-version: [all]
|
||||
domain: query
|
||||
keywords: [query, setfilter, setrange, open, read, dataset, filter-order]
|
||||
technologies: [al]
|
||||
countries: [w1]
|
||||
application-area: [all]
|
||||
---
|
||||
|
||||
# Set Query filters before Open
|
||||
|
||||
## Description
|
||||
|
||||
`Query.SetFilter` and `Query.SetRange` automatically close an open query dataset. A call placed after `Open()` therefore does not refine the rows already being read; it ends that dataset. The next `Read()` has no open dataset unless the code explicitly calls `Open()` again, so a plausible filter change can turn a working loop into an empty or failing read sequence without a compiler diagnostic.
|
||||
|
||||
## Best Practice
|
||||
|
||||
Apply every filter before `Open()`, then read the dataset to completion and call `Close()`. When a later branch needs different filters, close or clear the query, set the new filters, and open a new dataset deliberately.
|
||||
|
||||
See sample: `set-query-filters-before-open.good.al`.
|
||||
|
||||
## Anti Pattern
|
||||
|
||||
`Query.Open()` followed by `SetFilter` or `SetRange` and then `Read()` under the assumption that the filter updates the open cursor. Refiltering after `Open()` is valid only when the code intentionally opens a fresh dataset afterward.
|
||||
|
||||
See sample: `set-query-filters-before-open.bad.al`.
|
||||
Loading…
Add table
Add a link
Reference in a new issue