drizzle 0.1.16

A type-safe SQL query builder for Rust
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
@import 'tailwindcss';
@import 'tw-animate-css';
@import 'shadcn-svelte/tailwind.css';

/*
 * ============================================================================
 * Instrument — the visual system for the drizzle-rs benchmark site.
 * ============================================================================
 *
 * A benchmark is a recording. This suite ramps virtual users from nothing to
 * three thousand, samples every second, and repeats the whole thing five times;
 * the numbers on these pages are what is left after all of that is reduced. The
 * design's job is to keep the recording visible behind the reduction.
 *
 * So it is built like an instrument panel rather than a document:
 *
 *   Ground    Near-black, because every page here is a chart with numbers on
 *             it, and a dark ground lets a trace carry without shouting.
 *   Signal    One lime, used for the current position and nothing else. Series
 *             colours step away from it, so five lines stay separable while the
 *             accent still belongs to the page.
 *   Numbers   Monospace and tabular everywhere. Every figure on this site is
 *             read down a column against the figure above it.
 *   Recording Wherever one number stands for many, the many are drawn beside
 *             it: a sparkline on a row, a box and whisker in a detail, the ramp
 *             itself on a run.
 *
 * Dark is the designed mode. Light is derived by mirroring the lightness ramp
 * on the same hues, so the two are one palette rather than two to keep in sync,
 * and the theme toggle keeps working.
 */

/*
 * Fonts.
 *
 * `font-display: optional` is the only value that guarantees zero layout shift:
 * there is no swap period, so the browser either has the font in time for first
 * paint or renders in the fallback and swaps on the next navigation. It never
 * re-lays-out text already on screen. Fontsource's own CSS hardcodes `swap`,
 * which is the FOUT that moves things, so the faces are declared here instead.
 *
 * Inter for everything that is words, JetBrains Mono for everything that is a
 * number. The split is strict: a figure read down a column is always mono.
 */
@font-face {
	font-family: 'Inter Variable';
	font-style: normal;
	font-weight: 100 900;
	font-display: optional;
	src: url('@fontsource-variable/inter/files/inter-latin-wght-normal.woff2')
		format('woff2-variations');
	unicode-range:
		U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329,
		U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
	font-family: 'JetBrains Mono Variable';
	font-style: normal;
	font-weight: 100 800;
	font-display: optional;
	src: url('@fontsource-variable/jetbrains-mono/files/jetbrains-mono-latin-wght-normal.woff2')
		format('woff2-variations');
	unicode-range:
		U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329,
		U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/*
 * Metric-matched stand-ins, so the fallback render has the same line box and the
 * same line-break points as the real face. Every number below was measured off
 * the shipped woff2 with fontTools, against the local face named in `src`:
 *
 *   Inter            2048upm  asc 96.88%  desc 24.12%  avg advance 0.59153em
 *   Arial            2048upm                           avg advance 0.56517em
 *                                                      -> size-adjust 104.67%
 *   JetBrains Mono   1000upm  asc 102.0%  desc 30.00%  advance 0.60000em
 *   Courier New      2048upm                           advance 0.60010em
 *                                                      -> size-adjust  99.98%
 *
 * The ascent/descent overrides are the real face's percentages divided by the
 * size-adjust, which is what keeps the line box identical once the stand-in has
 * been scaled.
 */
@font-face {
	font-family: 'Inter Fallback';
	src: local('Arial');
	ascent-override: 92.56%;
	descent-override: 23.05%;
	line-gap-override: 0%;
	size-adjust: 104.67%;
}

@font-face {
	font-family: 'JetBrains Mono Fallback';
	src: local('Courier New');
	ascent-override: 102.02%;
	descent-override: 30%;
	line-gap-override: 0%;
	size-adjust: 99.98%;
}

/* Dark mode has two triggers and one source of truth. `light-dark()` below resolves against the
   used color-scheme, which follows the OS by default and is pinned by `data-theme` on <html>. This
   variant exists so the `dark:` utilities inside the vendored shadcn components resolve against the
   same two conditions. */
/* `js:` applies once the inline head script has marked the document as scripted. It exists for
   progressive-enhancement affordances that should not be shown to a scripted browser. */
@custom-variant js (&:where(:root.js, :root.js *));

@custom-variant dark {
	&:where([data-theme='dark'], [data-theme='dark'] *) {
		@slot;
	}

	@media (prefers-color-scheme: dark) {
		&:where(:root:not([data-theme='light']), :root:not([data-theme='light']) *) {
			@slot;
		}
	}
}

/*
 * ---------------------------------------------------------------------------
 * Tokens — the only place a colour, type step, or radius is decided.
 * ---------------------------------------------------------------------------
 * Every value is declared once as `light-dark(<light>, <dark>)`. There is no
 * second dark block to keep in sync, and no parallel hand-rolled palette:
 * Every value is declared once as `light-dark(<light>, <dark>)`. There is no
 * second dark block to keep in sync: `@theme inline` below publishes these to
 * Tailwind, and the vendored shadcn components read the same names.
 *
 * Neutrals sit at hue 285 with almost no chroma — a near-neutral charcoal that
 * keeps the lime from going muddy against it. Lime is hue 122.
 */
:root {
	color-scheme: light dark;

	/* Surfaces ------------------------------------------------------------- */
	--background: light-dark(oklch(0.968 0.002 285), oklch(0.145 0.004 285));
	--foreground: light-dark(oklch(0.205 0.006 285), oklch(0.935 0.003 285));
	--card: light-dark(oklch(0.995 0.001 285), oklch(0.188 0.005 285));
	--card-foreground: var(--foreground);
	--popover: var(--card);
	--popover-foreground: var(--foreground);
	--muted: light-dark(oklch(0.935 0.003 285), oklch(0.238 0.006 285));
	--muted-foreground: light-dark(oklch(0.5 0.008 285), oklch(0.68 0.008 285));
	--secondary: var(--muted);
	--secondary-foreground: var(--foreground);
	--accent: var(--muted);
	--accent-foreground: var(--foreground);

	/* The recessed well a chart is drawn into, and the chrome around the page. */
	--surface-inset: light-dark(oklch(0.945 0.003 285), oklch(0.118 0.004 285));
	--surface-chrome: light-dark(oklch(0.99 0.001 285), oklch(0.128 0.004 285));

	/* Ink steps. `faint` is decorative only — it does not clear 4.5:1 for text. */
	--foreground-secondary: light-dark(oklch(0.375 0.007 285), oklch(0.81 0.006 285));
	--foreground-faint: light-dark(oklch(0.66 0.008 285), oklch(0.5 0.008 285));

	/* Rules ----------------------------------------------------------------- */
	--border: light-dark(oklch(0.87 0.004 285), oklch(0.278 0.006 285));
	--border-soft: light-dark(oklch(0.922 0.003 285), oklch(0.222 0.006 285));
	--input: light-dark(oklch(0.85 0.005 285), oklch(0.33 0.007 285));
	--ring: light-dark(oklch(0.58 0.16 122), oklch(0.92 0.19 122));

	/* Signal ---------------------------------------------------------------- */
	/*
	 * Lime, marking the current position and nothing else: the page you are on,
	 * the filter you applied, the playhead.
	 *
	 * The two modes are not the same lightness, and cannot be. Dark mode gets the
	 * bright lime this palette is built around. On paper that same value is
	 * 1.3:1 against the page — invisible as a plotted line — so light mode runs
	 * an olive at L 0.55, which clears 3:1 as a mark on every surface here and
	 * still carries near-white text when it is used as a fill.
	 */
	--primary: light-dark(oklch(0.55 0.15 128), oklch(0.92 0.19 122));
	--primary-foreground: light-dark(oklch(0.99 0.005 122), oklch(0.19 0.05 122));
	--signal: var(--primary);
	--signal-ink: light-dark(oklch(0.5 0.14 128), oklch(0.9 0.19 122));

	/* Two steps of the same wash: the row that *is* current, and the row under
	   the pointer. Attention out-ranks identity, so the second is the louder. */
	--signal-wash: light-dark(oklch(0.965 0.03 122), oklch(0.21 0.03 122));
	--signal-wash-strong: light-dark(oklch(0.93 0.07 122), oklch(0.265 0.055 122));

	/* Status ---------------------------------------------------------------- */
	/* Well away from the lime: teal at 190, rose at 15. Never colour alone —
	   every use pairs with a sign, an arrow or a word. */
	--positive: light-dark(oklch(0.5 0.1 190), oklch(0.82 0.11 190));
	--negative: light-dark(oklch(0.52 0.19 15), oklch(0.74 0.17 15));
	--destructive: var(--negative);

	/* The one interrupting surface. A tinted panel plus a hatched edge and the
	   word, carrying no hue: an amber warning beside a lime signal is a coin
	   flip at a glance. */
	--caution: light-dark(oklch(0.9 0.006 285), oklch(0.26 0.006 285));
	--caution-border: light-dark(oklch(0.58 0.008 285), oklch(0.58 0.008 285));
	--caution-foreground: light-dark(oklch(0.28 0.008 285), oklch(0.92 0.004 285));

	/* Plotted series --------------------------------------------------------- */
	/*
	 * Five traces that stay apart at a glance and never collide with the signal.
	 * Lime leads because it is the accent; the rest step around the wheel to
	 * teal, azure, rose and amber.
	 */
	--series-1: light-dark(oklch(0.52 0.14 128), oklch(0.92 0.19 122));
	--series-2: light-dark(oklch(0.5 0.1 195), oklch(0.82 0.12 195));
	--series-3: light-dark(oklch(0.48 0.13 255), oklch(0.78 0.12 255));
	--series-4: light-dark(oklch(0.53 0.16 15), oklch(0.75 0.15 15));
	--series-5: light-dark(oklch(0.55 0.12 75), oklch(0.82 0.13 75));

	/* One metric, one hue, everywhere it is drawn. */
	--chart-1: var(--series-1);
	--chart-2: var(--series-3);
	--chart-3: var(--series-2);
	--chart-4: var(--series-5);
	--chart-5: var(--series-4);
	--metric-rps: var(--chart-1);
	--metric-latency: var(--chart-2);
	--metric-mem: var(--chart-3);
	--metric-cpu: var(--chart-4);
	--metric-err: var(--chart-5);

	/* Geometry -------------------------------------------------------------- */
	/* Softer than the old zero. An instrument panel has moulded corners; a
	   hairline grid of hard boxes is the newsprint look this replaced. */
	--radius: 0.375rem;
}

/* An explicit choice wins over the OS preference, in both directions. */
:root[data-theme='light'] {
	color-scheme: light;
}

:root[data-theme='dark'] {
	color-scheme: dark;
}

@theme inline {
	--font-sans: 'Inter Variable', 'Inter Fallback', ui-sans-serif, system-ui, sans-serif;
	--font-mono: 'JetBrains Mono Variable', 'JetBrains Mono Fallback', ui-monospace, monospace;

	--color-background: var(--background);
	--color-foreground: var(--foreground);
	--color-foreground-secondary: var(--foreground-secondary);
	--color-foreground-faint: var(--foreground-faint);
	--color-card: var(--card);
	--color-card-foreground: var(--card-foreground);
	--color-popover: var(--popover);
	--color-popover-foreground: var(--popover-foreground);
	--color-primary: var(--primary);
	--color-primary-foreground: var(--primary-foreground);
	--color-secondary: var(--secondary);
	--color-secondary-foreground: var(--secondary-foreground);
	--color-muted: var(--muted);
	--color-muted-foreground: var(--muted-foreground);
	--color-accent: var(--accent);
	--color-accent-foreground: var(--accent-foreground);
	--color-destructive: var(--destructive);
	--color-border: var(--border);
	--color-border-soft: var(--border-soft);
	--color-input: var(--input);
	--color-ring: var(--ring);
	--color-link: var(--link);
	--color-positive: var(--positive);
	--color-negative: var(--negative);
	--color-surface-inset: var(--surface-inset);
	--color-surface-chrome: var(--surface-chrome);
	--color-signal: var(--signal);
	--color-signal-ink: var(--signal-ink);
	--color-signal-wash: var(--signal-wash);
	--color-signal-wash-strong: var(--signal-wash-strong);
	--color-caution: var(--caution);
	--color-caution-border: var(--caution-border);
	--color-caution-foreground: var(--caution-foreground);
	--color-series-signal: var(--series-signal);
	--color-series-1: var(--series-1);
	--color-series-2: var(--series-2);
	--color-series-3: var(--series-3);
	--color-series-4: var(--series-4);
	--color-series-5: var(--series-5);

	--color-chart-1: var(--chart-1);
	--color-chart-2: var(--chart-2);
	--color-chart-3: var(--chart-3);
	--color-chart-4: var(--chart-4);
	--color-chart-5: var(--chart-5);
	--color-metric-rps: var(--metric-rps);
	--color-metric-latency: var(--metric-latency);
	--color-metric-mem: var(--metric-mem);
	--color-metric-cpu: var(--metric-cpu);
	--color-metric-err: var(--metric-err);

	/*
	 * Type. Each step has one job, so a size is picked by role and never by
	 * nudging a pixel value. Tailwind's own text-xs/text-sm scale is left
	 * untouched — the vendored shadcn components are calibrated against it.
	 *
	 *   micro    10.5px mono UPPERCASE — axis ticks, column labels
	 *   label    11.5px mono           — the meta strip beside a title
	 *   meta     12.5px                — the quiet note under a name
	 *   body     14px                  — UI copy: nav, filters, footnotes
	 *   lead     15px                  — a row's primary cell, card titles
	 *   heading  18px                  — section headings
	 *   figure   24px mono             — a KPI value
	 *   display  34px                  — page titles, set wide
	 *   prose    16px/1.625            — Method, the only page with paragraphs
	 *
	 * Line heights are absolute rather than unitless, and every one lands on a
	 * whole pixel at the default root size. A unitless 1.55 on 14px text is a
	 * 21.7px line box, and a stack of fractional boxes rounds differently
	 * depending on the glyph metrics in use — which shows up as a 1px shift
	 * during the font settle. Whole-pixel line boxes make a paragraph the same
	 * height in the fallback and in the real face.
	 */
	--text-micro: 0.65625rem;
	--text-micro--line-height: 0.875rem;
	--text-micro--letter-spacing: 0.07em;
	--text-label: 0.71875rem;
	--text-label--line-height: 1rem;
	--text-label--letter-spacing: 0.01em;
	--text-meta: 0.78125rem;
	--text-meta--line-height: 1.125rem;
	--text-body: 0.875rem;
	--text-body--line-height: 1.375rem;
	--text-lead: 0.9375rem;
	--text-lead--line-height: 1.25rem;
	--text-lead--letter-spacing: -0.006em;
	--text-heading: 1.125rem;
	--text-heading--line-height: 1.5rem;
	--text-heading--letter-spacing: -0.014em;
	--text-prose: 1rem;
	--text-prose--line-height: 1.625rem;
	--text-figure: 1.5rem;
	--text-figure--line-height: 1.75rem;
	--text-figure--letter-spacing: -0.018em;
	--text-display: 2.125rem;
	--text-display--line-height: 2.25rem;
	--text-display--letter-spacing: -0.026em;

	--radius-sm: calc(var(--radius) * 0.5);
	--radius-md: var(--radius);
	--radius-lg: calc(var(--radius) * 1.5);
	--radius-xl: calc(var(--radius) * 2);
	--radius-2xl: calc(var(--radius) * 3);
	--radius-3xl: calc(var(--radius) * 4);
	--radius-4xl: calc(var(--radius) * 5);
}

@layer base {
	*,
	::after,
	::before {
		border-color: var(--border);
	}

	html {
		font-family: var(--font-sans);
	}

	body {
		min-height: 100vh;
		background: var(--background);
		color: var(--foreground);
		font-size: 0.875rem;
		/* 22px, matching --text-body: whole pixels, so a paragraph is the same
		   height in the fallback face and the real one. */
		line-height: 1.375rem;
		/* Every number here is read in a column against the number above it. */
		font-variant-numeric: tabular-nums;
		-webkit-font-smoothing: antialiased;
		-moz-osx-font-smoothing: grayscale;
	}

	a {
		color: inherit;
		text-decoration: none;
	}

	/* Keyboard focus stays visible everywhere. Components that suppress the
	   default outline on :focus fall through to this. */
	:focus-visible {
		outline: 2px solid var(--ring);
		outline-offset: 2px;
	}

	::selection {
		background: light-dark(oklch(0.86 0.09 55 / 0.5), oklch(0.45 0.1 50));
		color: var(--foreground);
	}

	::-webkit-scrollbar {
		width: 8px;
		height: 8px;
	}

	::-webkit-scrollbar-thumb {
		background: var(--foreground-faint);
	}

	::-webkit-scrollbar-thumb:hover {
		background: var(--muted-foreground);
	}
}

/*
 * LayerChart sizes its root from a measurement that only exists once the
 * component is in the DOM, so between the server's markup and hydration the root
 * has no height of its own and collapses for a frame — which drops everything
 * below the chart and then lifts it back.
 *
 * Every chart here already sits in a wrapper whose height is reserved in CSS, so
 * the fix is to let the root fill the box that is already the right size. This
 * is a global element rule rather than a utility on each chart because it is a
 * property of the library, not of any one chart.
 */
.lc-root-container {
	height: 100%;
	/*
	 * Full width for the same reason, and it fixes a second, subtler shift. The
	 * server renders the chart at the nominal width `#lib/chart-ssr` supplies
	 * (800px), and the library's own wrapper centres it; on a 1016px-wide column
	 * that put the chart 108px in from the left, and hydration then snapped it
	 * back to the edge. Filling the box means the chart's left edge is in the
	 * same place before and after, so growing to the real width moves nothing.
	 */
	width: 100%;
}

/* --------------------------------------------------------------------------
   App utilities. Each one is a decision the design makes in exactly one place.
   -------------------------------------------------------------------------- */

@utility page-gutter {
	margin-inline: auto;
	width: 100%;
	/* 1200px content column. The ratio rail needs the width: a decade of scale
	   below about 240px stops being readable as distance. */
	max-width: 75rem;
	padding-inline: --spacing(5);

	@media (width >= 40rem) {
		padding-inline: 2.25rem;
	}
}

/*
 * Prose measure, expressed in rem rather than ch, and that is a layout-stability
 * fix rather than a preference. `ch` is the advance width of the font's "0"
 * glyph, so a `ch`-based max-width is recomputed the moment the real font
 * replaces the metric-matched fallback — the paragraph re-wraps, its height
 * changes, and everything below it moves. 36rem is 576px, which is where a line
 * of the 16px prose size stops needing a ruler, and it does not move.
 */
@utility measure {
	max-width: 36rem;
}

/*
 * Two named tracking steps, so the choice is stated once rather than repeated
 * as a magic number at every call site.
 */
/*
 * These two named the width axis of the old display face. Inter has no width
 * axis, so they now carry the same intent through tracking: a page title set
 * open, and an uppercase label set tight enough to sit over a column.
 */
@utility type-wide {
	letter-spacing: -0.03em;
}

@utility type-narrow {
	letter-spacing: 0.08em;
}

/*
 * The caution panel's hatch. This design has no amber in it — a warning is a
 * tinted panel plus 45-degree ruling plus the word, which survives greyscale,
 * colour-blindness and a bad projector, none of which a hue does.
 */
@utility hatch {
	background-image: repeating-linear-gradient(
		45deg,
		transparent,
		transparent 5px,
		var(--caution-border) 5px,
		var(--caution-border) 6px
	);
}