
Q Language
- 1 installs
- Updated June 18, 2026
- dreth/kdb-q-language
Write, review, and debug q and q-sql code for kdb+ queries, tables, functions, IPC, and persistence using bundled Q for Mortals chapter references.
About
Guides writing and reviewing idiomatic q/kdb+ code with a q-sql checklist, idiom reminders, and chapter-based references. A developer uses it when building or debugging kdb+ queries and tables.
- q-sql query checklist covering meta, functional forms, partitions
- Anti-pattern references for SQL literalism and rank mistakes
Q Language by the numbers
- 1 all-time installs (skills.sh)
- Ranked #770 of 911 Databases skills by installs in the Skillselion catalog
- Data as of Jul 8, 2026 (Skillselion catalog sync)
npx skills add https://github.com/dreth/kdb-q-language --skill q-languageAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 1 |
|---|---|
| Last updated | June 18, 2026 |
| Repository | dreth/kdb-q-language ↗ |
What it does
Write, review, and debug q and q-sql code for kdb+ queries, tables, functions, IPC, and persistence using bundled Q for Mortals chapter references.
Files
q Language
Use this skill when writing or reviewing q, kdb+, or q-sql. Prefer idiomatic array/table operations over translating row-oriented SQL or imperative loops.
Workflow
1. Read references/index.md first to choose the smallest relevant chapter notes. 2. For implementation tasks, start with references/recipes.md; for pasteable patterns, load references/executable-examples.md. 3. For reviews or generated-code cleanup, load references/anti-patterns.md and check for SQL literalism, atom/list rank mistakes, key misuse, and symbol interning risks. 4. For data modeling or query work, read chapter-08-tables.md and chapter-09-queries-q-sql.md before writing code. 5. For expression bugs, read chapter-01-q-shock-and-awe.md, chapter-03-lists.md, chapter-04-operators.md, and chapter-06-functions.md. 6. For type, null, cast, or enum bugs, read chapter-02-basic-data-types-atoms.md and chapter-07-transforming-data.md. 7. For persisted kdb+ databases, read chapter-11-io.md and chapter-14-introduction-to-kdb.md. 8. If an error message is supplied, read appendix-b-error-messages.md early.
q-sql Query Checklist
- Confirm whether the input is a table, keyed table, splayed table, or partitioned table.
- Check column names and types first with
meta t,cols t,key t, and smallselect[10] from tprobes when q is available. - Use q-sql templates for readable queries:
select ... by ... from t where ...,update ... by ... from t where ...,delete ... from t where .... - Use functional forms (
?[t;c;b;a],![t;c;b;a]) when column names, filters, groupings, or aggregates are dynamic. Build constraints as lists and enlist literal symbols inside expressions. - For partitioned tables, put the partition constraint first in
whereand avoid broadselect from tprobes. - Remember row order matters in q. Sort explicitly with
xasc,xdesc,asc,desc, or attributes when the result depends on order.
Idiom Reminders
- q evaluates function application from right to left and has no traditional operator precedence. Add parentheses when generating code for humans.
- Lists, dictionaries, functions, and tables can all behave like maps. Indexing and function application share notation.
- Prefer vector operations, atomic functions, iterators (
each,over,scan,prior,peach), and q-sql aggregates over explicit loops. - Use typed empty lists in schemas: `
sym$()`,long$()`,timestamp$()``. - Use
enlistwhen a single item must remain a list, row, key, or record. - Treat symbols as interned values. Avoid unbounded conversion of arbitrary strings to symbols in long-running processes.
- Use
null xinstead ofx=0N, and keep temporal units explicit when mixing date/time/timestamp values. - Prefer IPC function calls with typed arguments over constructing remote query strings.
Validation
When q is installed, run generated snippets against a scratch process and inspect type, meta, count, and representative results. Without q, do structural validation: balance brackets/braces, check q-sql phrase order, verify column names/types against schemas, and reason through atom-vs-list rank.
This skill includes scripts/validate_skill.py for repository structure checks and a small semantic suite when a local q runtime is available.
interface:
display_name: "q Language"
short_description: "Write practical q and kdb+ queries"
default_prompt: "Use $q-language to write an idiomatic q query and explain the key q-sql choices."
policy:
allow_implicit_invocation: true
Anti-Patterns
Common generated-code mistakes and the q idiom to use instead.
SQL Literalism
Do not write ANSI SQL order or string SQL unless you are intentionally sending text to another system.
/ q-sql
select avg px by sym from trades where date=2026.06.16Symbol and Backtick Confusion
Symbols are backtick values, not quoted strings. They are interned for the process lifetime.
sym:`IBM
select from trades where sym=`IBMAvoid converting unbounded user text to symbols in long-running processes; keep arbitrary identifiers as strings or enumerate against a controlled domain.
Atom vs Singleton List
An atom is not a one-item list. Use enlist when shape matters.
enlist `IBM
([] sym:enlist `IBM; px:enlist 101f)This matters for table rows, functional q-sql constraints, and keyed-table lookup data.
Keyed Tables Are Dictionaries
Do not treat keys as ordinary mutable columns. Unkey, change, and rekey when needed.
kt:`sym xkey trades
kt ([] sym:`IBM`MSFT)
trades2:0!ktUse keys kt for key column names and key kt for the key table.
Row-Loop Thinking
Prefer vector expressions, q-sql, and joins over per-row loops.
update notional:px*size from trades
select vwap:size wavg px by sym from trades
trades lj `sym xkey instLoops are usually a sign the table operation has not been expressed in q yet.
Dynamic Query Strings
Prefer functional forms when names or filters are dynamic.
c:enlist (=;`sym;enlist `IBM)
a:`sym`px!`sym`px
?[trades;c;0b;a]Build constraints as a list, and enlist literal symbols inside parse-tree expressions.
Appendix A. Built-in Functions
Source URL: https://code.kx.com/q4m3/A_Built-in_Functions/
Agent-Relevant Takeaways
- Appendix A is a lookup catalog for q built-ins. Read it when choosing a primitive instead of hand-writing logic.
- Many built-ins have unary and binary forms; verify which valence you need.
- Prefer built-ins for aggregation, searching, grouping, sorting, text processing, math, time-series deltas, moving windows, and list reshaping.
q Syntax/Forms That Matter
- Aggregates:
sum,avg,min,max,prd,dev,var,med,wavg,wsum - Running/moving:
sums,avgs,deltas,ratios,mavg,msum,prev,next,xprev - Selection/search:
where,find/?,in,within,bin,binr,like,ss,ssr,differ - Shape/list:
count,til,take/#,drop/_,cut,raze,enlist,flip,ungroup - Sort/group/set:
asc,desc,iasc,idesc,group,distinct,rank,xrank,except,inter,union - Fill/window:
fills,^,xbar - Table/query helpers:
meta,cols,xkey,xcol,xcols,lj,ij,ej,aj,wj,uj - Text/cast helpers:
string,value,sv,vs,$ - Evaluation/system:
parse,eval,value,system,getenv,setenv
Common Mistakes/Pitfalls
- Reimplementing built-ins with loops.
- Forgetting aggregate behavior on nulls differs by function and type.
- Confusing keyword names with operator glyphs, especially
?,#,_,,,^. - Using parallel
peachwhere side effects or ordering assumptions make it unsafe. - Choosing a join primitive before checking key columns, sort order, and duplicate column semantics.
Small Examples
px:100 101 103 102f
deltas px
3 mavg px
t:([] sym:`A`A`B; px:10 11 20f)
select last px, max px by sym from t
`sym xkey t
update px:fills px by sym from t
select open:first px, close:last px by sym, bucket:5 xbar i from tCross-Links
- chapter-04-operators.md
- chapter-06-functions.md
- chapter-09-queries-q-sql.md
Appendix B. Error Messages
Source URL: https://code.kx.com/q4m3/B_Error_Messages/
Agent-Relevant Takeaways
- q errors are terse. Diagnose by mapping the symbol to category: runtime, parse, system, or license.
- Start with the expression shape: valence, type, rank, length, name resolution, and parse structure.
- Use smaller expressions,
type,count,meta, and protected evaluation to isolate the failing part. - For q-sql errors, inspect the parsed phrase order, table kind, column names, and atom-vs-list rank of every predicate.
q Syntax/Forms That Matter
- Protected unary evaluation:
@[f;x;{x}] - Protected multi-arg evaluation:
.[f;args;{x}] - Debug prompt appears after unhandled errors in interactive sessions; inspect variables before exiting.
- Common signals:
'type,'length,'rank,'domain,'parse,'value - Common query causes: wrong column name (
'column/'value), mismatched column lengths ('length), scalar where predicate ('type/'rank) - Error map:
'typewrong type/cast,'lengthnon-conforming lists/columns,'rankarity/depth mismatch,'domaininvalid value,'splayinvalid persisted table shape.
Common Mistakes/Pitfalls
- Treating the error text as a complete diagnosis. It is usually only the first clue.
- Fixing symptoms without checking atom/list rank.
- Ignoring parse errors caused by missing whitespace around names or invalid q-sql phrase order.
- Missing license/system errors that are unrelated to code logic.
- Fixing a join by changing data types without checking key shape and duplicate rows.
- Debugging a persisted query as if the table were fully materialized in memory.
- Missing that
'lengthduring table construction usually means column counts disagree.
Small Examples
safe:{[f;x] @[f;x;{`error`detail!(x;y)}]}
safe[{x+1};"abc"]
type each (1;1 2;"ab";`ab)
meta ([] sym:`IBM`MSFT; px:101 250f)Cross-Links
- chapter-02-basic-data-types-atoms.md
- chapter-04-operators.md
- chapter-10-execution-control.md
0. Overview
Source URL: https://code.kx.com/q4m3/0_Overview/
Agent-Relevant Takeaways
- q is terse, array-oriented, column-oriented, and designed for high-volume time-series data.
- Lists, dictionaries, tables, and functions are best understood as mappings.
- q is interpreted: data and functions live in the workspace, scripts are text, and
parse/evalexpose code-as-data workflows. - kdb+ stores q column lists with persistent backing; q is both query language and stored-procedure language.
q Syntax/Forms That Matter
- Function application is central:
f x,f[x],x g y, andg[x;y]. parseconverts text to q parse trees;evalevaluates q data/code.- Ordered lists and columnar tables are the foundation for time-series operations.
Common Mistakes/Pitfalls
- Translating object models directly into q. Use dictionaries and tables instead.
- Forgetting q table row order is meaningful, unlike classical SQL set semantics.
- Overusing dynamic
eval; prefer explicit functions or functional query forms unless code generation is required.
Small Examples
sq:{x*x}
sq 6
/ A table is a column dictionary with display/query behavior.
t:([] time:09:30 09:31; sym:`AAPL`MSFT; px:187.2 421.5)
select avg px by sym from tCross-Links
- chapter-01-q-shock-and-awe.md
- chapter-05-dictionaries.md
- chapter-08-tables.md
1. Q Shock and Awe
Source URL: https://code.kx.com/q4m3/1_Q_Shock_and_Awe/
Agent-Relevant Takeaways
- This chapter is the fastest orientation to q syntax: assignment, comments, evaluation order, atoms, lists, functions, dictionaries, tables, q-sql, I/O, IPC, and WebSockets.
- Assignment uses
:. Equality uses=. - q reads left to right but evaluates function application right to left; there is no conventional arithmetic precedence.
- q examples often rely on the console. Script code should be explicit about names, semicolons, and side effects.
q Syntax/Forms That Matter
- Assignment:
name:value - Line comment:
/ text; multi-line comment blocks are script-oriented. - Function:
{[x;y] x+y}; implicit arguments:x,y,z. - List:
1 2 3; general list:(1;a;"bc")` - Dictionary: `
ab!10 20` - Table:
([] c1:1 2; c2:ab) - q-sql:
select cols by group from t where pred
Common Mistakes/Pitfalls
- Writing
a=42for assignment. - Assuming
2*3+4means(2*3)+4; in q, add parentheses when precedence matters. - Missing
enlistfor singleton rows or singleton keyed-table records. - Treating strings and symbols interchangeably.
Small Examples
price:101.5 102.0 100.75
qty:200 150 300
notional:price*qty
trades:([] sym:`IBM`IBM`MSFT; px:101.5 102.0 300.2; size:200 150 50)
select vwap:size wavg px by sym from tradesCross-Links
- chapter-02-basic-data-types-atoms.md
- chapter-03-lists.md
- chapter-06-functions.md
- chapter-09-queries-q-sql.md
2. Basic Data Types: Atoms
Source URL: https://code.kx.com/q4m3/2_Basic_Data_Types_Atoms/
Agent-Relevant Takeaways
- Atoms are scalar values. Each q atom has a type code; lists have positive type codes and atoms have negative type codes.
- Numeric types include short, int, long, real, float; default integer literals are long and default decimal literals are float.
- Text is split into chars (
"a") and symbols (`abc ``). Symbols are interned and should not be generated unboundedly from arbitrary text. - Temporal atoms have specific literal forms for date, month, time, minute, second, datetime, timestamp, and timespan.
- Nulls are typed; use
nullto test them. - Boolean, byte, GUID, and char use proxy nulls because all bit patterns are otherwise valid.
- Integer arithmetic can overflow into integral null/infinity bit patterns; division returns floats and uses float infinity/null.
q Syntax/Forms That Matter
- Boolean:
1b, byte:0x2a, short/int/long suffixes:42h,42i,42j - Float/real:
4.2,4.2e - Symbol: `
abc `; char list string:"abc"` - Date/time:
2026.06.16,12:34:56.789,2026.06.16D12:34:56.789000000 - Temporal arithmetic:
date+int,timestamp+timespan,timestamp-date - Null/infinity examples:
0N,0Nj,0n,0W,0w,0Nd,0Np, ```
Common Mistakes/Pitfalls
- Comparing nulls with
=instead ofnull. - Using symbols for high-cardinality unbounded strings in services.
- Mixing temporal types without checking units and precision.
- Forgetting that a single char is an atom but a string is a char list.
- Assuming q nulls behave like SQL
NULL; q nulls are ordinary typed values in vectors. - Relying on
0Nfor all missing data; use typed schemas andnull.
Small Examples
type each (42;42i;4.2;`abc;"abc";2026.06.16)
null (0N;0n;`;2026.06.16)
show `timestamp$"2026.06.16D09:30:00.000000000"
d:2026.06.16
ts:2026.06.16D09:30:00.000000000
(d+1; ts+0D00:00:01.000000000)
null (0Nd;0Np;0Nn;0Nt;`)Cross-Links
- chapter-07-transforming-data.md
- chapter-03-lists.md
- appendix-b-error-messages.md
3. Lists
Source URL: https://code.kx.com/q4m3/3_Lists/
Agent-Relevant Takeaways
- Lists are ordered and zero-indexed. Simple lists are homogeneous and contiguous; general lists can hold mixed or nested values.
count,first,last,til,where,take,drop,cut,raze, and indexing patterns are core q building blocks.- A list can act as a map from indices to values.
- Indexing can be repeated (
m[1][2]) or done at depth (m[1;2]). - List indexing accepts atoms, index lists, boolean masks via
where, and nested paths. #and_are overloaded: take/reshape and drop/cut. Negative counts operate from the end.
q Syntax/Forms That Matter
- Simple list:
10 20 30 - General list:
(10;a;"bc")` - Empty general list:
(); typed empty list: `long$()`` - Singleton list:
enlist 42 - Join:
,; fill/coalesce:^ - Indexing:
xs 0,xs[0 2],xs[where xs>10] - Index at depth:
m[1;2], amend at depth:.[m;1 2;+;10] - Shape:
n#xs,-n#xs,n_xs,-n_xs,raze nested - Indexed assignment:
xs[1]:99,xs[where xs>20]:0 - Search/group:
xs?20,where mask,distinct xs,group xs
Common Mistakes/Pitfalls
- Forgetting
enlistwhen constructing singleton lists, rows, or nested values. - Creating a general list accidentally by mixing types when a simple typed list is needed.
- Confusing omitted index, empty index, and null item behavior.
- Assuming out-of-range indexing always errors; lists can return typed nulls in some contexts.
- Using
whereas a filter result instead of indices; apply it back to the list/table. - Forgetting that
x 1 2selects two items, whilex[1;2]descends two levels.
Small Examples
xs:10 20 30 40
xs 1 3
xs where xs>25
nested:(1 2 3;10 20 30)
nested[1;2]
/ Boolean selection is two steps: make indices, then index.
idx:where xs within 20 40
xs idx
/ Matrix-style selection.
m:(1 2 3;10 20 30)
m[;1]
m[0 1;2]
/ Preserve nested rows with enlist.
(enlist `IBM`MSFT),enlist `AAPLCross-Links
- chapter-02-basic-data-types-atoms.md
- chapter-04-operators.md
- chapter-06-functions.md
4. Operators
Source URL: https://code.kx.com/q4m3/4_Operators/
Agent-Relevant Takeaways
- Operators and keywords are functions. Unary and binary forms can differ.
- q has no traditional operator precedence. Evaluation is "left of right": a function applies to the expression on its right.
- Many primitive functions are atomic: they automatically extend item-wise over lists.
- Match
~tests structural equivalence;=tests item-wise equality. - Amend
:is the core update mechanism for lists, dictionaries, and tables.
q Syntax/Forms That Matter
- Unary application:
f x; binary application:x f y - Equality/disequality:
=,<>; match:~ - Arithmetic:
+,-,*,%; integer division/modulus:div,mod - Greater/lesser:
|,& - Amend:
@[target;index;fn],.[target;path;fn] - Alias/view:
::
Common Mistakes/Pitfalls
- Writing arithmetic as if
*binds tighter than+. - Using
=when a whole-result equality check needs~. - Missing parentheses around the right argument of a binary operator.
- Confusing amend in-place effects with expressions that return modified copies.
Small Examples
/ Be explicit for generated code.
(2*3)+4
2*(3+4)
1 2 3 = 1 0 3
1 2 3 ~ 1 2 3
@[10 20 30;1;+;5]Cross-Links
- chapter-01-q-shock-and-awe.md
- chapter-03-lists.md
- chapter-06-functions.md
5. Dictionaries
Source URL: https://code.kx.com/q4m3/5_Dictionaries/
Agent-Relevant Takeaways
- A dictionary maps keys to values and is built with
!. - Lookup uses function/index notation:
d keyord[key]. - Dictionaries generalize lists: lists map integer positions to items; dictionaries use explicit keys.
- A table starts as a column dictionary whose values are same-length column lists, then
flipgives table behavior.
q Syntax/Forms That Matter
- Dictionary: `
abc!10 20 30 `` - Key/value extraction:
key d,value d,count d - Lookup:
da,d[ac]` - Reverse lookup/find:
d?20 - Remove keys:
key _ d - Column dictionary to table:
flipc1c2!(1 2;ab)
Common Mistakes/Pitfalls
- Assuming dictionary keys must be unique; non-unique keys are possible but usually troublesome.
- Forgetting a singleton dictionary needs enlisted key/value shape.
- Expecting lookup of a missing key to behave like every other language map; q returns a null appropriate to the value type in many cases.
- Joining dictionaries with overlapping keys without checking which value wins.
Small Examples
d:`bid`ask!101.2 101.4
d `ask
cols:`sym`px`size!(`IBM`MSFT;101.2 250.5;100 200)
t:flip colsCross-Links
- chapter-03-lists.md
- chapter-08-tables.md
- chapter-09-queries-q-sql.md
6. Functions
Source URL: https://code.kx.com/q4m3/6_Functions/
Agent-Relevant Takeaways
- q functions are data and can be assigned, passed, projected, and applied dynamically.
- Explicit parameters use
{[x;y] ...}; implicit parametersx,y,zare available for short lambdas. - q uses call-by-name evaluation for function arguments, which matters for side effects and repeated evaluation.
- Projection fixes some arguments and returns a new function.
- Iterators (
each,over,scan, etc.) are essential for idiomatic q. - q has no lexical closures over local variables; pass captured values explicitly or via projection.
- General application (
.) applies a function to an argument list and is useful for dynamic calls.
q Syntax/Forms That Matter
- Function definition:
f:{[x;y] x+y} - Anonymous function call:
{x*x} 5 - Nullary function:
{[] .z.P} - Early return/signal:
:value,'error - Projection:
add10:+[10;],within5_9:within[;5 9] - Iterators:
f each xs,xs f' ys,x f/: ys,xs f\: y,f/[init;xs],f\ xs,f':xs - General apply:
f . args - Identity:
::
Common Mistakes/Pitfalls
- Overusing explicit loops instead of atomic functions or iterators.
- Using globals accidentally from inside functions.
- Forgetting semicolons separate expressions inside function bodies.
- Creating projections with omitted arguments in the wrong position.
- Assuming every function is atomic; user functions need
eachor explicit atomic construction when list behavior differs. - Expecting a nested helper function to see the caller's locals automatically.
- Using
overwherescanis needed to retain intermediate states.
Small Examples
vwap:{[px;sz] sz wavg px}
vwap[101 102 103;100 200 100]
scale:{[m;x] m*x}
double:scale[2;]
double 10 20 30
sum2:{x+y}/[0;1 2 3 4]
running:{x+y}\[0;1 2 3 4]
({x*y} . 6 7)
prices:100 101 99 105f
-':pricesCross-Links
- chapter-04-operators.md
- chapter-10-execution-control.md
- appendix-a-built-in-functions.md
7. Transforming Data
Source URL: https://code.kx.com/q4m3/7_Transforming_Data/
Agent-Relevant Takeaways
typeis the first diagnostic for atom/list/table/dictionary behavior.- Cast with type symbols or type chars; some casts widen safely, while narrowing can overflow or lose precision.
string,$,value, and parsing forms bridge text and q values.- Typed empty lists are required for robust schemas.
- Enumerations normalize repeated symbols and underpin foreign keys and persisted symbol domains.
svandvsjoin/split text or symbols and are safer building blocks than ad hoc concatenation.- Parse text with expected types; use
valueonly for controlled q expressions.
q Syntax/Forms That Matter
- Type check:
type x - Cast: `
int$42.0 `,"I"$"42"` - Text conversion:
string x,value "1 2 3" - Split/join:
"," vs "a,b,c","," sv ("a";"b";"c") - Typed empty: `
symbol$()`,float$()`` - Enumeration:
city:londonparis, then `city$londonparislondon; resolve withvalue e` - Fill/coalesce after cast:
^[0N;42]
Common Mistakes/Pitfalls
- Parsing untrusted text with
valuewithout controlling the input. - Forgetting cast is atomic and applies across lists.
- Narrowing numeric data without checking range/null behavior.
- Misusing enumerations before the domain exists or failing to persist/load symbol domains with databases.
- Extending enum domains accidentally during ingest instead of validating against an expected set.
- Converting user text to symbols in a long-lived process without a bounded domain.
- Treating
"J"$txtparsing failures as data-quality successes.
Small Examples
schema:([] sym:`symbol$(); ts:`timestamp$(); px:`float$(); size:`long$())
type each schema
`int$10.9 20.1
"J"$("100";"200";"300")
parts:"," vs "IBM,101.5,200"
(`symbol$first parts;"F"$parts 1;"J"$parts 2)
city:`london`paris
e:`city$`london`paris`london
value eCross-Links
- chapter-02-basic-data-types-atoms.md
- chapter-08-tables.md
- chapter-14-introduction-to-kdb.md
8. Tables
Source URL: https://code.kx.com/q4m3/8_Tables/
Agent-Relevant Takeaways
- A q table is a flipped column dictionary; columns are equal-length lists.
- Table definition syntax
([] c1:...; c2:...)is preferred for clarity. - Use
meta,cols,count,key, andvalueto inspect tables and keyed tables. - Keyed tables are dictionaries from key table to value table.
- Foreign keys and virtual columns let one table reference another.
- Attributes can improve search/sort/group performance but must match data properties.
- Use
xkeyor keyed-table definition syntax to key by one or more columns; use0!ktto unkey. - A table row is a dictionary; selecting multiple keyed rows requires key-shaped data, often via
([] keycol:...). key ktreturns the key table;keys ktreturns key column names.
q Syntax/Forms That Matter
- Table:
([] sym:IBMMSFT; px:101.2 250.5) - Empty schema:
([] sym:symbol$(); px:float$()) - Keyed table:
([sym:IBMMSFT] px:101.2 250.5) - Key/unkey: `
sym xkey t `,0!kt; key data:key kt; key names:keys kt` - Metadata:
meta t; column access:t.sym,t[sym]` - Records:
first t,t 0,t[0;px],enlist rowdict` - Attribute apply: `
s#xs `,p#xs `,g#xs ``
Common Mistakes/Pitfalls
- Creating scalar columns without matching row count or
enlist. - Forgetting keyed tables are not the same shape as ordinary tables.
- Updating key columns as if they were normal value columns.
- Adding attributes to data that is not actually sorted/parted/grouped/unique.
- Looking up a keyed table with a bare symbol when the key shape is a row/table.
- Assuming
key ktreturns just column names; it returns the key table. - Assuming key values are always unique; duplicate keys can make lookup/update results surprising.
Small Examples
trades:([] time:09:30 09:31 09:32; sym:`IBM`IBM`MSFT; px:101 102 250f; size:100 50 200)
meta trades
select last px by sym from trades
quotes:([sym:`IBM`MSFT] bid:100.9 249.8; ask:101.1 250.2)
quotes `IBM
kt:`sym xkey trades
keys kt
key kt
kt ([] sym:`IBM`MSFT)
kt2:`sym`time xkey trades
kt2 ([] sym:`IBM`IBM; time:09:30 09:31)
0!ktCross-Links
- chapter-05-dictionaries.md
- chapter-09-queries-q-sql.md
- chapter-14-introduction-to-kdb.md
9. Queries: q-sql
Source URL: https://code.kx.com/q4m3/9_Queries_q-sql/
Agent-Relevant Takeaways
- q-sql templates are q expressions for table work, not ANSI SQL.
- Main templates:
select,update,delete,insert, andupsert. - Phrase order matters: q-sql template order is
select ... by ... from ... where ..., not ANSI SQL order. wherefilters are vector boolean expressions; multiple where subphrases are conjunctive.bygroups and can also key results.- Joins, parameterized queries, views, and functional forms support dynamic applications.
execreturns column values or dictionaries rather than a table; use it for extraction, not row-preserving results.- Functional forms mirror templates:
?for select/exec and!for update/delete. - Join choice depends on key shape, duplicate handling, temporal ordering, and whether unmatched left rows must survive.
q Syntax/Forms That Matter
- Select:
select cols by group from t where pred - Exec:
exec px by sym from trades - Aggregate:
select avg px, sum size by sym from trades - Group-relative filter:
select from trades where px=max px fby sym - Update:
update notional:px*size from trades - Delete rows/cols:
delete from t where pred,delete col from t - Insert/upsert:
insert[t;row],upsert[t;rows] - Functional select/exec:
?[t;constraints;by;select] - Functional update/delete:
![t;constraints;by;updates] - Functional dictionaries:
select/updatesare `newcol`, expressions;byis0b` or a grouping dictionary. - Common joins:
lj,ij,ej,pj,aj,wj,uj,, - Join operand rules:
lj/ijcommonly take an unkeyed left table and keyed right table;ejtakes join columns plus two tables;aj/wjrequire ordered temporal columns.
Common Mistakes/Pitfalls
- Mixing SQL phrase order into q and producing invalid templates.
- Forgetting
insertmutates a named table while many queries return new tables. - Not enlisting singleton rows.
- Using dynamic q-sql strings when functional forms would be safer.
- Ignoring keyed-table semantics for upsert.
- Building functional
wherewith a bare predicate instead of a list of constraints. - Forgetting to enlist literal symbols in functional expressions, e.g. `
(=;sym;enlistIBM)`. - Using
ujfor conforming tables when,orrazeis cheaper. - Running
ajon unsorted temporal data or with the time column in the wrong join-column position.
Small Examples
trades:([] time:2026.06.16D09:30 2026.06.16D09:31 2026.06.16D09:32; sym:`IBM`IBM`MSFT; px:101 102 250f; size:100 50 200)
select vwap:size wavg px, volume:sum size by sym from trades where size>50
update side:$[px>200;`high;`low] from trades
/ Dynamic column selection with functional form pieces.
?[trades;enlist (>;`size;50);0b;`sym`px!`sym`px]
/ Dynamic aggregate by symbol.
?[trades;();enlist[`sym]!enlist `sym;enlist[`vwap]!enlist (wavg;`size;`px)]
/ Functional update/delete by table name.
![`trades;enlist (=;`sym;enlist `IBM);0b;(enlist `notional)!enlist (*;`px;`size)]
![`trades;enlist (<;`size;100);0b;()]
/ Join operand shapes.
inst:([] sym:`IBM`MSFT; sector:`tech`tech)
trades lj `sym xkey inst
ej[`sym;trades;inst]
/ As-of join: quote current at each trade time.
quotes:([] time:2026.06.16D09:29 2026.06.16D09:31; sym:`IBM`IBM; bid:100 101f; ask:101 102f)
aj[`sym`time;trades;quotes]
w:-0D00:00:02.000000000 0D00:00:01.000000000+\:trades`time
wj[w;`sym`time;trades;(quotes;(max;`ask);(min;`bid))]Cross-Links
- chapter-08-tables.md
- chapter-06-functions.md
- chapter-14-introduction-to-kdb.md
10. Execution Control
Source URL: https://code.kx.com/q4m3/10_Execution_Control/
Agent-Relevant Takeaways
- q has conditional forms, loops, early return, signal, protected evaluation, debugging, and script loading.
- Prefer vector conditionals and q-sql/vector operations over
whileanddofor data work. $[...]is an expression and returns a value;ifis for side-effect statements and has no else result.- Protected evaluation is essential around file, IPC, parse, and dynamic execution boundaries.
q Syntax/Forms That Matter
- Conditional expression:
$[cond;trueExpr;falseExpr] - Vector conditional:
?[mask;trueValues;falseValues] - Statement conditional:
if[cond; expr1; expr2] - Loop:
do[n; expr],while[cond; expr] - Return:
:value; signal error:'msg - Protected eval:
@[f;x;handler],.[f;args;handler] - Load script:
\l file.q
Common Mistakes/Pitfalls
- Using
$[v;...]to test null; testnull vexplicitly. - Expecting
ifto return a useful else value. - Writing loops for columnar data that should be vectorized.
- Swallowing errors in protected evaluation without surfacing context.
Small Examples
classify:{[px] $[px>100;`rich;`cheap]}
classify each 99 101 102
safeValue:{[txt] @[value;txt;{`parseFailed,x}]}
safeValue "1+2"Cross-Links
- chapter-06-functions.md
- chapter-11-io.md
- appendix-b-error-messages.md
11. I/O
Source URL: https://code.kx.com/q4m3/11_IO/
Agent-Relevant Takeaways
- q uses handles for files, processes, sockets, HTTP, and WebSockets.
- Symbols beginning with
:represent file handles;hsymhelps safely form handles from paths. - q values can be serialized/deserialized as binary; tables can be saved, loaded, or splayed.
- Text I/O requires explicit parsing and type conversion.
- IPC supports synchronous and asynchronous remote execution. Treat remote input as code execution risk.
- Prefer remote function calls with typed arguments over interpolated q strings.
- Use protected evaluation around handles so connection errors and close failures are visible.
q Syntax/Forms That Matter
- File handle: `
:/path/file `,hsym$"/path with spaces/file.csv" - Binary set/get:
handle set value,get handle - Text lines:
read0 handle,handle 0: lines - CSV-like load:
("SFI"; enlist ",") 0: handle - Open/close:
hopen,hclose - IPC:
h:hopen:host:port, synch "2+2"orh({x+y};2;3), asyncneg[h] "expr"` - Remote query call:
h({[t;s] select from get t where sym in s};trades;syms)` - Remote update call:
neg[h] (upd;trades;enlist row)
Common Mistakes/Pitfalls
- Building file handles by string concatenation instead of
hsym. - Loading text without specifying types and delimiters.
- Forgetting to close handles in long-running processes.
- Sending unsanitized strings for remote execution.
- Confusing serialized single-file tables with splayed directories.
- Forgetting async sends return immediately and errors surface on the remote side.
- Assuming a file handle, process handle, and HTTP handle have identical close/error behavior.
Small Examples
path:hsym `$"/tmp/prices.csv"
rows:("SFI"; enlist ",") 0: path
h:hopen `:localhost:5010
r:@[h;({x+y};2;3);{`ipcError,x}]
neg[h] (`upd;`trades;enlist `sym`px!(`IBM;101.5))
@[hclose;h;{`closeError,x}]Cross-Links
- chapter-07-transforming-data.md
- chapter-10-execution-control.md
- chapter-14-introduction-to-kdb.md
12. Workspace Organization
Source URL: https://code.kx.com/q4m3/12_Workspace_Organization/
Agent-Relevant Takeaways
- q organizes names in contexts, which work like namespaces and dictionaries.
- The default context is
.. Application code commonly uses named contexts such as.app. - Contexts can be created, inspected, saved, loaded, and expunged.
- Namespacing is important for reusable libraries and for avoiding global-name collisions in long-running processes.
q Syntax/Forms That Matter
- Qualified name:
.ns.name - Change context:
\d .ns; return default:\d . - Get/set by symbol:
get.ns.name,set[.ns.name;value] - Context dictionary: `
.ns `` - Delete name:
delete name from.ns` or expunge via system command patterns
Common Mistakes/Pitfalls
- Loading scripts that define globals in
.unexpectedly. - Forgetting the active context after
\d. - Confusing OS paths with q contexts because both use dotted or separated naming conventions.
- Deleting or overwriting names in shared contexts.
Small Examples
.risk.limit:1000000
.risk.check:{[notional] notional<.risk.limit}
.risk.check 500000Cross-Links
- chapter-10-execution-control.md
- chapter-13-commands-and-system-variables.md
13. Commands and System Variables
Source URL: https://code.kx.com/q4m3/13_Commands_and_System_Variables/
Agent-Relevant Takeaways
- Backslash commands manage the q session: load files, set ports, inspect workspace, list tables/functions/variables, time expressions, and configure display/runtime options.
systemexecutes many command equivalents from q code..z.*variables expose runtime hooks, environment information, callbacks, and system state.- Use commands for diagnostics and scripts; be cautious in generated application logic.
q Syntax/Forms That Matter
- List tables/vars/functions:
\a,\v,\f - Load:
\l path/to/file.q - Context:
\d .ns - Port:
\p 5010; from code:system "p 5010" - Timing:
\t expr,\ts expr - Workspace:
\w - Display precision:
\P 12 - Common system variables:
.z.P,.z.D,.z.T,.z.K,.z.pw,.z.ts
Common Mistakes/Pitfalls
- Using command syntax inside functions where
systemis required. - Accidentally opening a port or changing global process settings in library code.
- Depending on display precision instead of actual numeric value.
- Forgetting timer callbacks can affect process behavior globally.
Small Examples
system "P 12"
.z.P
/ In the console:
\\ts select avg px by sym from tradesCross-Links
- chapter-10-execution-control.md
- chapter-12-workspace-organization.md
- chapter-11-io.md
14. Introduction to Kdb+
Source URL: https://code.kx.com/q4m3/14_Introduction_to_Kdb%2B/
Agent-Relevant Takeaways
- kdb+ persists q tables as serialized, splayed, partitioned, or segmented data on disk.
- Splayed tables store each column as a separate file in a table directory.
- Partitioned tables add a partition directory, most often by date, so queries can prune data.
- Symbol columns in persisted databases require a symbol domain file, commonly
sym. - Query performance depends heavily on partition filters, column selection, attributes, and avoiding unnecessary materialization.
- Mapped splayed/partitioned tables are not ordinary in-memory tables for every operation.
- Partitioned tables expose the partition as a virtual column, commonly
date;iis row number within each partition.
q Syntax/Forms That Matter
- Serialize table: `
:/db/t set t `` - Splay: `
:/db/trades/ set .Q.en[:db] trades` (adapt to actual database root/domain) - Load database:
\l /path/to/db - Partitioned query pattern:
select ... from trades where date within d0 d1, sym in syms - Daily partition write pattern: `
:/db/2026.06.16/trades/ set .Q.en[:db] delete date from dayTrades` - Inspect:
tables[],meta trades,count trades - Utility family:
.Q.*helpers for enumeration, splay, and database operations.
Common Mistakes/Pitfalls
- Querying partitioned tables without a partition constraint.
- Persisting symbol columns without managing the symbol file/domain.
- Treating splayed tables like ordinary in-memory tables for all updates.
- Appending data with mismatched schema or attributes.
- Forgetting
QHOME/working-directory assumptions in scripts. - Using
exec from partitionedTabledirectly where aselectwrapper is needed. - Filtering on virtual
iwithout a partition constraint, returning rows from each partition. - Persisting the virtual partition column inside each partition instead of removing it before write.
Small Examples
/ Shape a daily partition query to prune first, then aggregate.
select vwap:size wavg px by sym from trades
where date=2026.06.16, sym in `IBM`MSFT
/ Write one date partition with enumerated symbols.
root:`:/db
`:/db/2026.06.16/trades/ set .Q.en[root] delete date from dayTrades
\l /db
/ Pull columns through select first, then exec from the smaller result.
exec px from select px from trades where date=2026.06.16, sym=`IBMCross-Links
- chapter-08-tables.md
- chapter-09-queries-q-sql.md
- chapter-11-io.md
Colophon
Source URL: https://code.kx.com/q4m3/colophon/
Agent-Relevant Takeaways
- The colophon describes publication/tooling context for the HTML edition.
- It is relevant for attribution and source provenance, not q programming technique.
q Syntax/Forms That Matter
- None.
Common Mistakes/Pitfalls
- Treating publication metadata as language semantics.
- Omitting attribution to Q for Mortals/KX when using these notes.
Small Examples
/ No q example needed for publication metadata.Cross-Links
- preface.md
- chapter-00-overview.md
Executable Examples
Small q snippets that should run as-is in a scratch KDB-X/q process. Prefer adapting these before inventing syntax.
Lists and Rank
xs:10 20 30 40
xs where xs>20
count enlist 42
nested:(1 2 3;10 20 30)
nested[1;2]Dictionaries and Keyed Lookup
d:`IBM`MSFT!101 250f
d`IBM
key d
quotes:([sym:`IBM`MSFT] bid:100.9 249.8; ask:101.1 250.2)
quotes `IBM
quotes ([] sym:`IBM`MSFT)Tables and q-sql
trades:([] time:09:30 09:31 09:32; sym:`IBM`IBM`MSFT; px:101 102 250f; size:100 50 200)
meta trades
select vwap:size wavg px, volume:sum size by sym from trades where size>50
update notional:px*size from tradesFunctional q-sql
trades:([] sym:`IBM`MSFT`IBM; px:101 250 103f; size:100 200 50)
?[trades;enlist (>;`size;50);0b;`sym`px!`sym`px]
?[trades;();enlist[`sym]!enlist `sym;enlist[`vwap]!enlist (wavg;`size;`px)]Joins
trades:([] sym:`IBM`MSFT`IBM; px:101 250 103f; size:100 200 50)
inst:([] sym:`IBM`MSFT; sector:`tech`software)
trades lj `sym xkey inst
ej[`sym;trades;inst]Time-Series Join
quotes:([] time:09:30:00.000 09:30:01.000 09:30:02.000; sym:`IBM`IBM`IBM; bid:100 101 102f; ask:101 102 103f)
trades:([] time:09:30:01.500 09:30:02.500; sym:`IBM`IBM; px:101.2 102.4)
aj[`sym`time;trades;quotes]CSV I/O
p:`$":/tmp/prices.csv"
p 0:("sym,px";"IBM,101.5";"MSFT,250.25");
prices:("SF";enlist ",") 0:p
pricesq Language Reference Index
Source base: https://code.kx.com/q4m3/
These notes summarize Q for Mortals 3.1 for agents writing q. They are navigation aids, not a replacement for the source book.
Start Here
- Task recipes for common agent work: recipes.md
- Pasteable known-good snippets: executable-examples.md
- Generated-code review traps: anti-patterns.md
- New q code or unfamiliar syntax: chapter-01-q-shock-and-awe.md
- q-sql query, joins, functional forms: chapter-08-tables.md, chapter-09-queries-q-sql.md
- Atom/list/rank/type issue: chapter-02-basic-data-types-atoms.md, chapter-03-lists.md, chapter-07-transforming-data.md
- Function, projection, iterator, or evaluation issue: chapter-04-operators.md, chapter-06-functions.md
- Table schemas, keys, foreign keys, attributes: chapter-08-tables.md
- Insert/upsert/join/parameterized query/dynamic query: chapter-09-queries-q-sql.md
- File, text parsing, IPC, HTTP, WebSocket, persistence: chapter-11-io.md
- Namespaces, contexts, scripts, runtime commands: chapter-10-execution-control.md, chapter-12-workspace-organization.md, chapter-13-commands-and-system-variables.md
- Splayed/partitioned kdb+ database work: chapter-14-introduction-to-kdb.md
- Built-in lookup: appendix-a-built-in-functions.md
- Error diagnosis: appendix-b-error-messages.md
Compact Agent References
- recipes.md: CSV loading, keyed tables, q-sql aggregation, rank/type debugging, partitioned-table probes, and time-series joins.
- executable-examples.md: small snippets for lists, dictionaries, tables, joins, q-sql, functional q-sql, and I/O.
- anti-patterns.md: common LLM mistakes and safer q idioms.
Required Source Coverage
- preface.md
- chapter-00-overview.md
- chapter-01-q-shock-and-awe.md
- chapter-02-basic-data-types-atoms.md
- chapter-03-lists.md
- chapter-04-operators.md
- chapter-05-dictionaries.md
- chapter-06-functions.md
- chapter-07-transforming-data.md
- chapter-08-tables.md
- chapter-09-queries-q-sql.md
- chapter-10-execution-control.md
- chapter-11-io.md
- chapter-12-workspace-organization.md
- chapter-13-commands-and-system-variables.md
- chapter-14-introduction-to-kdb.md
- appendix-a-built-in-functions.md
- appendix-b-error-messages.md
- colophon.md
Preface
Source URL: https://code.kx.com/q4m3/preface/
Agent-Relevant Takeaways
- Q for Mortals 3.1 targets q 3.2 era behavior and the KX HTML edition updates terminology to common modern usage.
- The online edition is published by KX with permission and links into the KX q reference.
- Use these notes as practical guidance, then verify current production behavior against the installed q/kdb+ version when available.
q Syntax/Forms That Matter
- No q syntax is introduced here.
- Terminology mapping matters: older "monadic/dyadic" corresponds to unary/binary; "verbs/adverbs" corresponds to operators/iterators in current KX wording.
Common Mistakes/Pitfalls
- Assuming every phrase in older q material uses current KX terminology.
- Treating the book as a version guarantee for newer q releases.
Small Examples
/ Check runtime version in an available q session
.z.KCross-Links
- chapter-00-overview.md
- appendix-a-built-in-functions.md
Recipes
Use these as compact starting points for common q/kdb+ tasks. Confirm column names and types with meta, cols, count, and small bounded probes before broad queries.
Load CSV
/ Header row names the columns; schema chars type the data rows.
p:`$":/data/prices.csv"
prices:("SFJ";enlist ",") 0:p
meta pricesFor nonstandard text, read lines with read0, drop or transform headers deliberately, then parse; do not assume ANSI SQL import behavior.
Create and Use Keyed Tables
quotes:([sym:`IBM`MSFT] bid:100.9 249.8; ask:101.1 250.2)
quotes `IBM
trades:([] sym:`IBM`MSFT`IBM; px:101 250 103f; size:100 200 50)
kt:`sym xkey trades
kt ([] sym:`IBM`MSFT)
0!ktUse key-shaped lookup data for multi-row keyed-table access. key kt returns key data; keys kt returns key column names.
q-sql Aggregation
trades:([] sym:`IBM`MSFT`IBM; px:101 250 103f; size:100 200 50)
select vwap:size wavg px, volume:sum size, hi:max px by sym from trades where size>0q-sql phrase order is select ... by ... from ... where .... where predicates are vector expressions and multiple comma-separated predicates are conjunctive.
Debug Rank and Type Errors
type x
count x
0N!x
meta t
enlist xCheck whether a value is an atom, singleton list, table row, or one-row table. Use enlist to preserve a single row/list/key; use typed empties like ` long$()`` in schemas.
Query Partitioned Tables
\l /data/hdb
meta trade
select[10] from trade where date=2026.06.16,sym=`IBM
select sum size by sym from trade where date within 2026.06.10 2026.06.16,sym in `IBM`MSFTPut the partition constraint first, keep probes bounded, and avoid unqualified select from bigtable on HDB data.
Build Time-Series Joins
quotes:`sym`time xasc quotes
trades:`sym`time xasc trades
aj[`sym`time;trades;quotes]Use aj for latest quote at or before each trade. Ensure the temporal column is last in the join column list and both tables are ordered by symbol/time.
#!/usr/bin/env python3
"""Structural checks for the q-language skill."""
from __future__ import annotations
import re
import shutil
import subprocess
import sys
import tempfile
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
REPO = ROOT.parent
REFERENCES = ROOT / "references"
REQUIRED_REFERENCE_FILES = [
"index.md",
"preface.md",
"chapter-00-overview.md",
"chapter-01-q-shock-and-awe.md",
"chapter-02-basic-data-types-atoms.md",
"chapter-03-lists.md",
"chapter-04-operators.md",
"chapter-05-dictionaries.md",
"chapter-06-functions.md",
"chapter-07-transforming-data.md",
"chapter-08-tables.md",
"chapter-09-queries-q-sql.md",
"chapter-10-execution-control.md",
"chapter-11-io.md",
"chapter-12-workspace-organization.md",
"chapter-13-commands-and-system-variables.md",
"chapter-14-introduction-to-kdb.md",
"appendix-a-built-in-functions.md",
"appendix-b-error-messages.md",
"colophon.md",
]
AUX_REFERENCE_FILES = [
"anti-patterns.md",
"executable-examples.md",
"recipes.md",
]
REQUIRED_HEADINGS = [
"Source URL:",
"## Agent-Relevant Takeaways",
"## q Syntax/Forms That Matter",
"## Common Mistakes/Pitfalls",
"## Small Examples",
"## Cross-Links",
]
def fail(message: str) -> None:
print(f"FAIL: {message}")
sys.exit(1)
def check_skill_frontmatter() -> None:
text = (ROOT / "SKILL.md").read_text()
if not text.startswith("---\n"):
fail("SKILL.md missing YAML frontmatter")
try:
_, fm, _ = text.split("---\n", 2)
except ValueError:
fail("SKILL.md frontmatter is not closed")
keys = [line.split(":", 1)[0] for line in fm.splitlines() if line.strip()]
if keys != ["name", "description"]:
fail(f"SKILL.md frontmatter keys must be only name and description, got {keys}")
if "name: q-language" not in fm:
fail("SKILL.md name must be q-language")
def check_openai_yaml() -> None:
text = (ROOT / "agents" / "openai.yaml").read_text()
required = [
'display_name: "q Language"',
"short_description:",
"default_prompt:",
"allow_implicit_invocation: true",
]
for item in required:
if item not in text:
fail(f"openai.yaml missing {item}")
if "$q-language" not in text:
fail("openai.yaml default_prompt must mention $q-language")
def check_references() -> None:
for name in [*REQUIRED_REFERENCE_FILES, *AUX_REFERENCE_FILES]:
path = REFERENCES / name
if not path.exists():
fail(f"missing reference {name}")
if name in REQUIRED_REFERENCE_FILES and name != "index.md":
text = path.read_text()
for heading in REQUIRED_HEADINGS:
if heading not in text:
fail(f"{name} missing {heading}")
if "https://code.kx.com/q4m3/" not in text:
fail(f"{name} missing q4m3 source URL")
def check_local_links() -> None:
link_re = re.compile(r"\[[^\]]+\]\(([^)]+\.md)(?:#[^)]+)?\)")
for path in [ROOT / "SKILL.md", REPO / "README.md", *REFERENCES.glob("*.md")]:
text = path.read_text()
base = path.parent
for link in link_re.findall(text):
target = (base / link).resolve()
if not target.exists():
fail(f"{path.relative_to(REPO)} has broken link to {link}")
def find_q() -> str | None:
return shutil.which("q") or (
str(Path("/opt/data/home/.kx/bin/q"))
if Path("/opt/data/home/.kx/bin/q").exists()
else None
)
def run_q(q_path: str, program: str) -> str:
result = subprocess.run(
[q_path, "-q"],
input=f"{program.rstrip()}\n\\\n",
text=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
timeout=10,
check=False,
)
if result.returncode != 0:
fail(f"q semantic test failed: {result.stderr.strip() or result.stdout.strip()}")
return result.stdout
def assert_contains(output: str, expected: list[str], label: str) -> None:
missing = [item for item in expected if item not in output]
if missing:
fail(f"q semantic test {label} missing {missing!r}; output was:\n{output}")
def check_q_runtime(q_path: str) -> None:
semantic_cases = [
(
"lists",
"""
show "CASE lists"
xs:10 20 30 40
show xs where xs>20
show count enlist 42
""",
["CASE lists", "30 40", "1"],
),
(
"dictionaries",
"""
show "CASE dictionaries"
d:`IBM`MSFT!101 250f
show d`IBM
show key d
""",
["CASE dictionaries", "101f", "`IBM`MSFT"],
),
(
"qsql aggregation",
"""
show "CASE qsql"
trades:([] sym:`IBM`MSFT`IBM; px:101 250 103f; size:100 200 50)
show select vwap:size wavg px, volume:sum size by sym from trades
""",
["CASE qsql", "IBM", "101.6667", "150", "MSFT", "250", "200"],
),
(
"joins",
"""
show "CASE joins"
trades:([] sym:`IBM`MSFT`IBM; px:101 250 103f; size:100 200 50)
inst:([] sym:`IBM`MSFT; sector:`tech`software)
show trades lj `sym xkey inst
show (`sym xkey inst)`IBM
""",
["CASE joins", "sector", "software", "sector| tech"],
),
(
"asof join",
"""
show "CASE aj"
quotes:([] time:09:30:00.000 09:30:01.000 09:30:02.000; sym:`IBM`IBM`IBM; bid:100 101 102f; ask:101 102 103f)
trades:([] time:09:30:01.500 09:30:02.500; sym:`IBM`IBM; px:101.2 102.4)
show aj[`sym`time;trades;quotes]
""",
["CASE aj", "09:30:01.500", "101.2", "101", "102.4", "103"],
),
]
for label, program, expected in semantic_cases:
assert_contains(run_q(q_path, program), expected, label)
with tempfile.TemporaryDirectory(prefix="q-skill-") as tmp:
csv_path = Path(tmp) / "prices.csv"
output = run_q(
q_path,
f"""
show "CASE csv"
p:`$":{csv_path}"
p 0:("sym,px";"IBM,101.5";"MSFT,250.25");
t:("SF";enlist ",") 0:p
show t
show meta t
""",
)
assert_contains(output, ["CASE csv", "IBM", "101.5", "MSFT", "250.25", "sym| s", "px | f"], "csv")
def main() -> None:
check_skill_frontmatter()
check_openai_yaml()
check_references()
check_local_links()
q_path = find_q()
print("structural validation: ok")
if q_path:
check_q_runtime(q_path)
print(f"q runtime detected: {q_path}; semantic snippet suite: ok")
else:
print("q runtime detected: no; validation is structural only")
if __name__ == "__main__":
main()