Skip to content

Commit ba0bf3f

Browse files
committed
implement suggestions from review
1 parent fe8fae0 commit ba0bf3f

23 files changed

Lines changed: 286 additions & 116 deletions

CHANGELOG.md

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,7 @@
55
- New `aggregate` SETTING on Identity-stat layers (point, line, area, bar, ribbon,
66
range, segment, arrow, rule, text). By default it collapses each group to a
77
single row by replacing every numeric mapping in place with its aggregated
8-
value. Accepts a single string or array of strings; entries are either
9-
unprefixed defaults (`'mean'`) or per-aesthetic targets (`'y:max'`,
10-
`'color:median'`). Up to two defaults may be supplied — the first applies to
11-
lower-half aesthetics plus all non-range layers, the second to upper-half
12-
(`max`/`end` suffix). Numeric mappings without a target or applicable default
13-
are dropped with a warning. Targeting the same aesthetic more than once
14-
(e.g. `aggregate => ('y:min', 'y:max')`) produces one row per function with
15-
a synthetic `aggregate` column tagging each row, available for `REMAPPING` to
16-
another aesthetic; targets with a single function and the unprefixed defaults
17-
are reused unchanged across the exploded rows. The `aggregate` column's value
18-
is built from the dedup-and-joined function names of all exploded targets at
19-
each row, separated by `/` (so `('y:min', 'y:max', 'color:sum', 'color:prod')`
20-
yields `'min/sum'` and `'max/prod'`). Mixed lengths above 1 are an error.
8+
value. See the `DRAW` documentation for details.
219
- Added panel decorations (grid lines, axes, background) for polar coordinates (#156).
2210
- Added `radar` setting to polar coordinates for making radar plots (#418).
2311

@@ -27,7 +15,7 @@
2715

2816
- Side effects like `CREATE TEMP TABLE` before the `VISUALISE` statement are now
2917
separated from directly feeding into the visualisation data (#415)
30-
- Fixed bug where panel axes were unintentionally anchored to zero when using
18+
- Fixed bug where panel axes were unintentionally anchored to zero when using
3119
`FACET ... SETTING free => 'x'/'y'` (#410).
3220
- Fixed bug where faceted data were matched to the incorrect panels (#409)
3321

@@ -47,7 +35,6 @@ issues on Linux and macOS caused by relative paths to dynamic libraries.
4735

4836
### Added
4937

50-
5138
- Add cell delimiters and code lens actions to the Positron extension (#366)
5239
- ODBC is now turned on for the CLI as well (#344)
5340
- `FROM` can now come before `VISUALIZE`, mirroring the DuckDB style. This means
@@ -96,7 +83,6 @@ portion (#364).
9683
- Removed polars from dependency list along with all its transient dependencies. Rewrote DataFrame struct on top of arrow (#350)
9784
- Moved ggsql-python to its own repo (posit-dev/ggsql-python) and cleaned up any additional references to it
9885
- Moved ggsql-r to its own repo (posit-dev/ggsql-r)
99-
- The `orientation` setting on `ribbon` and `range` layers. With explicit `xmin`/`xmax` or `ymin`/`ymax` mappings, orientation is unambiguous and is auto-detected from the mappings; the override is no longer needed.
10086

10187
## [2.7.0] - 2026-04-20
10288

src/naming.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,22 @@ pub fn quote_ident(name: &str) -> String {
240240
format!("\"{}\"", name.replace('"', "\"\""))
241241
}
242242

243+
/// Quote a SQL string literal: wraps in single quotes and escapes embedded
244+
/// single quotes by doubling them, per the SQL standard.
245+
///
246+
/// Use this when interpolating user-supplied (or otherwise variable) string
247+
/// values into SQL literals — e.g. `WHERE name = 'O''Brien'`.
248+
///
249+
/// # Example
250+
/// ```
251+
/// use ggsql::naming;
252+
/// assert_eq!(naming::quote_literal("foo"), "'foo'");
253+
/// assert_eq!(naming::quote_literal("O'Brien"), "'O''Brien'");
254+
/// ```
255+
pub fn quote_literal(s: &str) -> String {
256+
format!("'{}'", s.replace('\'', "''"))
257+
}
258+
243259
// ============================================================================
244260
// Detection Functions
245261
// ============================================================================

src/plot/layer/geom/area.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ impl GeomTrait for Area {
5151
default: DefaultParamValue::String(ALIGNED),
5252
constraint: ParamConstraint::string_option(ORIENTATION_VALUES),
5353
},
54+
super::types::AGGREGATE_PARAM,
5455
];
5556
PARAMS
5657
}

src/plot/layer/geom/arrow.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,14 @@ impl GeomTrait for Arrow {
3232
}
3333

3434
fn default_params(&self) -> &'static [ParamDefinition] {
35-
const PARAMS: &[ParamDefinition] = &[ParamDefinition {
36-
name: "position",
37-
default: DefaultParamValue::String("identity"),
38-
constraint: ParamConstraint::string_option(POSITION_VALUES),
39-
}];
35+
const PARAMS: &[ParamDefinition] = &[
36+
ParamDefinition {
37+
name: "position",
38+
default: DefaultParamValue::String("identity"),
39+
constraint: ParamConstraint::string_option(POSITION_VALUES),
40+
},
41+
super::types::AGGREGATE_PARAM,
42+
];
4043
PARAMS
4144
}
4245

src/plot/layer/geom/bar.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ impl GeomTrait for Bar {
7272
default: DefaultParamValue::String("stack"),
7373
constraint: ParamConstraint::string_option(POSITION_VALUES),
7474
},
75+
super::types::AGGREGATE_PARAM,
7576
];
7677
PARAMS
7778
}

src/plot/layer/geom/line.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,14 @@ impl GeomTrait for Line {
3333
}
3434

3535
fn default_params(&self) -> &'static [ParamDefinition] {
36-
const PARAMS: &[ParamDefinition] = &[ParamDefinition {
37-
name: "orientation",
38-
default: DefaultParamValue::String(ALIGNED),
39-
constraint: ParamConstraint::string_option(ORIENTATION_VALUES),
40-
}];
36+
const PARAMS: &[ParamDefinition] = &[
37+
ParamDefinition {
38+
name: "orientation",
39+
default: DefaultParamValue::String(ALIGNED),
40+
constraint: ParamConstraint::string_option(ORIENTATION_VALUES),
41+
},
42+
super::types::AGGREGATE_PARAM,
43+
];
4144
PARAMS
4245
}
4346

src/plot/layer/geom/mod.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -296,9 +296,6 @@ pub trait GeomTrait: std::fmt::Debug + std::fmt::Display + Send + Sync {
296296
for param in self.default_params() {
297297
valid.push(param.name);
298298
}
299-
if self.supports_aggregate() {
300-
valid.push("aggregate");
301-
}
302299
valid
303300
}
304301
}

src/plot/layer/geom/point.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,14 @@ impl GeomTrait for Point {
3131
}
3232

3333
fn default_params(&self) -> &'static [ParamDefinition] {
34-
const PARAMS: &[ParamDefinition] = &[ParamDefinition {
35-
name: "position",
36-
default: DefaultParamValue::String("identity"),
37-
constraint: ParamConstraint::string_option(POSITION_VALUES),
38-
}];
34+
const PARAMS: &[ParamDefinition] = &[
35+
ParamDefinition {
36+
name: "position",
37+
default: DefaultParamValue::String("identity"),
38+
constraint: ParamConstraint::string_option(POSITION_VALUES),
39+
},
40+
super::types::AGGREGATE_PARAM,
41+
];
3942
PARAMS
4043
}
4144

src/plot/layer/geom/range.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ impl GeomTrait for Range {
4141
default: DefaultParamValue::Number(10.0),
4242
constraint: ParamConstraint::number_min(0.0),
4343
},
44+
super::types::AGGREGATE_PARAM,
4445
];
4546
PARAMS
4647
}

src/plot/layer/geom/ribbon.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,14 @@ impl GeomTrait for Ribbon {
3232
}
3333

3434
fn default_params(&self) -> &'static [ParamDefinition] {
35-
const PARAMS: &[ParamDefinition] = &[ParamDefinition {
36-
name: "position",
37-
default: DefaultParamValue::String("identity"),
38-
constraint: ParamConstraint::string_option(POSITION_VALUES),
39-
}];
35+
const PARAMS: &[ParamDefinition] = &[
36+
ParamDefinition {
37+
name: "position",
38+
default: DefaultParamValue::String("identity"),
39+
constraint: ParamConstraint::string_option(POSITION_VALUES),
40+
},
41+
super::types::AGGREGATE_PARAM,
42+
];
4043
PARAMS
4144
}
4245

0 commit comments

Comments
 (0)