{"id":"code-col-sqlite-ddl-from-spec-strict","audience":"college","category":"coding","track":"coding","technique":"constraints","title":"Write SQLite tables from a spec with your team's rules","free":false,"task":"Your study-group app's spec is below. Your team's rules: start with PRAGMA foreign_keys = ON;, name the tables exactly study_groups and group_members, and make both STRICT tables. group_members uses a composite primary key (group_id, user_id), its foreign key to study_groups uses ON DELETE CASCADE, and role defaults to 'member' and is limited with a CHECK to 'owner' or 'member'. Exactly 1 code block of at most 20 lines, under 20 words of text.","materialLabel":"The spec (attached to your prompt automatically)","material":"StudyCircle - data spec v0.3 (CS 3100 team project, team Juniper)\n\nGroups\n- A group has a name (required, no two groups with the same name)\n- Each group is for one course, stored as a code like \"CS 2110\"\n- We record when the group was created (default: now)\n\nPeople in groups\n- A user can join many groups; a group has many users\n- Users live in the auth service, we only store their user_id (integer)\n- Each membership has a role. Right now there are two roles:\n  owner and member. (Ines wants \"moderator\" later, NOT now.)\n- We record when they joined (default: now)\n- If a group is deleted, its memberships should go too\n- The same user can't be in the same group twice\n\nOut of scope for v0.3\n- Meeting times, chat, file uploads\n\nTech\n- SQLite 3.45 (bundled with Python 3.12 on the lab machines)\n- Dates stored as text (ISO 8601), like the rest of our tables\n\nOpen question from Darius: do we need an id column on memberships?\n(Answer from the TA: no, the two ids together are enough.)","rules":[{"type":"codeBlocks","count":1},{"type":"maxCodeLines","max":20},{"type":"maxProseWords","max":20}],"mistakes":[{"title":"Foreign keys switched off","why":"SQLite ignores foreign keys unless you turn them on, so the cascade never runs.","fix":"Add: \"Start with PRAGMA foreign_keys = ON;\"","checks":["r0"]},{"title":"Loose column types","why":"Without STRICT, SQLite lets any value into any column.","fix":"Add: \"Make both tables STRICT.\"","checks":["r0"]},{"title":"Letting the AI name tables","why":"The AI picks groups and memberships, which won't match your team's queries.","fix":"Add: \"Tables exactly study_groups and group_members; composite key (group_id, user_id).\"","checks":["r1"]},{"title":"No default role","why":"The AI won't default new members to 'member', and may add 'moderator' from the spec.","fix":"Add: \"role DEFAULT 'member', CHECK role IN ('owner', 'member') only.\"","checks":["r2"]},{"title":"Extra tables and notes","why":"The AI adds a users table, indexes and an explanation.","fix":"Add: \"Only these two tables, one code block, no text.\"","checks":["codeBlocks","maxCodeLines","maxProseWords"]}],"promptHints":[{"label":"Turns on foreign keys","patterns":["foreign_keys","pragma"]},{"label":"Asks for STRICT tables","patterns":["strict"]},{"label":"Names the tables","patterns":["study_groups","group_members"]},{"label":"Gives the key and cascade","patterns":["composite","primary key","cascade"]},{"label":"Limits the roles","patterns":["check","owner","member"]}],"hint":"SQLite has defaults that surprise people, and your team has naming rules. Tell the AI both, plus the exact keys and checks you want.","rubricLabels":["The first statement is PRAGMA foreign_keys = ON; and both CREATE TABLE statements end with STRICT","The tables are named exactly study_groups and group_members, and group_members has PRIMARY KEY (group_id, user_id) and a foreign key to study_groups with ON DELETE CASCADE","role is TEXT NOT NULL DEFAULT 'member' with CHECK (role IN ('owner', 'member')) (no moderator)"]}