Skip to content

Commit 7f2ae2f

Browse files
committed
Merge commit '3bbed9d1ef0800239bfcaebd399d7c3b1745505b'
2 parents 74a595c + 3bbed9d commit 7f2ae2f

48 files changed

Lines changed: 5795 additions & 605 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CLAUDE.md

Lines changed: 45 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -322,23 +322,39 @@ pub enum GlobalMappingItem {
322322

323323
pub struct Layer {
324324
pub geom: Geom, // Geometric object type
325+
pub position: Position, // Position adjustment (from SETTING position)
325326
pub aesthetics: HashMap<String, AestheticValue>, // Aesthetic mappings (from MAPPING)
326327
pub parameters: HashMap<String, ParameterValue>, // Geom parameters (from SETTING)
328+
pub source: Option<DataSource>, // Data source (from MAPPING ... FROM or PLACE)
327329
pub filter: Option<FilterExpression>, // Layer filter (from FILTER)
328330
pub partition_by: Vec<String>, // Grouping columns (from PARTITION BY)
329331
}
330332

331333
pub enum Geom {
332334
// Basic geoms
333-
Point, Line, Path, Bar, Col, Area, Tile, Polygon, Ribbon,
335+
Point, Line, Path, Bar, Col, Area, Rect, Polygon, Ribbon,
334336
// Statistical geoms
335337
Histogram, Density, Smooth, Boxplot, Violin,
336338
// Annotation geoms
337-
Text, Label, Segment, Arrow, Rule, Linear, ErrorBar,
339+
Text, Segment, Arrow, Rule, Linear, ErrorBar,
340+
}
341+
342+
pub enum DataSource {
343+
Identifier(String), // Table/CTE name
344+
FilePath(String), // File path (quoted)
345+
Annotation, // PLACE clause (no external data)
346+
}
347+
348+
pub enum Position {
349+
Identity, // No adjustment
350+
Stack, // Stack elements (bars, areas)
351+
Dodge, // Dodge side-by-side (bars)
352+
Jitter, // Jitter points randomly
338353
}
339354

340355
pub enum AestheticValue {
341-
Column(String), // Unquoted column reference: revenue AS x
356+
Column(String), // Column from data: revenue AS x
357+
AnnotationColumn(String), // Annotation literal (PLACE): uses identity scale
342358
Literal(ParameterValue), // Quoted literal: 'value' AS fill
343359
}
344360

@@ -1178,6 +1194,7 @@ Where `<global_mapping>` can be:
11781194
| ----------- | ---------- | ----------------- | ----------------------------------------- |
11791195
| `VISUALISE` | ✅ Yes | Entry point | `VISUALISE date AS x, revenue AS y` |
11801196
| `DRAW` | ✅ Yes | Define layers | `DRAW line MAPPING date AS x, value AS y` |
1197+
| `PLACE` | ✅ Yes | Annotation layers | `PLACE point SETTING x => 5, y => 10` |
11811198
| `SCALE` | ✅ Yes | Configure scales | `SCALE x VIA date` |
11821199
| `FACET` | ❌ No | Small multiples | `FACET region` |
11831200
| `PROJECT` | ❌ No | Coordinate system | `PROJECT TO cartesian` |
@@ -1200,7 +1217,7 @@ All clauses (MAPPING, SETTING, PARTITION BY, FILTER) are optional.
12001217

12011218
**Geom Types**:
12021219

1203-
- **Basic**: `point`, `line`, `path`, `bar`, `col`, `area`, `tile`, `polygon`, `ribbon`
1220+
- **Basic**: `point`, `line`, `path`, `bar`, `col`, `area`, `rect`, `polygon`, `ribbon`
12041221
- **Statistical**: `histogram`, `density`, `smooth`, `boxplot`, `violin`
12051222
- **Annotation**: `text`, `label`, `segment`, `arrow`, `rule`, `linear`, `errorbar`
12061223

@@ -1211,7 +1228,7 @@ Maps data values (columns or literals) to visual aesthetics. Syntax: `value AS a
12111228
- **Position**: `x`, `y`, `xmin`, `xmax`, `ymin`, `ymax`
12121229
- **Color**: `color`, `fill`, `stroke`, `opacity`
12131230
- **Size/Shape**: `size`, `shape`, `linetype`, `linewidth`
1214-
- **Text**: `label`, `family`, `fontface`
1231+
- **Text**: `label`, `typeface`, `fontweight`, `italic`
12151232

12161233
**Literal vs Column**:
12171234

@@ -1289,6 +1306,29 @@ DRAW line
12891306
FILTER year >= 2020
12901307
```
12911308

1309+
### PLACE Clause (Annotation Layers)
1310+
1311+
**Syntax**:
1312+
1313+
```sql
1314+
PLACE <geom> SETTING <aesthetic/parameter> => <value>, ...
1315+
```
1316+
1317+
Creates annotation layers with literal values only (no data mappings). All aesthetics set via SETTING; supports arrays that are recycled to longest length. No FILTER/PARTITION BY/ORDER BY support.
1318+
1319+
**Examples**:
1320+
1321+
```sql
1322+
-- Single annotation
1323+
PLACE point SETTING x => 5, y => 10, color => 'red'
1324+
1325+
-- Multiple annotations (array recycling)
1326+
PLACE point SETTING x => [1, 2, 3], y => [10, 20, 30]
1327+
1328+
-- Reference line
1329+
PLACE rule SETTING x => 5, color => 'red'
1330+
```
1331+
12921332
### SCALE Clause
12931333

12941334
**Syntax**:

doc/_quarto.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ website:
4040
href: syntax/clause/visualise.qmd
4141
- text: "`DRAW`"
4242
href: syntax/clause/draw.qmd
43+
- text: "`PLACE`"
44+
href: syntax/clause/place.qmd
4345
- text: "`SCALE`"
4446
href: syntax/clause/scale.qmd
4547
- text: "`FACET`"
@@ -77,6 +79,8 @@ website:
7779
href: syntax/clause/visualise.qmd
7880
- text: "`DRAW`"
7981
href: syntax/clause/draw.qmd
82+
- text: "`PLACE`"
83+
href: syntax/clause/place.qmd
8084
- text: "`SCALE`"
8185
href: syntax/clause/scale.qmd
8286
- text: "`FACET`"

doc/ggsql.xml

Lines changed: 53 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@
9090
<!-- ggsql Main Clause Keywords (triggers context switch) -->
9191
<list name="clause_keywords">
9292
<item>DRAW</item>
93+
<item>PLACE</item>
9394
<item>SCALE</item>
9495
<item>PROJECT</item>
9596
<item>FACET</item>
@@ -129,7 +130,7 @@
129130
<item>bar</item>
130131
<item>col</item>
131132
<item>area</item>
132-
<item>tile</item>
133+
<item>rect</item>
133134
<item>polygon</item>
134135
<item>ribbon</item>
135136
<item>histogram</item>
@@ -168,8 +169,9 @@
168169
<item>linewidth</item>
169170
<item>width</item>
170171
<item>height</item>
171-
<item>family</item>
172-
<item>fontface</item>
172+
<item>typeface</item>
173+
<item>fontweight</item>
174+
<item>italic</item>
173175
<item>hjust</item>
174176
<item>vjust</item>
175177
</list>
@@ -403,6 +405,7 @@
403405

404406
<!-- Clause keywords trigger context switches -->
405407
<WordDetect attribute="Keyword" context="DrawClause" String="DRAW" insensitive="true"/>
408+
<WordDetect attribute="Keyword" context="PlaceClause" String="PLACE" insensitive="true"/>
406409
<WordDetect attribute="Keyword" context="ScaleClause" String="SCALE" insensitive="true"/>
407410
<WordDetect attribute="Keyword" context="ProjectClause" String="PROJECT" insensitive="true"/>
408411
<WordDetect attribute="Keyword" context="FacetClause" String="FACET" insensitive="true"/>
@@ -450,6 +453,7 @@
450453

451454
<!-- Exit to other clause contexts -->
452455
<WordDetect attribute="Keyword" context="DrawClause" String="DRAW" insensitive="true"/>
456+
<WordDetect attribute="Keyword" context="PlaceClause" String="PLACE" insensitive="true"/>
453457
<WordDetect attribute="Keyword" context="ScaleClause" String="SCALE" insensitive="true"/>
454458
<WordDetect attribute="Keyword" context="ProjectClause" String="PROJECT" insensitive="true"/>
455459
<WordDetect attribute="Keyword" context="FacetClause" String="FACET" insensitive="true"/>
@@ -480,6 +484,46 @@
480484
<DetectChar char="," attribute="Symbol" context="#stay"/>
481485
</context>
482486

487+
<!-- PLACE clause context (annotation layers) -->
488+
<context name="PlaceClause" attribute="Normal Text" lineEndContext="#stay">
489+
<Detect2Chars char="-" char1="-" attribute="Comment" context="Comment"/>
490+
<Detect2Chars char="/" char1="*" attribute="Comment" context="CommentMulti" beginRegion="comment"/>
491+
<DetectChar char="'" attribute="String" context="StringSingle"/>
492+
<DetectChar char="&quot;" attribute="String" context="StringDouble"/>
493+
<RegExpr attribute="Number" context="#stay" String="-?[0-9]+\.?[0-9]*([eE][+-]?[0-9]+)?"/>
494+
495+
<!-- Exit to other clause contexts -->
496+
<WordDetect attribute="Keyword" context="DrawClause" String="DRAW" insensitive="true"/>
497+
<WordDetect attribute="Keyword" context="PlaceClause" String="PLACE" insensitive="true"/>
498+
<WordDetect attribute="Keyword" context="ScaleClause" String="SCALE" insensitive="true"/>
499+
<WordDetect attribute="Keyword" context="ProjectClause" String="PROJECT" insensitive="true"/>
500+
<WordDetect attribute="Keyword" context="FacetClause" String="FACET" insensitive="true"/>
501+
<WordDetect attribute="Keyword" context="LabelClause" String="LABEL" insensitive="true"/>
502+
<WordDetect attribute="Keyword" context="ThemeClause" String="THEME" insensitive="true"/>
503+
<WordDetect attribute="Keyword" context="Normal" String="VISUALISE" insensitive="true"/>
504+
<WordDetect attribute="Keyword" context="Normal" String="VISUALIZE" insensitive="true"/>
505+
<WordDetect attribute="Keyword" context="Normal" String="SELECT" insensitive="true"/>
506+
<WordDetect attribute="Keyword" context="Normal" String="WHERE" insensitive="true"/>
507+
<WordDetect attribute="Keyword" context="Normal" String="WITH" insensitive="true"/>
508+
509+
<!-- Geom types - same as DRAW -->
510+
<keyword attribute="Data Type" context="#stay" String="geoms"/>
511+
512+
<!-- Aesthetics -->
513+
<keyword attribute="Attribute" context="#stay" String="aesthetics"/>
514+
515+
<!-- Sub-keywords (only SETTING supported, not FILTER/PARTITION/ORDER) -->
516+
<WordDetect attribute="Keyword" context="#stay" String="SETTING" insensitive="true"/>
517+
518+
<StringDetect attribute="Operator" context="#stay" String="=&gt;"/>
519+
<AnyChar attribute="Operator" context="#stay" String="=!&lt;&gt;+-*/%"/>
520+
<DetectChar char="(" attribute="Symbol" context="#stay"/>
521+
<DetectChar char=")" attribute="Symbol" context="#stay"/>
522+
<DetectChar char="[" attribute="Symbol" context="#stay"/>
523+
<DetectChar char="]" attribute="Symbol" context="#stay"/>
524+
<DetectChar char="," attribute="Symbol" context="#stay"/>
525+
</context>
526+
483527
<!-- SCALE clause context -->
484528
<context name="ScaleClause" attribute="Normal Text" lineEndContext="#stay">
485529
<Detect2Chars char="-" char1="-" attribute="Comment" context="Comment"/>
@@ -490,6 +534,7 @@
490534

491535
<!-- Exit to other clause contexts -->
492536
<WordDetect attribute="Keyword" context="DrawClause" String="DRAW" insensitive="true"/>
537+
<WordDetect attribute="Keyword" context="PlaceClause" String="PLACE" insensitive="true"/>
493538
<WordDetect attribute="Keyword" context="ScaleClause" String="SCALE" insensitive="true"/>
494539
<WordDetect attribute="Keyword" context="ProjectClause" String="PROJECT" insensitive="true"/>
495540
<WordDetect attribute="Keyword" context="FacetClause" String="FACET" insensitive="true"/>
@@ -536,6 +581,7 @@
536581

537582
<!-- Exit to other clause contexts -->
538583
<WordDetect attribute="Keyword" context="DrawClause" String="DRAW" insensitive="true"/>
584+
<WordDetect attribute="Keyword" context="PlaceClause" String="PLACE" insensitive="true"/>
539585
<WordDetect attribute="Keyword" context="ScaleClause" String="SCALE" insensitive="true"/>
540586
<WordDetect attribute="Keyword" context="ProjectClause" String="PROJECT" insensitive="true"/>
541587
<WordDetect attribute="Keyword" context="FacetClause" String="FACET" insensitive="true"/>
@@ -579,6 +625,7 @@
579625

580626
<!-- Exit to other clause contexts -->
581627
<WordDetect attribute="Keyword" context="DrawClause" String="DRAW" insensitive="true"/>
628+
<WordDetect attribute="Keyword" context="PlaceClause" String="PLACE" insensitive="true"/>
582629
<WordDetect attribute="Keyword" context="ScaleClause" String="SCALE" insensitive="true"/>
583630
<WordDetect attribute="Keyword" context="ProjectClause" String="PROJECT" insensitive="true"/>
584631
<WordDetect attribute="Keyword" context="FacetClause" String="FACET" insensitive="true"/>
@@ -621,6 +668,7 @@
621668

622669
<!-- Exit to other clause contexts -->
623670
<WordDetect attribute="Keyword" context="DrawClause" String="DRAW" insensitive="true"/>
671+
<WordDetect attribute="Keyword" context="PlaceClause" String="PLACE" insensitive="true"/>
624672
<WordDetect attribute="Keyword" context="ScaleClause" String="SCALE" insensitive="true"/>
625673
<WordDetect attribute="Keyword" context="ProjectClause" String="PROJECT" insensitive="true"/>
626674
<WordDetect attribute="Keyword" context="FacetClause" String="FACET" insensitive="true"/>
@@ -658,6 +706,7 @@
658706

659707
<!-- Exit to other clause contexts -->
660708
<WordDetect attribute="Keyword" context="DrawClause" String="DRAW" insensitive="true"/>
709+
<WordDetect attribute="Keyword" context="PlaceClause" String="PLACE" insensitive="true"/>
661710
<WordDetect attribute="Keyword" context="ScaleClause" String="SCALE" insensitive="true"/>
662711
<WordDetect attribute="Keyword" context="ProjectClause" String="PROJECT" insensitive="true"/>
663712
<WordDetect attribute="Keyword" context="FacetClause" String="FACET" insensitive="true"/>
@@ -698,6 +747,7 @@
698747

699748
<!-- Exit to other clause contexts -->
700749
<WordDetect attribute="Keyword" context="DrawClause" String="DRAW" insensitive="true"/>
750+
<WordDetect attribute="Keyword" context="PlaceClause" String="PLACE" insensitive="true"/>
701751
<WordDetect attribute="Keyword" context="ScaleClause" String="SCALE" insensitive="true"/>
702752
<WordDetect attribute="Keyword" context="ProjectClause" String="PROJECT" insensitive="true"/>
703753
<WordDetect attribute="Keyword" context="FacetClause" String="FACET" insensitive="true"/>

doc/syntax/clause/place.qmd

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
---
2+
title: "Create annotation layers with `PLACE`"
3+
---
4+
5+
The `PLACE` clause is the little sibling of the [`DRAW` clause](draw.qmd) that also creates layers.
6+
A layer created with `PLACE` has no mappings to data, all aesthetics are set using literal values instead.
7+
8+
## Clause syntax
9+
The `PLACE` clause takes just a type and a setting clause, all of them required.
10+
11+
```ggsql
12+
PLACE <layer-type>
13+
SETTING <parameter/aesthetic> => <value>, ...
14+
```
15+
16+
Like `DRAW`, the layer type is required and specifies the type of layer to draw, like `point` or `text`.
17+
It defines how the remaining settings are interpreted.
18+
The [main syntax page](../index.qmd#layers) has a list of all available layer types
19+
20+
Unlike the `DRAW` clause, the `PLACE` clause does not support `FILTER`, `PARTITION BY`, and `ORDER BY` clauses since
21+
everything is declared inline.
22+
23+
### `SETTING`
24+
```ggsql
25+
SETTING <parameter/aesthetic> => <value>, ...
26+
```
27+
28+
The `SETTING` clause can be used for two different things:
29+
30+
* *Setting aesthetics*: All aesthetics in `PLACE` layers are specified using literal value, e.g. 'red' (as in the color red).
31+
Aesthetics that are set will not go through a scale but will use the provided value as-is.
32+
You cannot set an aesthetic to a column, only to a literal values.
33+
Contrary to `DRAW` layers, `PLACE` layers can take multiple literal values in an array.
34+
* *Setting parameters*: Some layers take additional arguments that control how they behave.
35+
Often, but not always, these modify the statistical transformation in some way.
36+
An example would be the binwidth parameter in histogram which controls the width of each bin during histogram calculation.
37+
This is not a statistical property since it is not related to each record, but to the calculation as a whole.

doc/syntax/index.qmd

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ ggsql augments the standard SQL syntax with a number of new clauses to describe
77

88
- [`VISUALISE`](clause/visualise.qmd) initiates the visualisation part of the query
99
- [`DRAW`](clause/draw.qmd) adds a new layer to the visualisation
10+
- [`PLACE`](clause/place.qmd) adds an annotation layer
1011
- [`SCALE`](clause/scale.qmd) specify how an aesthetic should be scaled
1112
- [`FACET`](clause/facet.qmd) describes how data should be split into small multiples
1213
- [`PROJECT`](clause/project.qmd) is used for selecting the coordinate system to use
@@ -25,12 +26,14 @@ There are many different layers to choose from when visualising your data. Some
2526
- [`area`](layer/type/area.qmd) is used to display series as an area chart.
2627
- [`ribbon`](layer/type/ribbon.qmd) is used to display series extrema.
2728
- [`polygon`](layer/type/polygon.qmd) is used to display arbitrary shapes as polygons.
29+
- [`text`](layer/text.qmd) is used to render datapoints as text.
2830
- [`bar`](layer/type/bar.qmd) creates a bar chart, optionally calculating y from the number of records in each bar.
2931
- [`density`](layer/type/density.qmd) creates univariate kernel density estimates, showing the distribution of a variable.
3032
- [`violin`](layer/type/violin.qmd) displays a rotated kernel density estimate.
3133
- [`histogram`](layer/type/histogram.qmd) bins the data along the x axis and produces a bar for each bin showing the number of records in it.
3234
- [`boxplot`](layer/type/boxplot.qmd) displays continuous variables as 5-number summaries.
3335
- [`errorbar`](layer/type/errorbar.qmd) a line segment with hinges at the endpoints.
36+
- [`smooth`](layer/type/smooth.qmd) a trendline that follows the data shape.
3437

3538
### Position adjustments
3639
- [`stack`](layer/position/stack.qmd) places objects with a shared baseline on top of each other.

doc/syntax/layer/type/linear.qmd

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,10 @@ Add a simple reference line to a scatterplot:
4646
```{ggsql}
4747
VISUALISE FROM ggsql:penguins
4848
DRAW point MAPPING bill_len AS x, bill_dep AS y
49-
DRAW linear MAPPING 0.4 AS coef, -1 AS intercept
49+
PLACE linear SETTING coef => 0.4, intercept => -1
5050
```
5151

52-
Add multiple reference lines with different colors from a separate dataset:
52+
Add multiple reference lines with different colors from a separate dataset. Note we're mapping from data here, so we use `DRAW` instead of `PLACE`.
5353

5454
```{ggsql}
5555
WITH lines AS (

0 commit comments

Comments
 (0)