Skip to content

feat(glue-alpha): opaque Schema Type with Schema.custom, and stronger StorageParameter types - #38592

Open
otaviomacedo wants to merge 4 commits into
mainfrom
otaviom/glue/tables-internals
Open

feat(glue-alpha): opaque Schema Type with Schema.custom, and stronger StorageParameter types#38592
otaviomacedo wants to merge 4 commits into
mainfrom
otaviom/glue/tables-internals

Conversation

@otaviomacedo

Copy link
Copy Markdown
Contributor

Table schema Type was an open public interface, so a column type could be hand-built as { isPrimitive, inputString } — an uncontrolled escape hatch that bypassed the Schema factories entirely, with no sanctioned way to express a custom type. Type is now an opaque class produced only by Schema factories, and Schema.custom(inputString, isPrimitive?) is the explicit escape hatch for types the factories don't model. Schema.decimal now validates precision (1-38) and scale (0..precision), matching the bounds char/varchar already enforce.

StorageParameter weak primitives are tightened: custom(key, value) takes a string value instead of any, and writeKmsKeyId takes a kms.IKey instead of a raw key-id string (rendering key.keyId).

BREAKING CHANGE: schema Type is now an opaque class; construct column types via the Schema factories or Schema.custom(...) rather than { isPrimitive, inputString } literals. StorageParameter.custom(key, value) requires a string value, and StorageParameter.writeKmsKeyId takes a kms.IKey instead of a string.


By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license

… StorageParameter types

Table schema `Type` was an open public interface, so a column type could be
hand-built as `{ isPrimitive, inputString }` — an uncontrolled escape hatch that
bypassed the `Schema` factories entirely, with no sanctioned way to express a
custom type. `Type` is now an opaque class produced only by `Schema` factories,
and `Schema.custom(inputString, isPrimitive?)` is the explicit escape hatch for
types the factories don't model. `Schema.decimal` now validates precision (1-38)
and scale (0..precision), matching the bounds `char`/`varchar` already enforce.

`StorageParameter` weak primitives are tightened: `custom(key, value)` takes a
`string` value instead of `any`, and `writeKmsKeyId` takes a `kms.IKey` instead of
a raw key-id string (rendering `key.keyId`).

Addresses the Type/Schema.custom, Schema.decimal-bounds, and
StorageParameter-weak-primitives findings from the aws-glue-alpha pre-GA API
review. (The overlapping `StorageParameters`-enum-vs-factory dedup is deferred —
it is entangled with the deprecated-`Table` deletion still in flight.)

BREAKING CHANGE: schema `Type` is now an opaque class; construct column types via
the `Schema` factories or `Schema.custom(...)` rather than `{ isPrimitive,
inputString }` literals. `StorageParameter.custom(key, value)` requires a `string`
value, and `StorageParameter.writeKmsKeyId` takes a `kms.IKey` instead of a string.
@github-actions github-actions Bot added the p2 label Aug 18, 2026
@aws-cdk-automation
aws-cdk-automation requested a review from a team August 18, 2026 08:58
@mergify mergify Bot added the contribution/core This is a PR that came from AWS. label Aug 18, 2026
@mergify
mergify Bot deployed to automation August 18, 2026 08:59 Active
@mergify
mergify Bot deployed to automation August 18, 2026 08:59 Active
@github-actions

Copy link
Copy Markdown
Contributor

⚠️ This pull request description does not follow the correct template structure.

PRs without a linked issue will receive lower priority for review and merging. Please update the description to follow the PR template and include a line like Closes #123 in the Issue section. If no existing issue matches your change, create one first.

@aws-cdk-automation aws-cdk-automation left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(This review is outdated)

@otaviomacedo otaviomacedo added the pr-linter/exempt-integ-test The PR linter will not require integ test changes label Aug 18, 2026
@aws-cdk-automation
aws-cdk-automation dismissed their stale review August 18, 2026 09:01

✅ Updated pull request passes all PRLinter validations. Dismissing previous PRLinter review.

@aws-cdk-automation aws-cdk-automation added the pr/needs-maintainer-review This PR needs a review from a Core Team Member label Aug 18, 2026
@gudipati gudipati self-assigned this Aug 20, 2026
Comment on lines +114 to +119
if (precision < 1 || precision > 38 || precision % 1 !== 0) {
throw new UnscopedValidationError(lit`DecimalPrecisionOutOfRange`, `decimal precision must be a positive integer between 1 and 38, got ${precision}`);
}
if (scale !== undefined && (scale < 0 || scale > 38 || scale % 1 !== 0)) {
throw new UnscopedValidationError(lit`DecimalScaleOutOfRange`, `decimal scale must be an integer between 0 and 38, got ${scale}`);
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do these need any token resolution check (Token.isUnresolved) ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, done.

public static writeKmsKeyId(value: string): StorageParameter {
return new StorageParameter('write.kms.key.id', value);
public static writeKmsKeyId(key: kms.IKeyRef): StorageParameter {
return new StorageParameter('write.kms.key.id', key.keyRef.keyId);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can keyArn be used here instead of keyId ?
keyId drops the account and breaks cross-account imported keys -keyArn works for both same and cross-account

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Were you able to verify this works while deploying to CFN ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes

*
* @param inputString the Glue input string for the type (for example `interval_day_to_second`).
* @param isPrimitive whether the type is a primitive (non-nested) data type.
* @default isPrimitive - true

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: I think @default is not needed here - You can mention the default behaviour on @param itself -

* @param isPrimitive whether the type is a primitive (non-nested) data type. Defaults to true.


test('decimal rejects scale greater than 38', () => {
expect(() => Schema.decimal(38, 39)).toThrow(/decimal scale must be an integer between 0 and 38/);
});

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: should we add a test for non-integer precision/scale ?

test('decimal rejects non-integer precision or scale', () => {
  expect(() => Schema.decimal(5.5)).toThrow(/.../);
  expect(() => Schema.decimal(10, 2.5)).toThrow(/.../);
});

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, good point.

isPrimitive: true,
inputString: scale !== undefined ? `decimal(${precision},${scale})` : `decimal(${precision})`,
};
if (Token.isResolved(precision) && Token.isResolved(scale)) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if scale is not provided and precision is not a token, then precision check will not be validated.

I think you will need to do the following instead -

      if (Token.isResolved(precision) && (precision < 1 || precision > 38 || precision % 1 !== 0)) {
        throw new UnscopedValidationError(lit`DecimalPrecisionOutOfRange`, `decimal precision must be a positive integer between 1 and 38, got ${precision}`);
      }
      if (scale !== undefined && Token.isResolved(scale) && (scale < 0 || scale > 38 || scale % 1 !== 0)) {
        throw new UnscopedValidationError(lit`DecimalScaleOutOfRange`, `decimal scale must be an integer between 0 and 38, got ${scale}`);
      }

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True. Done.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

contribution/core This is a PR that came from AWS. p2 pr/needs-maintainer-review This PR needs a review from a Core Team Member pr-linter/exempt-integ-test The PR linter will not require integ test changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants