Attributes · The Four Attributes · Practice Question
What Does It Mean That Attributes Are "Descriptive, Not Prescriptive"?
Question
Explain the statement "kdb+ attributes are descriptive, not prescriptive." What happens when you apply s# to an unsorted list? What about p# to a non-contiguous list?
Solution
/ All three structured attributes validate at apply time:
/ s# — throws 's-fail if not sorted
`s# 4 2 5 1 3 / 's-fail
/ u# — throws 'u-fail if not unique
`u# 1 2 1 3 4 / 'u-fail
/ p# — throws 'u-fail if not contiguous
`p# 1 1 2 3 4 1 2 / 'u-fail — 1 appears non-contiguously
/ p# succeeds only when values are genuinely contiguous (grouped)
`p# 1 1 2 2 3 3 / ok — each value forms one contiguous block
`p# `AAPL`AAPL`GOOG`GOOG`MSFT / ok
/ g# — no structural constraint, always succeeds
`g# 1 2 1 3 2 1 / ok — any order, any values
/ Descriptive: attributes assert existing structure
/ They do NOT sort, deduplicate, or reorganise the data for you
L: `s# asc 5 3 1 4 2 / correct: sort first, then assert s#
L: asc 5 3 1 4 2 / asc automatically applies s# anywayExplanation
Descriptive means an attribute is a declaration: "this data has this structure." kdb+ validates the declaration at apply time and uses it to choose a faster algorithm. It does not impose or maintain the structure going forward.
Prescriptive would mean "enforce this structure going forward." Attributes are not prescriptive — applying g# to a sym column does not prevent you from inserting a row that breaks some invariant; it just maintains the inverted index as data arrives. Applying s# does not re-sort the list when you append a smaller element — it drops the attribute.
Validation at apply time:
All three structured attributes check the data when you apply them:
s#— verifies ascending order →'s-failif notu#— verifies uniqueness →'u-failif notp#— verifies contiguity →'u-failif not (same error code asu#)g#— no constraint to check → always succeeds
After apply, kdb+ does not maintain the guarantee. This is the "descriptive" part. If you apply s# to a sorted list and then insert a smaller value (n,: smallValue), the attribute is silently dropped — kdb+ detects the violation and removes the attribute rather than leaving it in an inconsistent state. Similarly, p# is dropped on any append (even one that would maintain contiguity). Always re-check with attr after mutations if the attribute matters for query correctness.
The correct EOD sequence for HDB:
/ Sort first — this is what makes the data parted
`sym xasc `:/hdb/2025.01.01/trade/
/ Then assert p# — will throw if xasc failed or data has issues
@[`:/hdb/2025.01.01/trade/; `sym; `p#]
/ WRONG order — xasc strips p# immediately after it was applied
@[`:/hdb/2025.01.01/trade/; `sym; `p#] / p# set
`sym xasc `:/hdb/2025.01.01/trade/ / xasc then drops p#