Skip to content

Commit 7203852

Browse files
authored
Adds PartiqlShapeBuilder with NodeId generation for the StaticType (#485)
* Adds `NodeId` to the `StaticType` This PR - adds `NodeId` to `StaticType`; this is to be able to use the `id` as a reference to add additional data to the types out of band. - makes `AutoNodeIdGenerator` thread-safe - adds `PartiqlShapeBuilder` and moves some `PartiqlShape` APIs to it; this is to be able to generate unique `NodeId`s for a `PartiqlShape` that includes static types that themselves can include other static types. - adds a static thread safe `shape_builder` function that provides a convenient way for using `PartiqlShapeBuilder` for creating new shapes. - prepends existing type macros with `type` such as `type_int!` to make macro names more friendly. - removes `const` PartiQL types under `partiql-types` in favor of `PartiqlShapeBuilder`. **_The majority of the diffs are related to the macro renames or replacement with the previous `const` types. The main change is in `partiql-types/src/lib.rs` file._**
1 parent e5b8ce7 commit 7203852

File tree

16 files changed

+714
-483
lines changed

16 files changed

+714
-483
lines changed

.gitmodules

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
[submodule "partiql-conformance-tests/partiql-tests"]
22
path = partiql-conformance-tests/partiql-tests
3-
url = git@github.com:partiql/partiql-tests.git
3+
url = https://github.com/partiql/partiql-tests.git

CHANGELOG.md

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,24 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1111
- partiql-ast: improved pretty-printing of `CASE` and various clauses
1212
-
1313
### Added
14+
- Added `partiql-common`.
15+
- Added `NodeId` to `StaticType`.
16+
- *BREAKING* Added thread-safe `PartiqlShapeBuilder` and automatic `NodeId` generation for the `StaticType`.
17+
- Added a static thread safe `shape_builder` function that provides a convenient way for using `PartiqlShapeBuilder` for creating new shapes.
1418

15-
### Fixed
19+
### Removed
20+
- *BREAKING* Removed `partiql-source-map`.
21+
- *BREAKING* Removed `const` PartiQL types under `partiql-types` in favor of `PartiqlShapeBuilder`.
22+
- *BREAKING* Removed `StaticType`'s `new`, `new_non_nullable`, and `as_non-nullable` APIs in favor of `PartiqlShapeBuilder`.
1623

1724
## [0.10.0]
1825
### Changed
1926
- *BREAKING:* partiql-ast: added modeling of `EXCLUDE`
2027
- *BREAKING:* partiql-ast: added pretty-printing of `EXCLUDE`
28+
- *BREAKING* Moved some of the `PartiqlShape` APIs to the `PartiqlShapeBuilder`.
29+
- *BREAKING* Prepended existing type macros with `type` to make macro names more friendly: e.g., `type_int!`
30+
- *BREAKING* Moved node id generation and `partiql-source-map` to it.
31+
- *BREAKING* Changed `AutoNodeIdGenerator` to a thread-safe version
2132

2233
### Added
2334
- *BREAKING:* partiql-parser: added parsing of `EXCLUDE`

extension/partiql-extension-ddl/src/ddl.rs

Lines changed: 35 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -123,8 +123,8 @@ impl PartiqlBasicDdlEncoder {
123123
Static::Float64 => out.push_str("DOUBLE"),
124124
Static::String => out.push_str("VARCHAR"),
125125
Static::Struct(s) => out.push_str(&self.write_struct(s)?),
126-
Static::Bag(b) => out.push_str(&self.write_bag(b)?),
127-
Static::Array(a) => out.push_str(&self.write_array(a)?),
126+
Static::Bag(b) => out.push_str(&self.write_type_bag(b)?),
127+
Static::Array(a) => out.push_str(&self.write_type_array(a)?),
128128
// non-exhaustive catch-all
129129
_ => todo!("handle type for {}", ty),
130130
}
@@ -136,12 +136,18 @@ impl PartiqlBasicDdlEncoder {
136136
Ok(out)
137137
}
138138

139-
fn write_bag(&self, bag: &BagType) -> ShapeDdlEncodeResult<String> {
140-
Ok(format!("BAG<{}>", self.write_shape(bag.element_type())?))
139+
fn write_type_bag(&self, type_bag: &BagType) -> ShapeDdlEncodeResult<String> {
140+
Ok(format!(
141+
"type_bag<{}>",
142+
self.write_shape(type_bag.element_type())?
143+
))
141144
}
142145

143-
fn write_array(&self, arr: &ArrayType) -> ShapeDdlEncodeResult<String> {
144-
Ok(format!("ARRAY<{}>", self.write_shape(arr.element_type())?))
146+
fn write_type_array(&self, arr: &ArrayType) -> ShapeDdlEncodeResult<String> {
147+
Ok(format!(
148+
"type_array<{}>",
149+
self.write_shape(arr.element_type())?
150+
))
145151
}
146152

147153
fn write_struct(&self, strct: &StructType) -> ShapeDdlEncodeResult<String> {
@@ -189,8 +195,8 @@ impl PartiqlDdlEncoder for PartiqlBasicDdlEncoder {
189195
let mut output = String::new();
190196
let ty = ty.expect_static()?;
191197

192-
if let Static::Bag(bag) = ty.ty() {
193-
let s = bag.element_type().expect_struct()?;
198+
if let Static::Bag(type_bag) = ty.ty() {
199+
let s = type_bag.element_type().expect_struct()?;
194200
let mut fields = s.fields().peekable();
195201
while let Some(field) = fields.next() {
196202
output.push_str(&format!("\"{}\" ", field.name()));
@@ -223,41 +229,47 @@ impl PartiqlDdlEncoder for PartiqlBasicDdlEncoder {
223229
mod tests {
224230
use super::*;
225231
use indexmap::IndexSet;
226-
use partiql_types::{array, bag, f64, int8, r#struct, str, struct_fields, StructConstraint};
232+
use partiql_types::{
233+
struct_fields, type_array, type_bag, type_float64, type_int8, type_string, type_struct,
234+
PartiqlShapeBuilder, StructConstraint,
235+
};
227236

228237
#[test]
229238
fn ddl_test() {
230239
let nested_attrs = struct_fields![
231240
(
232241
"a",
233-
PartiqlShape::any_of(vec![
234-
PartiqlShape::new(Static::DecimalP(5, 4)),
235-
PartiqlShape::new(Static::Int8),
242+
PartiqlShapeBuilder::init_or_get().any_of(vec![
243+
PartiqlShapeBuilder::init_or_get().new_static(Static::DecimalP(5, 4)),
244+
PartiqlShapeBuilder::init_or_get().new_static(Static::Int8),
236245
])
237246
),
238-
("b", array![str![]]),
239-
("c", f64!()),
247+
("b", type_array![type_string![]]),
248+
("c", type_float64!()),
240249
];
241-
let details = r#struct![IndexSet::from([nested_attrs])];
250+
let details = type_struct![IndexSet::from([nested_attrs])];
242251

243252
let fields = struct_fields![
244-
("employee_id", int8![]),
245-
("full_name", str![]),
246-
("salary", PartiqlShape::new(Static::DecimalP(8, 2))),
253+
("employee_id", type_int8![]),
254+
("full_name", type_string![]),
255+
(
256+
"salary",
257+
PartiqlShapeBuilder::init_or_get().new_static(Static::DecimalP(8, 2))
258+
),
247259
("details", details),
248-
("dependents", array![str![]])
260+
("dependents", type_array![type_string![]])
249261
];
250-
let ty = bag![r#struct![IndexSet::from([
262+
let ty = type_bag![type_struct![IndexSet::from([
251263
fields,
252264
StructConstraint::Open(false)
253265
])]];
254266

255-
let expected_compact = r#""employee_id" TINYINT,"full_name" VARCHAR,"salary" DECIMAL(8, 2),"details" STRUCT<"a": UNION<DECIMAL(5, 4),TINYINT>,"b": ARRAY<VARCHAR>,"c": DOUBLE>,"dependents" ARRAY<VARCHAR>"#;
267+
let expected_compact = r#""employee_id" TINYINT,"full_name" VARCHAR,"salary" DECIMAL(8, 2),"details" STRUCT<"a": UNION<DECIMAL(5, 4),TINYINT>,"b": type_array<VARCHAR>,"c": DOUBLE>,"dependents" type_array<VARCHAR>"#;
256268
let expected_pretty = r#""employee_id" TINYINT,
257269
"full_name" VARCHAR,
258270
"salary" DECIMAL(8, 2),
259-
"details" STRUCT<"a": UNION<DECIMAL(5, 4),TINYINT>,"b": ARRAY<VARCHAR>,"c": DOUBLE>,
260-
"dependents" ARRAY<VARCHAR>"#;
271+
"details" STRUCT<"a": UNION<DECIMAL(5, 4),TINYINT>,"b": type_array<VARCHAR>,"c": DOUBLE>,
272+
"dependents" type_array<VARCHAR>"#;
261273

262274
let ddl_compact = PartiqlBasicDdlEncoder::new(DdlFormat::Compact);
263275
assert_eq!(ddl_compact.ddl(&ty).expect("write shape"), expected_compact);

extension/partiql-extension-ddl/tests/ddl-tests.rs

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,26 @@
11
use indexmap::IndexSet;
22
use partiql_extension_ddl::ddl::{DdlFormat, PartiqlBasicDdlEncoder, PartiqlDdlEncoder};
3-
use partiql_types::{bag, int, r#struct, str, struct_fields, StructConstraint, StructField};
4-
use partiql_types::{BagType, PartiqlShape, Static, StructType};
3+
use partiql_types::{
4+
struct_fields, type_bag, type_int, type_string, type_struct, PartiqlShapeBuilder,
5+
StructConstraint, StructField,
6+
};
7+
use partiql_types::{BagType, Static, StructType};
58

69
#[test]
710
fn basic_ddl_test() {
8-
let details_fields = struct_fields![("age", int!())];
9-
let details = r#struct![IndexSet::from([details_fields])];
11+
let details_fields = struct_fields![("age", type_int!())];
12+
let details = type_struct![IndexSet::from([details_fields])];
1013
let fields = [
11-
StructField::new("id", int!()),
12-
StructField::new("name", str!()),
13-
StructField::new("address", PartiqlShape::new_non_nullable(Static::String)),
14+
StructField::new("id", type_int!()),
15+
StructField::new("name", type_string!()),
16+
StructField::new(
17+
"address",
18+
PartiqlShapeBuilder::init_or_get().new_non_nullable_static(Static::String),
19+
),
1420
StructField::new_optional("details", details.clone()),
1521
]
1622
.into();
17-
let shape = bag![r#struct![IndexSet::from([
23+
let shape = type_bag![type_struct![IndexSet::from([
1824
StructConstraint::Fields(fields),
1925
StructConstraint::Open(false)
2026
])]];

partiql-ast/src/builder.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ where
1717

1818
pub fn node<T>(&mut self, node: T) -> AstNode<T> {
1919
let id = self.id_gen.id();
20-
AstNode { id, node }
20+
let id = id.read().expect("NodId read lock");
21+
AstNode { id: *id, node }
2122
}
2223
}
2324

partiql-common/src/node.rs

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use indexmap::IndexMap;
22
use std::hash::Hash;
3+
use std::sync::{Arc, RwLock};
34

45
#[cfg(feature = "serde")]
56
use serde::{Deserialize, Serialize};
@@ -12,27 +13,37 @@ pub struct NodeId(pub u32);
1213

1314
/// Auto-incrementing [`NodeIdGenerator`]
1415
pub struct AutoNodeIdGenerator {
15-
next_id: NodeId,
16+
next_id: Arc<RwLock<NodeId>>,
1617
}
1718

1819
impl Default for AutoNodeIdGenerator {
1920
fn default() -> Self {
20-
AutoNodeIdGenerator { next_id: NodeId(1) }
21+
AutoNodeIdGenerator {
22+
next_id: Arc::new(RwLock::from(NodeId(1))),
23+
}
2124
}
2225
}
2326

2427
/// A provider of 'fresh' [`NodeId`]s.
2528
pub trait NodeIdGenerator {
29+
fn id(&self) -> Arc<RwLock<NodeId>>;
30+
2631
/// Provides a 'fresh' [`NodeId`].
27-
fn id(&mut self) -> NodeId;
32+
fn next_id(&self) -> NodeId;
2833
}
2934

3035
impl NodeIdGenerator for AutoNodeIdGenerator {
36+
fn id(&self) -> Arc<RwLock<NodeId>> {
37+
let id = self.next_id();
38+
let mut w = self.next_id.write().expect("NodId write lock");
39+
*w = id;
40+
Arc::clone(&self.next_id)
41+
}
42+
3143
#[inline]
32-
fn id(&mut self) -> NodeId {
33-
let mut next = NodeId(&self.next_id.0 + 1);
34-
std::mem::swap(&mut self.next_id, &mut next);
35-
next
44+
fn next_id(&self) -> NodeId {
45+
let id = &self.next_id.read().expect("NodId read lock");
46+
NodeId(id.0 + 1)
3647
}
3748
}
3849

@@ -41,7 +52,11 @@ impl NodeIdGenerator for AutoNodeIdGenerator {
4152
pub struct NullIdGenerator {}
4253

4354
impl NodeIdGenerator for NullIdGenerator {
44-
fn id(&mut self) -> NodeId {
55+
fn id(&self) -> Arc<RwLock<NodeId>> {
56+
Arc::new(RwLock::from(self.next_id()))
57+
}
58+
59+
fn next_id(&self) -> NodeId {
4560
NodeId(0)
4661
}
4762
}

partiql-eval/src/eval/eval_expr_wrapper.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use crate::eval::expr::{BindError, EvalExpr};
44
use crate::eval::EvalContext;
55
use itertools::Itertools;
66

7-
use partiql_types::{PartiqlShape, Static, TYPE_DYNAMIC};
7+
use partiql_types::{type_dynamic, PartiqlShape, Static, TYPE_DYNAMIC};
88
use partiql_value::Value::{Missing, Null};
99
use partiql_value::{Tuple, Value};
1010

@@ -413,7 +413,7 @@ impl UnaryValueExpr {
413413
where
414414
F: 'static + Fn(&Value) -> Value,
415415
{
416-
Self::create_typed::<STRICT, F>([TYPE_DYNAMIC; 1], args, f)
416+
Self::create_typed::<STRICT, F>([type_dynamic!(); 1], args, f)
417417
}
418418

419419
#[allow(dead_code)]

partiql-eval/src/eval/expr/coll.rs

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@ use crate::eval::expr::{BindError, BindEvalExpr, EvalExpr};
44

55
use itertools::{Itertools, Unique};
66

7-
use partiql_types::{ArrayType, BagType, PartiqlShape, Static, TYPE_BOOL, TYPE_NUMERIC_TYPES};
7+
use partiql_types::{
8+
type_bool, type_numeric, ArrayType, BagType, PartiqlShape, PartiqlShapeBuilder, Static,
9+
};
810
use partiql_value::Value::{Missing, Null};
911
use partiql_value::{BinaryAnd, BinaryOr, Value, ValueIter};
1012

@@ -49,21 +51,23 @@ impl BindEvalExpr for EvalCollFn {
4951
value.sequence_iter().map_or(Missing, &f)
5052
})
5153
}
52-
let boolean_elems = [PartiqlShape::any_of([
53-
PartiqlShape::new(Static::Array(ArrayType::new(Box::new(TYPE_BOOL)))),
54-
PartiqlShape::new(Static::Bag(BagType::new(Box::new(TYPE_BOOL)))),
54+
let boolean_elems = [PartiqlShapeBuilder::init_or_get().any_of([
55+
PartiqlShapeBuilder::init_or_get()
56+
.new_static(Static::Array(ArrayType::new(Box::new(type_bool!())))),
57+
PartiqlShapeBuilder::init_or_get()
58+
.new_static(Static::Bag(BagType::new(Box::new(type_bool!())))),
5559
])];
56-
let numeric_elems = [PartiqlShape::any_of([
57-
PartiqlShape::new(Static::Array(ArrayType::new(Box::new(
58-
PartiqlShape::any_of(TYPE_NUMERIC_TYPES),
60+
let numeric_elems = [PartiqlShapeBuilder::init_or_get().any_of([
61+
PartiqlShapeBuilder::init_or_get().new_static(Static::Array(ArrayType::new(Box::new(
62+
PartiqlShapeBuilder::init_or_get().any_of(type_numeric!()),
63+
)))),
64+
PartiqlShapeBuilder::init_or_get().new_static(Static::Bag(BagType::new(Box::new(
65+
PartiqlShapeBuilder::init_or_get().any_of(type_numeric!()),
5966
)))),
60-
PartiqlShape::new(Static::Bag(BagType::new(Box::new(PartiqlShape::any_of(
61-
TYPE_NUMERIC_TYPES,
62-
))))),
6367
])];
64-
let any_elems = [PartiqlShape::any_of([
65-
PartiqlShape::new(Static::Array(ArrayType::new_any())),
66-
PartiqlShape::new(Static::Bag(BagType::new_any())),
68+
let any_elems = [PartiqlShapeBuilder::init_or_get().any_of([
69+
PartiqlShapeBuilder::init_or_get().new_static(Static::Array(ArrayType::new_any())),
70+
PartiqlShapeBuilder::init_or_get().new_static(Static::Bag(BagType::new_any())),
6771
])];
6872

6973
match *self {

partiql-eval/src/eval/expr/datetime.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::eval::expr::{BindError, BindEvalExpr, EvalExpr};
22

3-
use partiql_types::TYPE_DATETIME;
3+
use partiql_types::type_datetime;
44
use partiql_value::Value::Missing;
55
use partiql_value::{DateTime, Value};
66

@@ -43,7 +43,7 @@ impl BindEvalExpr for EvalExtractFn {
4343
}
4444

4545
let create = |f: fn(&DateTime) -> Value| {
46-
UnaryValueExpr::create_typed::<{ STRICT }, _>([TYPE_DATETIME], args, move |value| {
46+
UnaryValueExpr::create_typed::<{ STRICT }, _>([type_datetime!()], args, move |value| {
4747
match value {
4848
Value::DateTime(dt) => f(dt.as_ref()),
4949
_ => Missing,

0 commit comments

Comments
 (0)