Jump to content

Module:Cargo query/doc

From HopperWiki

This is the documentation page for Module:Cargo query

This module is the single entry point for all Cargo queries on HopperWiki. It wraps mw.ext.cargo.query() with schema-aware WHERE clause construction, automatic type detection, result parsing, deduplication, and table rendering.

The primary function is p.query (aliased as p.q). p.resource_query is a human-friendly wrapper over it for the Resource table. The older functions — filter_cargo_table_enhanced, filter_cargo_table, cargo_query, and thin_cargo_wrapper — have been removed; every template that called them has been migrated to p.query.

Architecture

The query pipeline runs in a fixed order regardless of which tier is used.

Stage 1 · Arguments Stage 2 · WHERE clause Stage 3 · Query + parse Stage 4 · Render

Resolve args from frame and parent frame. Apply alias fallbacks. Build label map with automatic underscore→space defaults.

Detect tier from args present. Build WHERE clause via schema-aware escaping. HOLDS vs = determined from field type.

Run cargo.query(). Parse raw results into typed Lua structures via parse_cargo_results(). Apply file fallbacks. Deduplicate. Transform URL fields.

Evaluate collapse threshold. Render via generate_wiki_table_enhanced(), bulleted_list(), or return count string.

Tiers

The WHERE clause tier is detected automatically from which arguments are present. You never declare which tier you are using — the module infers it.

Tier Detected when Use case
1 · Single field filter_field is present and filters and where are absent One focal field, one or more include values, optional excludes against the same field
2 · Multi-field structured filters is present and where is absent Multiple fields composed with AND; values within a field composed with OR; schema-aware escaping applied automatically
3 · Raw WHERE where is present Full escape hatch — passed directly to Cargo. Use when Tier 2 cannot express the logic (date comparisons, LIKE, IS NULL) or when a value must be a template parameter substituted before #invoke runs

Tier detection priority: where wins over filters wins over filter_field. If none are present the query returns all rows — the caller's responsibility.

Parameters

Required

Parameter Notes
table Cargo table name. Alias: cargo_table
fields Comma-separated fields to fetch from Cargo. Aliases: cargo_fields, query_fields

Display

Parameter Default Notes
display_fields Same as fields Fields to show as columns. Fetch a field in fields but omit it here to filter on it without displaying it. Aliases: cargo_display_fields, table_columns
column_labels Underscore→space for every field Override labels for specific columns only. Format: Field_name=My label, Other_field=Other label. Fields not listed get automatic labels — you do not need to list every field.
format table table, bulleted_list, or count. count short-circuits before any rendering and returns a plain integer string.
row_cutoff 3 Rows visible before the table collapses. The CSS class row-cutoff-N is applied at N+1 internally.
character_cutoff 600 Maximum characters per cell before truncation with ellipsis. Not applied to file or list_of_file fields.
default_file_fields — Fallback image for empty file fields. Format: Field: File.jpg; OtherField: Default.png. Semicolon-separated.
options — JSON string passed to transform_link_fields(). Supports link_text and link_text_fields keys.

Tier 1 — single field

Parameter Default Notes
filter_field — The field to filter on. Must be the bare field name as declared in the Cargo schema — not Table.Field. Alias: cargo_focal_field
filter_values Current page title Comma-separated values to include. Alias: filter_value
exclude_values — Comma-separated values to exclude from the same field. Aliases: not_values, not_value

Tier 2 — multi-field structured

Parameter Notes
filters Semicolon-separated filter clauses. Each clause is one of: Field HOLDS value1, value2 · Field = value · Field != value. Clauses are joined with AND. Multiple values within a HOLDS clause are joined with OR. Schema-aware escaping is applied automatically.
excludes Semicolon-separated exclusion clauses in the same syntax. Each becomes an AND NOT fragment appended after the main filters.

Tier 3 — raw WHERE

Parameter Notes
where Passed directly to cargo.query() as the WHERE clause. No escaping applied. Template parameter substitution (e.g. Identification) happens before #invoke runs, making this the correct tier when a value must be caller-configurable.

Query modifiers (all tiers)

Parameter Notes
order_by ORDER BY clause. Example: Year_published DESC. Note: Year_published is a string field — ordering is lexicographic. Store years as zero-padded four-digit strings for correct sort behavior.
group_by GROUP BY clause.
limit Hard cap on rows returned from Cargo before any deduplication.

Clause syntax reference

Tier 2 clause fragments and how they compile:

Input clause Field type Compiled WHERE fragment
Species_purview HOLDS Melanoplus list_of_string Species_purview HOLDS 'Melanoplus'
Species_purview HOLDS Melanoplus, Chorthippus list_of_string (Species_purview HOLDS 'Melanoplus' OR Species_purview HOLDS 'Chorthippus')
Language = French list_of_string Language HOLDS 'French' (auto-upgraded to HOLDS because field is a list type)
Language = French string Language = 'French'
Language != French list_of_string NOT (Language HOLDS 'French')
Language != French string Language != 'French'
Year_published > 2000 any Passed through unchanged (no recognized operator — treated as raw fragment)

Multiple clauses in filters are joined: (...) AND (...) AND (...)

Multiple clauses in excludes each become: AND NOT (...)

Examples

Tier 1: single field, page title as filter

{{#invoke:Cargo_query|query
| table         = Resource
| fields        = Name, Year_published, Resource_link, Author
| filter_field  = All_geography
| row_cutoff    = 3
}}

Fetches resources where All_geography HOLDS Cargo query/doc. Column labels default to Name, Year published, Resource link, Author — no column_labels needed.

Tier 1: with explicit filter value and excludes

{{#invoke:Cargo_query|query
| table          = Resource
| fields         = Name, Year_published, Resource_link, Language
| filter_field   = Species_purview
| filter_values  = Melanoplus devastator
| exclude_values = Unknown
| row_cutoff     = 5
}}

Tier 2: AND across two list fields

{{#invoke:Cargo_query|query
| table    = Resource
| fields   = Name, Long_title, Year_published, Resource_link, Author, Language, Descriptive_keyword
| display_fields = Name, Long_title, Year_published, Resource_link, Author, Language
| filters  = Species_purview HOLDS {{PAGENAME}}; Descriptive_keyword HOLDS Identification
| excludes = Language = Chinese; Language = Japanese
| order_by = Year_published DESC
| row_cutoff = 5
}}

Descriptive_keyword is fetched but excluded from display_fields — it drives the filter without appearing as a column.

Tier 2: geographic region + category

{{#invoke:Cargo_query|query
| table    = Resource
| fields   = Name, Long_title, Year_published, Resource_link, Author, Category
| filters  = All_geography HOLDS {{PAGENAME}}; Category = Media
| order_by = Year_published DESC
| limit    = 10
| row_cutoff = 5
}}

Tier 3: raw WHERE with template parameter

{{#invoke:Cargo_query|query
| table  = Resource
| fields = Name, Year_published, Resource_link
| where  = Species_purview HOLDS '{{PAGENAME}}' AND Descriptive_keyword HOLDS '{{{keyword|Identification}}}'
}}

Use Tier 3 when a value must be a caller-configurable template parameter. The Identification substitution happens before #invoke runs, which Tier 2 cannot accommodate.

Count format for conditional section display

{{#ifexpr: {{#invoke:Cargo_query|query
| table        = Resource
| fields       = Name
| filter_field = Species_purview
| format       = count
}} > 0 | {{Species resources}} }}

Post-query pipeline

After cargo.query() returns, results pass through these steps in order:

  1. Parse — parse_cargo_results() splits list fields into Lua arrays using the delimiter declared in the Cargo schema (~~ for most HopperWiki list fields). Scalar fields remain strings.
  2. File fallbacks — Empty file and list_of_file fields are replaced with the value from default_file_fields if provided.
  3. Deduplication — deduplicate_rows() removes duplicate rows across the display fields.
  4. Link transformation — transform_link_fields() rewrites url and list_of_url fields as labeled external links.
  5. Collapse — If row count ≥ row_cutoff + 1, the CSS class collapsible-cargo-table row-cutoff-N is applied.

Fetch-but-don't-display pattern

Any field listed in fields but absent from display_fields is available to the WHERE clause but does not appear as a column. This is the standard approach for filter-only fields:

| fields         = Name, Year_published, Descriptive_keyword
| display_fields = Name, Year_published
| filters        = Descriptive_keyword HOLDS Identification

Descriptive_keyword drives the filter. It never appears in the rendered table.

Known gotchas

Situation What happens Fix
filter_field = Table.Field Schema lookup fails — field not found Use bare field name only: filter_field = Species_purview
Comma in a filter value (Tier 2 HOLDS) Value is split at the comma, producing two filter tokens Move to Tier 3 and write the WHERE clause manually
Year_published DESC with non-numeric values Lexicographic sort — "circa 1987" or "unknown" sort unpredictably Store years as plain four-digit strings
limit applied before deduplication Cargo caps rows before the pipeline runs — deduplication may reduce the final count below limit Set limit generously if deduplication is expected to remove rows
column_labels listing every field with Name=Name style entries Unnecessary — automatic underscore→space handles this Omit column_labels entirely, or list only fields that need a genuinely custom label
Tier 3 with unescaped user input SQL injection risk Never pass raw user-supplied values into where=. Use Tier 1 or Tier 2 for user-supplied values.

Removed functions

filter_cargo_table_enhanced, filter_cargo_table, cargo_query (and its aliases p.cargo / p.cargo_enhanced), and thin_cargo_wrapper have been removed from this module. All templates that called them were migrated to p.query:

Old function Replacement
filter_cargo_table_enhanced p.query with filter_field
cargo_query / p.cargo / p.cargo_enhanced p.query with filters or where
thin_cargo_wrapper p.query with filters or where
filter_cargo_table Was dead code (scope errors, never callable) — deleted outright

Module family

Module:Cargo_query is one of several modules in the HopperWiki utilities family. It depends on:

Module Role
Module:Cargo query utilities Schema parsing, WHERE clause construction, row fetching
Module:Cargo format utilities Result parsing, list splitting, URL and file formatting
Module:Wiki output utilities Table and list rendering (generate_wiki_table_enhanced, bulleted_list)
Module:Utilities Re-exports all of the above for backward compatibility
Module:Arguments Frame argument processing


Cookies help us deliver our services. By using our services, you agree to our use of cookies.