diff --git a/website/STYLE.md b/website/STYLE.md index 8d3ee7a..c90cf7d 100644 --- a/website/STYLE.md +++ b/website/STYLE.md @@ -39,22 +39,63 @@ Status tags used below: **[DECIDED]** (binding or settled) · instructions ("Create a table…"). - Prefer short sentences and concrete examples over abstract prose. +## Structure [DECIDED] + +Pragmatic, Diátaxis-influenced split (four top-level sidebar sections, +autogenerated per directory under `src/content/docs/`): + +- **Getting started** — install, first project, simple vs. advanced, the + example database. +- **Guides** — task-oriented how-tos. *These are the most important didactic + content and will be iterated for teaching quality before publication.* +- **Reference** — the exhaustive command/SQL/type surface. **Page + granularity: one page per topic / command-family** (Tables, Columns, + Relationships, Indexes, Constraints, Inserting & editing data, Querying, + Types, …), each covering the simple-mode and advanced-mode forms where + both apply. Hand-written now (the command surface is settled bar H1a + output); small post-release adjustments are expected and fine. +- **Concepts** — the "why": projects & storage, undo & history, etc. + +Ground every reference page in source — `parse.usage.*` and `help.*` in +`src/friendly/strings/en-US.yaml`, `src/dsl/command.rs`, `src/dsl/types.rs` +— never paraphrase grammar from memory. + ## "Planned / not yet available" callouts [DECIDED — ADR-0042 §7] Any capability that is not yet fully implemented is **omitted** or carries a -clear **"planned / not yet available"** callout — never presented as -shipped. Use a Starlight aside (`:::caution` or a custom badge). **[OPEN]**: -exact component + wording (see log). +clear callout — never presented as shipped. Standard form: a Starlight aside -## Examples & code [OPEN] +```md +:::caution[Planned] +This is planned and not yet available. +::: +``` -Direction (to confirm in the log): -- A single **standard example schema/dataset** reused across pages so - readers build familiarity (candidate: a small, recognisable domain). +## Examples & code [DECIDED] + +- **Shared example database: a small library** — `authors`, `books`, + `members`, `loans` (see the canonical schema below). Reuse it across all + pages so readers build familiarity; it models 1:n (an author has many + books) and m:n (books ↔ members, through loans). - Where both modes apply, show the **simple-mode** form and its **advanced-mode (SQL)** equivalent — the in-app teaching echo already - pairs these, so docs can mirror it. -- Code blocks for input/output; reserve casts for motion/flow (see below). + pairs these, so docs mirror it. +- Code blocks for exact input/output; reserve casts for motion/flow. + +### Canonical library schema (source of truth for examples) + +Use these exact names/types in every example: + +| Table | Columns (playground types) | +|-----------|---------------------------------------------------------------------------------------------| +| `authors` | `author_id` serial (pk) · `name` text (not null) · `birth_year` int | +| `books` | `book_id` serial (pk) · `title` text (not null) · `author_id` int (→ authors) · `published` int · `isbn` text (unique) | +| `members` | `member_id` serial (pk) · `name` text (not null) · `joined` date | +| `loans` | `loan_id` serial (pk) · `book_id` int (→ books) · `member_id` int (→ members) · `loaned_on` date · `returned_on` date | + +Relationships: `books.author_id → authors.author_id` (1:n); `loans` joins +`books` and `members` (the m:n bridge). Show `shortid` on the Types page via +a small standalone example, not by complicating this schema. ## asciinema casts [DECIDED, details OPEN] @@ -81,20 +122,23 @@ Direction (to confirm in the log): Decide these as we write; record the outcome (and escalate to an ADR if significant). -1. **Depth / organising spine.** Adopt **Diátaxis** (tutorial / how-to / - reference / explanation) as the structure, or a lighter - getting-started + reference + concepts split? Affects the whole sidebar. -2. **Page granularity & splitting.** One page per command, per - command-family, or per task? When does a page split? -3. **Standard example schema/dataset.** What domain + tables do all examples - share? -4. **Simple-vs-advanced pairing.** Always show both forms, or only where - instructive? How to present the pairing visually. -5. **"Planned" callout component & wording.** Exact Starlight component and - standard sentence. -6. **Reference generation vs hand-writing.** Generate the command reference - from source (the `help` REGISTRY / `en-US.yaml`) to avoid drift, or - author by hand? (Flagged in the plan's notes.) -7. **Versioning.** Do docs need version selectors at/after v1, or is - single-version fine for launch? -8. **SEO/meta conventions.** Title/description patterns, Open Graph. +**Resolved (2026-06-05):** +1. ~~Depth / organising spine~~ → **Pragmatic** four-section split (see + Structure above). +2. ~~Page granularity~~ → **one page per topic / command-family**, both + modes per page (see Structure). +3. ~~Standard example dataset~~ → **the library** (schema above). +4. ~~Simple-vs-advanced pairing~~ → **show both where both apply** (see + Examples). +5. ~~"Planned" callout~~ → standard `:::caution[Planned]` aside (see above). +6. ~~Reference generation vs hand-writing~~ → **hand-write now** (command + surface is settled bar H1a output; small later adjustments expected). + +**Still open:** +7. **Versioning.** Version selectors at/after v1, or single-version for + launch? (Leaning single-version for launch.) +8. **SEO/meta conventions.** Title/description patterns, Open Graph — settle + with Phase B (landing) and the `site` URL. +9. **Cast scripting toolchain.** Confirm the scripted-input driver + (`asciinema-automation`/autocast vs alternative) via a test run; define + the `.cast` script format + storage location. (Execution task, in flight.) diff --git a/website/astro.config.mjs b/website/astro.config.mjs index 41fc504..d5ac274 100644 --- a/website/astro.config.mjs +++ b/website/astro.config.mjs @@ -6,28 +6,30 @@ import tailwindcss from '@tailwindcss/vite'; // https://astro.build/config export default defineConfig({ - integrations: [ - starlight({ - title: 'My Docs', - social: [{ icon: 'github', label: 'GitHub', href: 'https://github.com/withastro/starlight' }], - customCss: ['./src/styles/global.css'], - sidebar: [ - { - label: 'Guides', - items: [ - // Each item here is one entry in the navigation menu. - { label: 'Example Guide', slug: 'guides/example' }, - ], - }, - { - label: 'Reference', - items: [{ autogenerate: { directory: 'reference' } }], - }, - ], - }), + // TODO(Phase B/SEO): set `site` to the production URL once the domain is + // known — enables the sitemap and canonical/OG URLs. + integrations: [ + starlight({ + title: 'RDBMS Playground', + tagline: 'Learn relational databases by doing.', + // TODO(Phase B): point at the real repository once it moves to its + // public home. Omitted for now rather than linking the wrong repo. + // social: [{ icon: 'github', label: 'GitHub', href: '…' }], + customCss: ['./src/styles/global.css'], + // Pragmatic structure (ADR-0042 §7 / website/STYLE.md): Getting + // started, Guides, Reference, Concepts. Autogenerated per directory; + // in-section order is controlled by each page's `sidebar.order` + // frontmatter. + sidebar: [ + { label: 'Getting started', items: [{ autogenerate: { directory: 'getting-started' } }] }, + { label: 'Guides', items: [{ autogenerate: { directory: 'guides' } }] }, + { label: 'Reference', items: [{ autogenerate: { directory: 'reference' } }] }, + { label: 'Concepts', items: [{ autogenerate: { directory: 'concepts' } }] }, + ], + }), ], - vite: { - plugins: [tailwindcss()], - }, -}); \ No newline at end of file + vite: { + plugins: [tailwindcss()], + }, +}); diff --git a/website/src/content/docs/concepts/projects-and-storage.md b/website/src/content/docs/concepts/projects-and-storage.md new file mode 100644 index 0000000..cd3991a --- /dev/null +++ b/website/src/content/docs/concepts/projects-and-storage.md @@ -0,0 +1,73 @@ +--- +title: Projects and storage +description: How the playground stores your work — readable files, a derived database, autosave, and temporary projects. +sidebar: + order: 1 +--- + +Everything you do in the playground lives in a **project** — a folder on +disk. Understanding what is in that folder explains why your work is safe, +shareable, and easy to inspect. + +## What a project contains + +| File / folder | Role | +|---|---| +| `project.yaml` | The schema: your tables, columns, keys, relationships, and indexes. | +| `data/.csv` | One file per table holding its rows, as plain CSV. | +| `history.log` | An append-only journal of every command you have run. | +| the database file | The working database the playground queries. **Derived** — see below. | + +The first three are the **authoritative, human-readable** record of your +project. You can open them in any editor, diff them in version control, and +read them without the playground. + +## The database is derived + +The database file the playground queries is built *from* `project.yaml` and +the CSV files. Because it is derived, it never needs to be shared or backed +up separately — and if it is ever missing or stale, the `rebuild` command +regenerates it from the readable files: + +```text +rebuild +``` + +## Your work saves itself + +There is no "save" step to remember. Every command writes through to the +files as it runs, so a project is always up to date on disk. (The `save` +command exists for a different purpose: giving a temporary project a +permanent name — see below.) + +## Temporary vs. named projects + +When you start the playground without naming a project, it creates a +**temporary** project with an automatic name. Temporary projects are perfect +for quick experiments. When you want to keep one, give it a name: + +```text +save +``` + +Empty, untouched temporary projects are cleaned up automatically, so casual +experimenting never leaves clutter behind. + +## Where projects live + +Projects are stored in a standard per-user location for your operating +system. Override it for a single run with `--data-dir ` — handy for +keeping a course's projects together, or for testing. + +## Sharing a project + +The `export` command packages a project as a zip you can send to anyone: + +```text +export +``` + +The zip contains the readable files (`project.yaml` and `data/`) but **not** +the derived database or your private `history.log`. The recipient opens it +and the playground rebuilds the database for them. Exporting and +importing has its own reference page. diff --git a/website/src/content/docs/getting-started/example-library.md b/website/src/content/docs/getting-started/example-library.md new file mode 100644 index 0000000..6b87b76 --- /dev/null +++ b/website/src/content/docs/getting-started/example-library.md @@ -0,0 +1,32 @@ +--- +title: The example library +description: The small library database used throughout these docs. +sidebar: + order: 4 +--- + +Most examples in this documentation use the same small database: a library +with **authors**, **books**, **members**, and **loans**. Keeping one +familiar set of tables makes it easier to focus on the concept each page is +teaching. + +## The tables + +| Table | Columns | +|---|---| +| `authors` | `author_id` (serial, primary key), `name` (text), `birth_year` (int) | +| `books` | `book_id` (serial, primary key), `title` (text), `author_id` (int → authors), `published` (int), `isbn` (text, unique) | +| `members` | `member_id` (serial, primary key), `name` (text), `joined` (date) | +| `loans` | `loan_id` (serial, primary key), `book_id` (int → books), `member_id` (int → members), `loaned_on` (date), `returned_on` (date) | + +## The relationships + +- **An author has many books.** `books.author_id` points at + `authors.author_id` — a one-to-many relationship. +- **Members borrow books.** Each row in `loans` ties one book to one member, + so `loans` connects `books` and `members` — a many-to-many relationship + expressed through a bridging table. + +You will build these tables and relationships step by step in +[Build the library](/guides/build-the-library/). Individual reference pages +use whichever part of this schema illustrates the command at hand. diff --git a/website/src/content/docs/getting-started/first-project.md b/website/src/content/docs/getting-started/first-project.md new file mode 100644 index 0000000..30562f1 --- /dev/null +++ b/website/src/content/docs/getting-started/first-project.md @@ -0,0 +1,60 @@ +--- +title: Your first project +description: Create a table, add a row, and look at it — a two-minute tour of the playground. +sidebar: + order: 2 +--- + +This is the shortest possible tour: create a table, put a row in it, and +look at the result. Everything here is in **simple mode**, which is how the +playground starts. + +When you launch `rdbms-playground` with no arguments, it opens a fresh +temporary project for you. Type commands into the input field at the bottom +and press Enter to run them. + +## Create a table + +A table needs at least a primary key. The `with pk` clause names the +primary-key column and its type: + +```text +create table authors with pk author_id(serial) +``` + +`serial` is an auto-incrementing number — you will not have to fill it in +yourself. + +## Add a couple of columns + +In simple mode you create a table with its key, then add the other columns +one at a time: + +```text +add column to authors: name (text) +add column to authors: birth_year (int) +``` + +## Add a row + +`insert` adds a row. List the columns you are supplying — the `author_id` +fills itself in because it is a `serial`: + +```text +insert into authors (name, birth_year) values ('Ada Lovelace', 1815) +``` + +The playground shows the row it just inserted, including the generated +`author_id`. + +## Look at the data + +```text +show data authors +``` + +That is the whole loop: **create → add columns → insert → show**. From here: + +- Build the full example database in [Build the library](/guides/build-the-library/). +- Learn how [simple and advanced modes](/getting-started/modes/) differ. +- Look up any command in the [Reference](/reference/types/). diff --git a/website/src/content/docs/getting-started/installation.md b/website/src/content/docs/getting-started/installation.md new file mode 100644 index 0000000..7765c23 --- /dev/null +++ b/website/src/content/docs/getting-started/installation.md @@ -0,0 +1,64 @@ +--- +title: Installation +description: Install RDBMS Playground from a prebuilt binary or a package manager, and run it for the first time. +sidebar: + order: 1 +--- + +RDBMS Playground is a single self-contained program. There is nothing to +configure and no separate database to install — everything it needs is +built in. + +## Prebuilt binaries + +Download the binary for your platform, make it executable if needed, and +put it somewhere on your `PATH`. + +:::note +Download links are published with each release. They are added here when the +first public version ships. +::: + +## Package managers + +Once published, the playground will be installable through common package +managers: + +```sh +# macOS / Linux (Homebrew) +brew install rdbms-playground + +# Windows (Scoop) +scoop install rdbms-playground +``` + +:::note +Package-manager availability lands with the first public release; the exact +names are confirmed here at that time. +::: + +## Run it + +Start the playground with no arguments and it opens a fresh, automatically +named temporary project so you can start experimenting immediately: + +```sh +rdbms-playground +``` + +To open an existing project, pass its path: + +```sh +rdbms-playground path/to/project +``` + +Useful options (run `rdbms-playground --help` for the full list): + +| Option | What it does | +|---|---| +| `--resume` | Reopen the most recently used project. | +| `--data-dir ` | Use a different location for stored projects. | +| `--theme ` | Force a theme instead of auto-detecting. | +| `--mode ` | Start in a specific input mode. | + +Next: [create your first project](/getting-started/first-project/). diff --git a/website/src/content/docs/getting-started/modes.md b/website/src/content/docs/getting-started/modes.md new file mode 100644 index 0000000..4464d93 --- /dev/null +++ b/website/src/content/docs/getting-started/modes.md @@ -0,0 +1,60 @@ +--- +title: Simple and advanced modes +description: How the playground's two input modes differ, how to switch, and the one-line escape hatch. +sidebar: + order: 3 +--- + +The playground has two input modes. You can do everything a beginner needs +in **simple mode**, and reach for **advanced mode** when you want full SQL. + +## Simple mode (the default) + +Simple mode is a friendly, keyword-based command language designed for +learning. Commands read close to English: + +```text +create table authors with pk author_id(serial) +show data authors +``` + +Simple mode accepts these learning commands plus the app-level commands +(like `save`, `undo`, and `help`). If you type raw SQL here, the playground +gently points you at advanced mode instead of failing silently. + +## Advanced mode (SQL) + +Advanced mode accepts standard SQL — `SELECT`, `INSERT`, `CREATE TABLE`, and +more — alongside the same app-level commands: + +```sql +select title, published from books where published >= 2000 order by published; +``` + +Switch modes with the `mode` command: + +```text +mode advanced +mode simple +``` + +The mode you leave a project in is remembered and restored the next time you +open it, so a project set up for SQL practice reopens in advanced mode. + +## The one-line escape + +When you are in simple mode and want to run a single SQL statement without +switching, prefix the line with a colon: + +```text +:select count(*) from books +``` + +That runs just this one line as SQL; you stay in simple mode afterwards. + +## Seeing the SQL behind a command + +When you run a simple-mode command in advanced mode, the playground prints +the equivalent SQL beneath your command. It is a built-in way to learn how +the friendly commands map onto real SQL — the same statements you could type +yourself in advanced mode. diff --git a/website/src/content/docs/guides/build-the-library.md b/website/src/content/docs/guides/build-the-library.md new file mode 100644 index 0000000..bc618d1 --- /dev/null +++ b/website/src/content/docs/guides/build-the-library.md @@ -0,0 +1,69 @@ +--- +title: Build the library +description: Build the example library database step by step — tables, a relationship, and some rows. +sidebar: + order: 1 +--- + +:::note[Draft] +This guide is an early draft. The walkthrough is correct, but the wording +and pacing will be refined for teaching before the docs are published. +::: + +This guide builds the [example library](/getting-started/example-library/) +from scratch in simple mode: two tables, a relationship between them, and a +few rows. By the end you will have used the create → add column → relate → +insert → query loop end to end. + +## 1. Create the authors table + +```text +create table authors with pk author_id(serial) +add column to authors: name (text) +add column to authors: birth_year (int) +``` + +## 2. Create the books table + +```text +create table books with pk book_id(serial) +add column to books: title (text) +add column to books: author_id (int) +add column to books: published (int) +``` + +## 3. Relate books to authors + +An author has many books, so `books.author_id` should point at +`authors.author_id`. Declare that one-to-many relationship: + +```text +add 1:n relationship from authors.author_id to books.author_id +``` + +The relationship reads parent-to-child: **from** the `authors` side **to** +the `books` side. + +## 4. Add some rows + +`author_id` and `book_id` are `serial`, so they fill themselves in: + +```text +insert into authors (name, birth_year) values ('Ada Lovelace', 1815) +insert into authors (name, birth_year) values ('Alan Turing', 1912) +insert into books (title, author_id, published) values ('Notes on the Analytical Engine', 1, 1843) +``` + +## 5. Look at your data + +```text +show data authors +show data books +``` + +## Where to go next + +- Add the `members` and `loans` tables the same way to model borrowing — a + many-to-many relationship through `loans`. +- Try the same steps in advanced mode to see the SQL form of each command. +- Look up any command in detail in the Reference section. diff --git a/website/src/content/docs/guides/example.md b/website/src/content/docs/guides/example.md deleted file mode 100644 index ebd0f3b..0000000 --- a/website/src/content/docs/guides/example.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -title: Example Guide -description: A guide in my new Starlight docs site. ---- - -Guides lead a user through a specific task they want to accomplish, often with a sequence of steps. -Writing a good guide requires thinking about what your users are trying to do. - -## Further reading - -- Read [about how-to guides](https://diataxis.fr/how-to-guides/) in the Diátaxis framework diff --git a/website/src/content/docs/index.mdx b/website/src/content/docs/index.mdx index e6ed51f..a25ac87 100644 --- a/website/src/content/docs/index.mdx +++ b/website/src/content/docs/index.mdx @@ -1,40 +1,50 @@ --- -title: Welcome to Starlight -description: Get started building your docs site with Starlight. -template: splash # Remove or comment out this line to display the site sidebar on this page. +title: RDBMS Playground +description: A terminal playground for learning relational databases — tables, keys, relationships, indexes, queries, and query plans, hands-on. +template: splash hero: - tagline: Congrats on setting up a new Starlight project! - image: - file: ../../assets/houston.webp + tagline: Learn relational databases by doing — in your terminal. actions: - - text: Example Guide - link: /guides/example/ + - text: Get started + link: /getting-started/installation/ icon: right-arrow - - text: Read the Starlight docs - link: https://starlight.astro.build - icon: external + - text: Browse the reference + link: /reference/types/ variant: minimal --- -import { Card, CardGrid } from '@astrojs/starlight/components'; +import { Card, CardGrid, LinkCard } from '@astrojs/starlight/components'; -## Next steps +RDBMS Playground is a cross-platform terminal app that gives you a safe +sandbox for exploring relational database concepts: tables, columns, +primary and foreign keys, relationships, indexes, queries, and query +plans. It is built for learning — from your first table to writing raw +SQL. - - - Edit `src/content/docs/index.mdx` to see this page change. + + + Start in **simple mode** — a friendly, keyword-based command language — + and switch to **advanced mode** for standard SQL whenever you are ready. - - Delete `template: splash` in `src/content/docs/index.mdx` to display a - sidebar on this page. + + Run a simple-mode command in advanced mode and the playground shows you + the equivalent SQL, so the bridge from concepts to SQL is always visible. - - Add Markdown or MDX files to `src/content/docs` to create new pages. + + Every change can be undone, your work is saved as you go, and you can + rebuild the whole database from plain, readable files. - - Edit your `sidebar` and other config in `astro.config.mjs`. - - - Learn more in [the Starlight Docs](https://starlight.astro.build/). + + Ask the playground to explain any query and it renders the database's + plan as an annotated tree — so indexes and scans stop being a mystery. + +## Start here + + + + + + + diff --git a/website/src/content/docs/reference/example.md b/website/src/content/docs/reference/example.md deleted file mode 100644 index 0224f09..0000000 --- a/website/src/content/docs/reference/example.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -title: Example Reference -description: A reference page in my new Starlight docs site. ---- - -Reference pages are ideal for outlining how things work in terse and clear terms. -Less concerned with telling a story or addressing a specific use case, they should give a comprehensive outline of what you're documenting. - -## Further reading - -- Read [about reference](https://diataxis.fr/reference/) in the Diátaxis framework diff --git a/website/src/content/docs/reference/tables.md b/website/src/content/docs/reference/tables.md new file mode 100644 index 0000000..c53b771 --- /dev/null +++ b/website/src/content/docs/reference/tables.md @@ -0,0 +1,92 @@ +--- +title: Tables +description: Create and drop tables in simple mode and in advanced-mode SQL, including compound primary keys. +sidebar: + order: 2 +--- + +A table is the core building block. This page covers creating and removing +tables; changing a table's columns after it exists is covered under Columns +in the Reference. + +## Create a table (simple mode) + +Every table is created with its primary key. The `with pk` clause lists the +primary-key column(s): + +```text +create table authors with pk author_id(serial) +``` + +Other columns are added afterwards with `add column`: + +```text +add column to authors: name (text) +add column to authors: birth_year (int) +``` + +### Compound primary keys + +To make the primary key span more than one column, list them, comma +separated: + +```text +create table loans with pk book_id(int), member_id(int) +``` + +**Syntax** + +```text +create table with pk ()[, ...] +``` + +## Create a table (advanced mode) + +In advanced mode you write a full `CREATE TABLE` with every column and +constraint inline: + +```sql +create table authors ( + author_id serial primary key, + name text not null, + birth_year int +) +``` + +The advanced form also accepts table-level constraints and inline foreign +keys — see the Constraints and Relationships references. + +**Syntax** + +```text +create table [if not exists] ( [constraints], ...) +``` + +## Drop a table + +```text +drop table authors +``` + +In advanced mode you may add `if exists` so removing a table that is not +there succeeds quietly: + +```sql +drop table if exists authors +``` + +:::caution +Dropping a table removes its rows as well. Use `undo` if you drop one by +mistake. +::: + +## Renaming a table + +Renaming a table is available in advanced mode: + +```sql +alter table authors rename to writers +``` + +There is no simple-mode rename verb — switch to advanced mode (or use the +one-line `:` escape) to rename a table. diff --git a/website/src/content/docs/reference/types.md b/website/src/content/docs/reference/types.md new file mode 100644 index 0000000..70d8963 --- /dev/null +++ b/website/src/content/docs/reference/types.md @@ -0,0 +1,72 @@ +--- +title: Types +description: The ten column types, what they store, and the auto-generating serial and shortid types. +sidebar: + order: 1 +--- + +Every column has a type. The playground offers ten, chosen to cover what a +learner needs without the sprawl of a production database. + +## The ten types + +| Type | Stores | +|---|---| +| `text` | Text of any length. | +| `int` | A whole number (64-bit signed). | +| `real` | A floating-point number. | +| `decimal` | An exact decimal number, kept precise (see note below). | +| `bool` | A truth value, shown as `true` / `false`. | +| `date` | A calendar date, `YYYY-MM-DD`. | +| `datetime` | A date and time, `YYYY-MM-DDTHH:MM:SS`. | +| `blob` | Arbitrary binary data. | +| `serial` | An auto-incrementing whole number — see below. | +| `shortid` | A short random identifier — see below. | + +:::note +`decimal`, `date`, and `datetime` are compared as text, so they sort in the +expected order when written in their standard form. Arithmetic on a +`decimal` needs an explicit cast — they are stored exactly rather than as +approximate floating point. +::: + +## Auto-generated types: `serial` and `shortid` + +Two types fill themselves in when you insert a row, so you never supply them +by hand. + +- **`serial`** — the next number in sequence (one more than the current + maximum). It is the natural choice for a primary key. Outside a primary + key, a `serial` column is kept unique. +- **`shortid`** — a short, random, base58 identifier (10–12 characters, + avoiding easily-confused characters). Always kept unique. Useful when you + want an identifier that is compact but not guessable or sequential. + +```text +create table members with pk member_id(serial) +add column to members: member_code (shortid) +insert into members (name) values ('Grace Hopper') +``` + +Both the `member_id` and the `member_code` are generated for you. + +If you add a `serial` or `shortid` column to a table that already has rows — +or change an existing column to one of these types — the empty cells are +filled with freshly generated values in the same step. + +## Keys that point at these types + +A foreign key stores a plain looked-up value, not a new generated one. So a +column that references a `serial` primary key is itself an `int`, and one +that references a `shortid` is a `text`. The playground handles this for you +when you declare a relationship; it is worth knowing why the child column's +type differs from the parent key's. + +## Type names in advanced mode + +In advanced mode you may also use familiar standard-SQL spellings, which map +onto the types above — for example `integer`, `bigint`, and `smallint` are +all `int`; `varchar` and `char` are `text`; `boolean` is `bool`; `timestamp` +is `datetime`; `numeric` is `decimal`; `float` and `double precision` are +`real`. Simple mode uses only the ten names in the table, so it teaches one +clear vocabulary.