Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
bc9f0a9
feat(partiql): parse PartiQL statements and plan their key reads
LeeroyHannigan Nov 3, 2026
a213fba
feat(partiql): run ExecuteStatement, BatchExecuteStatement and Execut…
LeeroyHannigan Nov 3, 2026
1d458fc
test(partiql): add dual-target wire tests measured against DynamoDB
LeeroyHannigan Nov 3, 2026
0e10290
feat(partiql): authorize each statement with the action of its type
LeeroyHannigan Nov 3, 2026
ef59293
test(partiql): test the authorization of each statement
LeeroyHannigan Nov 3, 2026
8a3f8cd
style(partiql): clear the clippy pedantic warnings of the new code
LeeroyHannigan Nov 3, 2026
af0fac7
fix(partiql): size an UPDATE by its finished item, as the service does
LeeroyHannigan Nov 4, 2026
023404b
Merge origin/main into feat/partiql
LeeroyHannigan Nov 5, 2026
6c7e67c
fix(partiql): sort a batch by the statements that translate
LeeroyHannigan Nov 5, 2026
251490d
fix(partiql): count index units and failed writes in a batch
LeeroyHannigan Nov 5, 2026
26695e3
fix(partiql): check each transaction member in order
LeeroyHannigan Nov 5, 2026
4ba74b0
fix(partiql): honour the projection of a transaction read
LeeroyHannigan Nov 5, 2026
a80f39e
fix(partiql): refuse a statement of only whitespace as empty
LeeroyHannigan Nov 5, 2026
c8c51ed
fix(partiql): check ORDER BY on an index and refuse a path in its list
LeeroyHannigan Nov 5, 2026
095190c
fix(partiql): refuse a path into a key attribute in a write's WHERE
LeeroyHannigan Nov 5, 2026
94e6936
fix(partiql): read a string or a name in brackets as a map member
LeeroyHannigan Nov 5, 2026
b156d29
fix(partiql): read one value or path in parentheses as grouping
LeeroyHannigan Nov 5, 2026
eb92f2f
fix(partiql): refuse a negative zero decimal literal
LeeroyHannigan Nov 5, 2026
a0454c4
style(partiql): apply rustfmt to the PartiQL changes
LeeroyHannigan Nov 5, 2026
90aea5f
fix(partiql): end an operand at a token that does not go on with it
LeeroyHannigan Nov 5, 2026
58e1264
Merge the PartiQL parser fixes into feat/partiql
LeeroyHannigan Nov 5, 2026
c745a3c
fix(partiql): refuse an index key type ahead of a path into a key
LeeroyHannigan Nov 5, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

32 changes: 30 additions & 2 deletions crates/auth/src/policy/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,10 @@ pub struct RequestParams {
pub return_consumed_capacity: Option<String>,
/// The enclosing operation for batch/transact sub-operations.
pub enclosing_operation: Option<String>,
/// `dynamodb:FullTableScan` for a request that is not a scan
/// (`RequestContext::build` sets it to `true` for one). `None` leaves the
/// key absent; a PartiQL read by key sets `false`.
pub full_table_scan: Option<bool>,
/// The caller ARN (`aws:PrincipalArn`), when known.
pub principal_arn: Option<String>,
/// The caller's account id (`aws:PrincipalAccount`), when known.
Expand Down Expand Up @@ -299,7 +303,8 @@ impl RequestContext {
/// Build context for a `DynamoDB` operation.
///
/// `principal_tags` and `resource_tags` come from the identity and target
/// table respectively. `is_scan` should be true for Scan operations.
/// table respectively. `is_scan` should be true for Scan operations; for
/// any other request `params.full_table_scan` gives the key.
/// `params` carries operation-specific request parameters.
#[must_use]
pub fn build(
Expand All @@ -317,7 +322,11 @@ impl RequestContext {
select: params.select,
return_values: params.return_values,
return_consumed_capacity: params.return_consumed_capacity,
full_table_scan: if is_scan { Some(true) } else { None },
full_table_scan: if is_scan {
Some(true)
} else {
params.full_table_scan
},
enclosing_operation: params.enclosing_operation,
principal_arn: params.principal_arn,
principal_account: params.principal_account,
Expand Down Expand Up @@ -997,6 +1006,25 @@ mod tests {
);
}

#[test]
fn request_context_full_table_scan_set_by_the_request() {
// A PartiQL read by key carries "false" (measured 2026-11-03); a
// request that sets nothing leaves the key absent unless it is a scan.
let ctx = RequestContext::build(
HashMap::new(),
HashMap::new(),
false,
RequestParams {
full_table_scan: Some(false),
..Default::default()
},
);
assert_eq!(
ctx.resolve_key("dynamodb:FullTableScan"),
Some(vec!["false"])
);
}

#[test]
fn assume_role_context_external_id() {
let ctx = ar_ctx(HashMap::new(), Some("ext-123".to_owned()), HashMap::new());
Expand Down
6 changes: 6 additions & 0 deletions crates/core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,9 @@ md-5 = { workspace = true }
sha2 = { workspace = true }
time = { workspace = true }
uuid = { workspace = true }

[features]
default = ["partiql"]
# PartiQL grammar, AST and query planning. Removable: with this off, the
# `partiql` module is not compiled and nothing else in core references it.
partiql = []
10 changes: 10 additions & 0 deletions crates/core/src/error/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,13 @@ pub enum DynamoDbError {
LimitExceededException(String),
#[error("{0}")]
ConditionalCheckFailedException(String, Option<Item>),
/// A PartiQL `INSERT` targeted a primary key that already exists.
///
/// `INSERT` is create-only, so a duplicate full key fails with this error
/// rather than `ConditionalCheckFailedException`. HTTP 400. The message is
/// always `Duplicate primary key exists in table`, measured on the service.
#[error("{0}")]
DuplicateItemException(String),
#[error("{message}")]
TransactionCanceledException {
/// Human-readable message.
Expand Down Expand Up @@ -157,6 +164,7 @@ impl DynamoDbError {
| Self::TableNotFoundException(_)
| Self::LimitExceededException(_)
| Self::ConditionalCheckFailedException(..)
| Self::DuplicateItemException(_)
| Self::TransactionCanceledException { .. }
| Self::IdempotentParameterMismatchException(_)
| Self::SerializationException(_)
Expand Down Expand Up @@ -204,6 +212,7 @@ impl DynamoDbError {
Self::TableNotFoundException(_) => "TableNotFoundException",
Self::LimitExceededException(_) => "LimitExceededException",
Self::ConditionalCheckFailedException(..) => "ConditionalCheckFailedException",
Self::DuplicateItemException(_) => "DuplicateItemException",
Self::TransactionCanceledException { .. } => "TransactionCanceledException",
Self::IdempotentParameterMismatchException(_) => "IdempotentParameterMismatchException",
Self::SerializationException(_) => "SerializationException",
Expand Down Expand Up @@ -280,6 +289,7 @@ impl DynamoDbError {
| Self::TableNotFoundException(m)
| Self::LimitExceededException(m)
| Self::ConditionalCheckFailedException(m, _)
| Self::DuplicateItemException(m)
| Self::IdempotentParameterMismatchException(m)
| Self::SerializationException(m)
| Self::UnknownOperationException(m)
Expand Down
6 changes: 6 additions & 0 deletions crates/core/src/expression/resolver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ pub struct ExpressionMaps {
/// and was desugared into an update expression. The service sizes that
/// form against the item limit differently from an expression.
pub legacy_attribute_updates: bool,
/// Set by the engine for an update translated from a PartiQL `UPDATE`.
/// The service sizes that statement by its finished item alone, as it
/// sizes a transacted Update, and not by the statement as it sizes
/// `UpdateItem`.
pub finished_item_sizing: bool,
/// Pre-parsed `BigDecimal` values for numeric placeholders.
/// Populated eagerly by `new()` and refreshed by `pre_parse_numerics()`.
parsed_numerics: HashMap<String, bigdecimal::BigDecimal>,
Expand All @@ -45,6 +50,7 @@ impl ExpressionMaps {
names,
values,
legacy_attribute_updates: false,
finished_item_sizing: false,
parsed_numerics: HashMap::new(),
};
maps.pre_parse_numerics();
Expand Down
2 changes: 2 additions & 0 deletions crates/core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ pub mod error;
pub mod expression;
pub mod limits;
pub mod metrics;
#[cfg(feature = "partiql")]
pub mod partiql;
pub mod serde_helpers;
pub mod settings_keys;
pub mod throttle;
Expand Down
Loading
Loading