{"database": "cp40x", "private": false, "path": "/cp40x", "size": 661966848, "tables": [{"name": "cases", "columns": ["id", "roll_id", "side", "roll_number", "image", "county", "case_type", "plaintiff", "defendant", "source_row", "source_file", "roll_label", "term", "year", "monarch", "source_downloaded_at"], "primary_keys": ["id"], "count": null, "hidden": false, "fts_table": null, "foreign_keys": {"incoming": [{"other_table": "names", "column": "id", "other_column": "case_id"}], "outgoing": [{"other_table": "rolls", "column": "roll_id", "other_column": "id"}]}, "private": false}, {"name": "import_log", "columns": ["id", "source_file", "status", "message", "rows_imported", "logged_at"], "primary_keys": ["id"], "count": 576, "hidden": false, "fts_table": null, "foreign_keys": {"incoming": [], "outgoing": []}, "private": false}, {"name": "names", "columns": ["id", "case_id", "role", "surname", "forename", "occupation", "place_id", "raw_segment", "seq"], "primary_keys": ["id"], "count": null, "hidden": false, "fts_table": null, "foreign_keys": {"incoming": [], "outgoing": [{"other_table": "places", "column": "place_id", "other_column": "id"}, {"other_table": "cases", "column": "case_id", "other_column": "id"}]}, "private": false}, {"name": "places", "columns": ["id", "place_name", "place_norm", "locality", "county", "flags"], "primary_keys": ["id"], "count": 238900, "hidden": false, "fts_table": null, "foreign_keys": {"incoming": [{"other_table": "names", "column": "id", "other_column": "place_id"}], "outgoing": []}, "private": false}, {"name": "rolls", "columns": ["id", "source_file", "roll_label", "term", "year", "indexed_by", "alphabet_slice", "row_count", "imported_at", "monarch", "aalt_roll_url", "source_downloaded_at"], "primary_keys": ["id"], "count": 138, "hidden": false, "fts_table": null, "foreign_keys": {"incoming": [{"other_table": "cases", "column": "id", "other_column": "roll_id"}], "outgoing": []}, "private": false}, {"name": "sqlite_sequence", "columns": ["name", "seq"], "primary_keys": [], "count": 5, "hidden": false, "fts_table": null, "foreign_keys": {"incoming": [], "outgoing": []}, "private": false}], "hidden_count": 0, "views": [], "queries": [{"title": "Row counts", "description": "How many cases, names, places, and rolls", "sql": "SELECT 'cases' AS table_name, COUNT(*) AS n FROM cases\nUNION ALL\nSELECT 'names', COUNT(*) FROM names\nUNION ALL\nSELECT 'places', COUNT(*) FROM places\nUNION ALL\nSELECT 'rolls', COUNT(*) FROM rolls\n", "name": "row_counts", "private": false}, {"title": "Cases by year", "description": "Counts per year. Optional start_year / end_year (defaults 1349\u20131596, the min/max years in the DB). Rows with NULL year are omitted.\n", "sql": "SELECT year, COUNT(*) AS n\nFROM cases\nWHERE year IS NOT NULL\n  AND year >= CAST(COALESCE(NULLIF(:start_year, ''), '1349') AS INTEGER)\n  AND year <= CAST(COALESCE(NULLIF(:end_year, ''), '1596') AS INTEGER)\nGROUP BY year\nORDER BY year\n", "params": ["start_year", "end_year"], "name": "cases_by_year", "private": false}, {"title": "Top surnames", "description": "Most common surnames in the year range (defaults 1349\u20131596).\n", "sql": "SELECT n.surname, COUNT(*) AS n\nFROM names n\nJOIN cases c ON c.id = n.case_id\nWHERE c.year IS NOT NULL\n  AND c.year >= CAST(COALESCE(NULLIF(:start_year, ''), '1349') AS INTEGER)\n  AND c.year <= CAST(COALESCE(NULLIF(:end_year, ''), '1596') AS INTEGER)\nGROUP BY n.surname\nORDER BY n DESC\nLIMIT 40\n", "params": ["start_year", "end_year"], "name": "top_surnames", "private": false}, {"title": "Busiest places", "description": "Places with most name links in the year range (defaults 1349\u20131596).\n", "sql": "SELECT p.place_name, p.county, COUNT(*) AS n\nFROM names n\nJOIN places p ON p.id = n.place_id\nJOIN cases c ON c.id = n.case_id\nWHERE c.year IS NOT NULL\n  AND c.year >= CAST(COALESCE(NULLIF(:start_year, ''), '1349') AS INTEGER)\n  AND c.year <= CAST(COALESCE(NULLIF(:end_year, ''), '1596') AS INTEGER)\nGROUP BY p.id\nORDER BY n DESC\nLIMIT 40\n", "params": ["start_year", "end_year"], "name": "top_places", "private": false}, {"title": "Search surname", "description": "Surname uses SQL LIKE wildcards: % (any run of characters), _ (one character). If you type neither, a trailing % is added (prefix search). Optional venue filters cases.county (court venue \u2014 often differs from the person\u2019s place county). Optional role=plaintiff|defendant (blank = both). Optional start_year / end_year default to 1349\u20131596. Includes membrane side/image, roll label, AALT roll URL when known, and source download date. Cases with NULL year are excluded.\n", "sql": "SELECT n.surname, n.forename, n.occupation,\n       p.locality, p.county,\n       c.county AS venue, c.case_type, c.year, c.term,\n       c.side, c.image, c.roll_label, c.roll_number,\n       r.aalt_roll_url, c.source_downloaded_at,\n       n.role, n.raw_segment\nFROM names n\nLEFT JOIN places p ON p.id = n.place_id\nJOIN cases c ON c.id = n.case_id\nLEFT JOIN rolls r ON r.id = c.roll_id\nWHERE n.surname LIKE (\n    CASE\n      WHEN INSTR(:surname, '%') > 0 OR INSTR(:surname, '_') > 0\n      THEN :surname\n      ELSE :surname || '%'\n    END\n  )\n  AND (NULLIF(:role, '') IS NULL OR n.role = :role)\n  AND (\n    NULLIF(:venue, '') IS NULL\n    OR c.county LIKE (\n      CASE\n        WHEN INSTR(:venue, '%') > 0 OR INSTR(:venue, '_') > 0\n        THEN :venue\n        ELSE :venue || '%'\n      END\n    )\n  )\n  AND c.year IS NOT NULL\n  AND c.year >= CAST(COALESCE(NULLIF(:start_year, ''), '1349') AS INTEGER)\n  AND c.year <= CAST(COALESCE(NULLIF(:end_year, ''), '1596') AS INTEGER)\nORDER BY c.year, n.surname\nLIMIT 100\n", "params": ["surname", "venue", "role", "start_year", "end_year"], "name": "search_surname", "private": false}, {"title": "Search surname + place / county", "description": "Surname, place, county, and venue use SQL LIKE wildcards (% and _). If a field has neither wildcard, a trailing % is added (prefix). Blank place/county/venue = no filter on that field. county = person\u2019s place county; venue = court venue (cases.county) \u2014 often different. Optional role (blank = both) and start_year / end_year (defaults 1349\u20131596). Returns case/roll fields, not names-only rows.\n", "sql": "SELECT n.surname, n.forename, n.occupation,\n       p.locality, p.county,\n       c.county AS venue, c.case_type, c.year, c.term,\n       c.side, c.image, c.roll_label, c.roll_number,\n       r.aalt_roll_url, c.source_downloaded_at,\n       n.role, n.raw_segment\nFROM names n\nLEFT JOIN places p ON p.id = n.place_id\nJOIN cases c ON c.id = n.case_id\nLEFT JOIN rolls r ON r.id = c.roll_id\nWHERE n.surname LIKE (\n    CASE\n      WHEN INSTR(:surname, '%') > 0 OR INSTR(:surname, '_') > 0\n      THEN :surname\n      ELSE :surname || '%'\n    END\n  )\n  AND (NULLIF(:role, '') IS NULL OR n.role = :role)\n  AND (\n    NULLIF(:place, '') IS NULL\n    OR p.locality LIKE (\n      CASE\n        WHEN INSTR(:place, '%') > 0 OR INSTR(:place, '_') > 0\n        THEN :place\n        ELSE :place || '%'\n      END\n    )\n    OR p.place_name LIKE (\n      CASE\n        WHEN INSTR(:place, '%') > 0 OR INSTR(:place, '_') > 0\n        THEN :place\n        ELSE :place || '%'\n      END\n    )\n  )\n  AND (\n    NULLIF(:county, '') IS NULL\n    OR p.county LIKE (\n      CASE\n        WHEN INSTR(:county, '%') > 0 OR INSTR(:county, '_') > 0\n        THEN :county\n        ELSE :county || '%'\n      END\n    )\n  )\n  AND (\n    NULLIF(:venue, '') IS NULL\n    OR c.county LIKE (\n      CASE\n        WHEN INSTR(:venue, '%') > 0 OR INSTR(:venue, '_') > 0\n        THEN :venue\n        ELSE :venue || '%'\n      END\n    )\n  )\n  AND c.year IS NOT NULL\n  AND c.year >= CAST(COALESCE(NULLIF(:start_year, ''), '1349') AS INTEGER)\n  AND c.year <= CAST(COALESCE(NULLIF(:end_year, ''), '1596') AS INTEGER)\nORDER BY c.year, n.surname\nLIMIT 100\n", "params": ["surname", "place", "county", "venue", "role", "start_year", "end_year"], "name": "search_name_place", "private": false}, {"title": "Sample relationship glosses in occupation", "description": "Sample rows with relationship glosses; optional start_year / end_year (defaults 1349\u20131596).\n", "sql": "SELECT n.surname, n.forename, n.occupation, n.raw_segment, c.year\nFROM names n\nJOIN cases c ON c.id = n.case_id\nWHERE (n.occupation LIKE '%his wife%'\n   OR n.occupation LIKE '%his son%'\n   OR n.occupation LIKE '%widow%')\n  AND c.year IS NOT NULL\n  AND c.year >= CAST(COALESCE(NULLIF(:start_year, ''), '1349') AS INTEGER)\n  AND c.year <= CAST(COALESCE(NULLIF(:end_year, ''), '1596') AS INTEGER)\nLIMIT 50\n", "params": ["start_year", "end_year"], "name": "occupation_gloss_sample", "private": false}, {"title": "Sample institutional offices", "description": "Sample institutional offices; optional start_year / end_year (defaults 1349\u20131596).\n", "sql": "SELECT n.surname, n.forename, n.occupation, n.raw_segment, c.year\nFROM names n\nJOIN cases c ON c.id = n.case_id\nWHERE n.surname IN ('(not given)', '(illegible)')\n  AND n.occupation IS NOT NULL\n  AND (\n    lower(n.occupation) LIKE '%abbot%'\n    OR lower(n.occupation) LIKE '%prior%'\n    OR lower(n.occupation) LIKE '%dean%'\n  )\n  AND c.year IS NOT NULL\n  AND c.year >= CAST(COALESCE(NULLIF(:start_year, ''), '1349') AS INTEGER)\n  AND c.year <= CAST(COALESCE(NULLIF(:end_year, ''), '1596') AS INTEGER)\nLIMIT 50\n", "params": ["start_year", "end_year"], "name": "office_placeholder_sample", "private": false}], "allow_execute_sql": true, "query_ms": 28.064285404980183}