From 21fcf2d6fa1ec90f4d6579f33993d4b71a1685d8 Mon Sep 17 00:00:00 2001 From: dc Date: Thu, 15 Oct 2026 22:54:20 +0000 Subject: [PATCH] docs(developer-guide): the delete-record column is client-owned The pre-edit hook example re-added _____DELETE__THIS__RECORD_____="No" when it re-read the table, mirroring the data step getdata.sas used to run. That column is created by the editor itself (it is the Delete? column) and is never part of the dataset, so the example no longer adds it - and a response that carries the name is refused by the editor, which the "What the hook does" bullet now states. Also notes the reserved name on the MPE_TABLES page, and says in the user guide that the Delete? column is created by Data Controller rather than being part of the table. --- docs/dc-userguide.md | 2 +- docs/dcc-tables.md | 3 +++ docs/developer-guide/filter-pre-edit-hook.md | 3 +-- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/docs/dc-userguide.md b/docs/dc-userguide.md index 404438a..79e090c 100644 --- a/docs/dc-userguide.md +++ b/docs/dc-userguide.md @@ -42,7 +42,7 @@ The Editor screen lets users who have been pre-authorised (via the `DATACTRL.MPE 2 - *Upload*. If you have a lot of data, you can [upload it directly](files). The changes are then approved in the usual way. -3 - *Edit*. This is the main interface, data is displayed in tabular format. The first column is always "Delete?", as this allows you to mark rows for deletion. Note that removing a row from display does not mark it for deletion! It simply means that this row is not part of the changeset being submitted. +3 - *Edit*. This is the main interface, data is displayed in tabular format. The first column is always "Delete?", as this allows you to mark rows for deletion. This column is created by Data Controller and is not part of your table. Note that removing a row from display does not mark it for deletion! It simply means that this row is not part of the changeset being submitted. The next set of columns are the Primary Key, and are shaded grey. If the table has a surrogate / retained key, then it is the Business Key that is shown here (the RK field is calculated / updated at the backend). For SCD2 type tables, the 'validity' fields are not shown. It is assumed that the user is always working with the current version of the data, and the view is filtered as such. After this, remaining columns are shown. Dates / datetime fields have appropriate datepickers. Other fields may also have dropdowns to ensure entry of standard values, these can be configured in the `DATACTRL.MPE_SELECTBOX` table. diff --git a/docs/dcc-tables.md b/docs/dcc-tables.md index c0102f6..f67679c 100644 --- a/docs/dcc-tables.md +++ b/docs/dcc-tables.md @@ -16,6 +16,9 @@ Adding tables to the Data Controller is a matter of configuration, specifically ![screenshot](img/configtable.png) +!!! note + `_____DELETE__THIS__RECORD_____` is a reserved name. The editor creates that column itself - it is the **Delete?** column - and never reads it from the table, so a target table must not contain a column of that name. The editor refuses to open a table that does, rather than let the two collide. + ## MPE_TABLES Configuration Details Each table to be edited in the Data Controller is represented by one record in `DATACTRL.MPE_TABLES`. The fields should be populated as follows: diff --git a/docs/developer-guide/filter-pre-edit-hook.md b/docs/developer-guide/filter-pre-edit-hook.md index e1bcac0..2ee4a59 100644 --- a/docs/developer-guide/filter-pre-edit-hook.md +++ b/docs/developer-guide/filter-pre-edit-hook.md @@ -101,7 +101,6 @@ The hook below is registered in `MPE_TABLES.PRE_EDIT_HOOK` for a table with a da /* re-read the table, so the grid shows both quarters */ data work.out (drop=&var_txfrom &var_txto &var_processed &drop_rk); - _____DELETE__THIS__RECORD_____="No"; set &orig_libds; where %inc newfilt; run; @@ -130,7 +129,7 @@ The hook below is registered in `MPE_TABLES.PRE_EDIT_HOOK` for a table with a da - **The user's clause.** `work.QUERY` is the filter's clauses as structured rows, and `%mp_filtergenerate` turns them back into a WHERE clause. This is the user's filter on its own, with no Row Level Security or validity clause mixed in. - **Data Controller's clause.** Calling `%mpe_filtermaster` with `filter_rk=-1` produces the part of the filter that is not the user's: the current-record validity clause and any Row Level Security, or `1=1` when there is neither. - **The combined filter.** The two clauses are combined as `( user OR previous-quarter ) AND ( validity + RLS )`, so the previous quarter is added to the user's selection without widening anything the user is not entitled to see. -- **The rows.** `work.OUT` is rebuilt with the combined filter, using the same drop list as the data step `getdata` runs itself - the transaction and processing columns, plus `&drop_rk`, the surrogate key that `getdata` hides when a table is registered with `RK_UNDERLYING` - and sorted on `&sortpk`, because `getdata` sorts before the hook runs and does not sort again afterwards. On a bitemporal table `getdata` also deduplicates to the latest record per primary key (`by &pk &var_busfrom`); add that step too, or the re-read returns every temporal version rather than the current one. +- **The rows.** `work.OUT` is rebuilt with the combined filter, using the same drop list as the data step `getdata` runs itself - the transaction and processing columns, plus `&drop_rk`, the surrogate key that `getdata` hides when a table is registered with `RK_UNDERLYING` - and sorted on `&sortpk`, because `getdata` sorts before the hook runs and does not sort again afterwards. On a bitemporal table `getdata` also deduplicates to the latest record per primary key (`by &pk &var_busfrom`); add that step too, or the re-read returns every temporal version rather than the current one. The delete column is **not** re-added: `_____DELETE__THIS__RECORD_____` is created by the editor itself and is never a column of the dataset, so a hook must not introduce it (a response that carries that name is refused by the editor). - **The returned text.** `filtref` is overwritten with the combined filter, so the clause the editor shows is the one that was actually applied. ### What it looks like -- 2.53.0