Skip to content

Commit

Permalink
fix(redshift): adding distKey to an existing table fails deployment (#…
Browse files Browse the repository at this point in the history
…26789)

The current implementation executes a `CREATE TABLE` if the table has no `distKey` specified and one is added, or if a `distKey` is present and is removed.
The resulting table is created with the same name, causing the update operation to fail.
This fixes the problem by using [`ALTER TABLE`](https://docs.aws.amazon.com/redshift/latest/dg/r_ALTER_TABLE.html) when adding/removing `distKey` on a table update. 

Closes #26733.

----

*By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
  • Loading branch information
lpizzinidev committed Aug 17, 2023
1 parent ecb34bb commit 8c9f0e2
Show file tree
Hide file tree
Showing 26 changed files with 6,264 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -164,9 +164,14 @@ async function updateTable(

const oldDistKey = getDistKeyColumn(oldTableColumns)?.name;
const newDistKey = getDistKeyColumn(tableColumns)?.name;
if ((!oldDistKey && newDistKey ) || (oldDistKey && !newDistKey)) {
return createTable(tableNamePrefix, tableNameSuffix, tableColumns, tableAndClusterProps);
if (!oldDistKey && newDistKey) {
// Table has no existing distribution key, add a new one
alterationStatements.push(`ALTER TABLE ${tableName} ALTER DISTSTYLE KEY DISTKEY ${newDistKey}`);
} else if (oldDistKey && !newDistKey) {
// Table has a distribution key, remove and set to AUTO
alterationStatements.push(`ALTER TABLE ${tableName} ALTER DISTSTYLE AUTO`);
} else if (oldDistKey !== newDistKey) {
// Table has an existing distribution key, change it
alterationStatements.push(`ALTER TABLE ${tableName} ALTER DISTKEY ${newDistKey}`);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -384,21 +384,21 @@ describe('update', () => {
}));
});

test('replaces if distKey is added', async () => {
test('adds key without creating table if distKey is added', async () => {
const newResourceProperties: ResourcePropertiesType = {
...resourceProperties,
tableColumns: [{ name: 'col1', dataType: 'varchar(1)', distKey: true }],
};

await expect(manageTable(newResourceProperties, event)).resolves.not.toMatchObject({
await expect(manageTable(newResourceProperties, event)).resolves.toMatchObject({
PhysicalResourceId: physicalResourceId,
});
expect(mockExecuteStatement).toHaveBeenCalledWith(expect.objectContaining({
Sql: `CREATE TABLE ${tableNamePrefix}${requestIdTruncated} (col1 varchar(1)) DISTKEY(col1)`,
Sql: `ALTER TABLE ${physicalResourceId} ALTER DISTSTYLE KEY DISTKEY col1`,
}));
});

test('replaces if distKey is removed', async () => {
test('removes key without replacing table if distKey is removed', async () => {
const newEvent: AWSLambda.CloudFormationCustomResourceEvent = {
...event,
OldResourceProperties: {
Expand All @@ -410,11 +410,11 @@ describe('update', () => {
...resourceProperties,
};

await expect(manageTable(newResourceProperties, newEvent)).resolves.not.toMatchObject({
await expect(manageTable(newResourceProperties, newEvent)).resolves.toMatchObject({
PhysicalResourceId: physicalResourceId,
});
expect(mockExecuteStatement).toHaveBeenCalledWith(expect.objectContaining({
Sql: `CREATE TABLE ${tableNamePrefix}${requestIdTruncated} (col1 varchar(1))`,
Sql: `ALTER TABLE ${physicalResourceId} ALTER DISTSTYLE AUTO`,
}));
});

Expand Down

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

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

Loading

0 comments on commit 8c9f0e2

Please sign in to comment.