The export screen
A three-step query builder over the real schema: pick a table, pick what to join to it, add conditions, download the CSV. It accepts read statements and streams their result.
/system/export is how a CSV comes out of CCC without anyone writing SQL. It builds the query for you, step by step, from the database's own structure.
The three steps
Table. The screen lists every table in the database with its row count and size, so you can see what you are about to pull before pulling it. Picking one moves to the next step.
Joins. It reads the chosen table's SHOW CREATE TABLE text, finds the columns that look like foreign keys, and offers the tables those point at as checkboxes. Tick the ones whose columns you want beside your rows.
Where. It lists the fields available across the table and its joins. Pick a field, pick an operator, type a value, submit. Conditions accumulate, so this step is repeated until the filter is what you want. Dates are entered as YYYY-MM-DD.
Then Download posts the built query to public/export.php, which streams the CSV in a new tab.
What guards it
Three gates, all required: a session, the system/export page permission, and the export module flag on the user. Holding one or two is not enough.
Then a fourth, on the statement itself: export.php refuses anything that database->isreadquery() does not read as a single read. Write statements are rejected by that check; this is an application guard, not a separate read-only database credential.
export.php receives the query base64-encoded in the POST body rather than as a form of parameters. That it accepts a statement at all is deliberately recorded posture in AGENTS.md, not an oversight: replacing it with a server-rebuilt query is a separate piece of work. In normal use the statement is the one this screen built.
What comes out
A CSV of the rows the query returned, streamed rather than assembled in memory, so a large export does not have to fit in memory_limit.
A join can multiply rows. An order joined to its lines returns one row per line, and summing the order total across that counts it once per line. See data model before exporting anything you intend to total.
Where to look instead
For a per-order figure, cm_impact_salesorders is already one row per order. For field meanings, /dictionary. For a repeatable pull that another system consumes, see consumption contracts rather than exporting by hand.
Related
Evidence
The three steps, the foreign-key discovery from SHOW CREATE TABLE and the field list from app/http/system/export.php and templates/main/system/export.tpl. The three gates, the base64 POST and the read-only statement check from AGENTS.md, Entry points and Known posture, and database->isreadquery(). Basis: code-checked against the current implementation.
- Type
page - Status
active - Updated
2026-09-14 - Created
2026-09-13 - Covers
system/export