Skip to content

Commit 412f175

Browse files
dhasani23David Hasani
andauthored
feat(amazonq): support SQL conversions (#5775)
## Problem QCT wants to support converting embedded SQL in Java apps. ## Solution Allow users to start a transformation for SQL conversions. --- <!--- REMINDER: Ensure that your PR meets the guidelines in CONTRIBUTING.md --> License: I confirm that my contribution is made under the terms of the Apache 2.0 license. --------- Co-authored-by: David Hasani <[email protected]>
1 parent d660430 commit 412f175

File tree

21 files changed

+868
-243
lines changed

21 files changed

+868
-243
lines changed

package-lock.json

Lines changed: 4 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
"generateNonCodeFiles": "npm run generateNonCodeFiles -w packages/ --if-present"
4040
},
4141
"devDependencies": {
42-
"@aws-toolkits/telemetry": "^1.0.272",
42+
"@aws-toolkits/telemetry": "^1.0.274",
4343
"@playwright/browser-chromium": "^1.43.1",
4444
"@types/he": "^1.2.3",
4545
"@types/vscode": "^1.68.0",

packages/core/src/amazonq/webview/ui/quickActions/generator.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ export class QuickActionGenerator {
4040
? [
4141
{
4242
command: '/transform',
43-
description: 'Transform your Java 8 or 11 Maven project to Java 17',
43+
description: 'Transform your Java project',
4444
},
4545
]
4646
: []),

packages/core/src/amazonq/webview/ui/tabs/constants.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
33
* SPDX-License-Identifier: Apache-2.0
44
*/
5+
import { isSQLTransformReady } from '../../../../dev/config'
56
import { TabType } from '../storages/tabsStorage'
67

78
export type TabTypeData = {
@@ -33,7 +34,15 @@ What would you like to work on?`,
3334
gumby: {
3435
title: 'Q - Code Transformation',
3536
placeholder: 'Open a new tab to chat with Q',
36-
welcome: `Welcome to Code Transformation!
37+
welcome: isSQLTransformReady
38+
? `Welcome to code transformation!
39+
40+
I can help you with the following tasks:
41+
- Upgrade your Java 8 and Java 11 codebases to Java 17
42+
- Convert embedded SQL from Oracle databases to PostgreSQL
43+
44+
What would you like to do? You can enter 'language upgrade' or 'SQL conversion'.`
45+
: `Welcome to code transformation!
3746
3847
I can help you upgrade your Java 8 and 11 codebases to Java 17.`,
3948
},

packages/core/src/amazonqGumby/app.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,4 +71,5 @@ export function init(appContext: AmazonQAppInitContext) {
7171
showTransformationHub.register()
7272

7373
transformByQState.setChatControllers(gumbyChatControllerEventEmitters)
74+
transformByQState.setChatMessenger(messenger)
7475
}

packages/core/src/amazonqGumby/chat/controller/controller.ts

Lines changed: 215 additions & 80 deletions
Large diffs are not rendered by default.

packages/core/src/amazonqGumby/chat/controller/messenger/messenger.ts

Lines changed: 146 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ export type StaticTextResponseType =
3535
| 'start-transformation-confirmed'
3636
| 'job-transmitted'
3737
| 'end-HIL-early'
38+
| 'choose-transformation-objective'
39+
| 'language-upgrade-selected'
40+
| 'sql-conversion-selected'
3841

3942
export type UnrecoverableErrorType =
4043
| 'no-project-found'
@@ -45,6 +48,10 @@ export type UnrecoverableErrorType =
4548
| 'unsupported-source-jdk-version'
4649
| 'upload-to-s3-failed'
4750
| 'job-start-failed'
51+
| 'unsupported-source-db'
52+
| 'unsupported-target-db'
53+
| 'error-parsing-sct-file'
54+
| 'invalid-zip-no-sct-file'
4855

4956
export enum GumbyNamedMessages {
5057
COMPILATION_PROGRESS_MESSAGE = 'gumbyProjectCompilationMessage',
@@ -148,7 +155,7 @@ export class Messenger {
148155
)
149156
}
150157

151-
public async sendProjectPrompt(projects: TransformationCandidateProject[], tabID: string) {
158+
public async sendLanguageUpgradeProjectPrompt(projects: TransformationCandidateProject[], tabID: string) {
152159
const projectFormOptions: { value: any; label: string }[] = []
153160
const detectedJavaVersions = new Array<JDKVersion | undefined>()
154161

@@ -162,7 +169,7 @@ export class Messenger {
162169

163170
const formItems: ChatItemFormItem[] = []
164171
formItems.push({
165-
id: 'GumbyTransformProjectForm',
172+
id: 'GumbyTransformLanguageUpgradeProjectForm',
166173
type: 'select',
167174
title: CodeWhispererConstants.chooseProjectFormTitle,
168175
mandatory: true,
@@ -178,11 +185,11 @@ export class Messenger {
178185
options: [
179186
{
180187
value: JDKVersion.JDK8,
181-
label: JDKVersion.JDK8.toString(),
188+
label: JDKVersion.JDK8,
182189
},
183190
{
184191
value: JDKVersion.JDK11,
185-
label: JDKVersion.JDK11.toString(),
192+
label: JDKVersion.JDK11,
186193
},
187194
{
188195
value: JDKVersion.UNSUPPORTED,
@@ -207,7 +214,7 @@ export class Messenger {
207214
this.dispatcher.sendAsyncEventProgress(
208215
new AsyncEventProgressMessage(tabID, {
209216
inProgress: true,
210-
message: MessengerUtils.createTransformationConfirmationPrompt(detectedJavaVersions),
217+
message: MessengerUtils.createLanguageUpgradeConfirmationPrompt(detectedJavaVersions),
211218
})
212219
)
213220

@@ -224,7 +231,64 @@ export class Messenger {
224231
message: 'Q Code Transformation',
225232
formItems: formItems,
226233
},
227-
'TransformForm',
234+
'LanguageUpgradeTransformForm',
235+
tabID,
236+
false
237+
)
238+
)
239+
}
240+
241+
public async sendSQLConversionProjectPrompt(projects: TransformationCandidateProject[], tabID: string) {
242+
const projectFormOptions: { value: any; label: string }[] = []
243+
244+
projects.forEach((candidateProject) => {
245+
projectFormOptions.push({
246+
value: candidateProject.path,
247+
label: candidateProject.name,
248+
})
249+
})
250+
251+
const formItems: ChatItemFormItem[] = []
252+
formItems.push({
253+
id: 'GumbyTransformSQLConversionProjectForm',
254+
type: 'select',
255+
title: 'Choose a project to transform',
256+
mandatory: true,
257+
options: projectFormOptions,
258+
})
259+
260+
formItems.push({
261+
id: 'GumbyTransformSQLSchemaForm',
262+
type: 'select',
263+
title: 'Choose the schema of the database',
264+
mandatory: true,
265+
options: Array.from(transformByQState.getSchemaOptions()).map((schema) => ({
266+
value: schema,
267+
label: schema,
268+
})),
269+
})
270+
271+
this.dispatcher.sendAsyncEventProgress(
272+
new AsyncEventProgressMessage(tabID, {
273+
inProgress: true,
274+
message: 'I can convert your embedded SQL, but I need some more info from you first.',
275+
})
276+
)
277+
278+
this.dispatcher.sendAsyncEventProgress(
279+
new AsyncEventProgressMessage(tabID, {
280+
inProgress: false,
281+
message: undefined,
282+
})
283+
)
284+
285+
this.dispatcher.sendChatPrompt(
286+
new ChatPrompt(
287+
{
288+
message: 'Q Code Transformation',
289+
formItems: formItems,
290+
},
291+
'SQLConversionTransformForm',
228292
tabID,
229293
false
230294
)
@@ -315,15 +379,18 @@ export class Messenger {
315379
)
316380
}
317381

318-
public sendStaticTextResponse(type: StaticTextResponseType, tabID: string) {
382+
public sendStaticTextResponse(messageType: StaticTextResponseType, tabID: string) {
319383
let message = '...'
320384

321-
switch (type) {
385+
switch (messageType) {
322386
case 'java-home-not-set':
323387
message = MessengerUtils.createJavaHomePrompt()
324388
break
325389
case 'end-HIL-early':
326-
message = `I will continue transforming your code without upgrading this dependency.`
390+
message = 'I will continue transforming your code without upgrading this dependency.'
391+
break
392+
case 'choose-transformation-objective':
393+
message = 'Choose your transformation objective.'
327394
break
328395
}
329396

@@ -366,6 +433,18 @@ export class Messenger {
366433
case 'unsupported-source-jdk-version':
367434
message = CodeWhispererConstants.unsupportedJavaVersionChatMessage
368435
break
436+
case 'unsupported-source-db':
437+
message = CodeWhispererConstants.invalidMetadataFileUnsupportedSourceDB
438+
break
439+
case 'unsupported-target-db':
440+
message = CodeWhispererConstants.invalidMetadataFileUnsupportedTargetDB
441+
break
442+
case 'error-parsing-sct-file':
443+
message = CodeWhispererConstants.invalidMetadataFileErrorParsing
444+
break
445+
case 'invalid-zip-no-sct-file':
446+
message = CodeWhispererConstants.invalidMetadataFileNoSctFile
447+
break
369448
}
370449

371450
const buttons: ChatItemButton[] = []
@@ -442,7 +521,7 @@ export class Messenger {
442521
)
443522
}
444523

445-
public sendProjectSelectionMessage(
524+
public sendLanguageUpgradeProjectChoiceMessage(
446525
projectName: string,
447526
fromJDKVersion: JDKVersion,
448527
toJDKVersion: JDKVersion,
@@ -460,6 +539,35 @@ export class Messenger {
460539
this.dispatcher.sendChatMessage(new ChatMessage({ message, messageType: 'prompt' }, tabID))
461540
}
462541

542+
public sendSQLConversionProjectSelectionMessage(projectName: string, schema: string, tabID: string) {
543+
const message = `### Transformation details
544+
-------------
545+
| | |
546+
| :------------------- | -------: |
547+
| **Project** | ${projectName} |
548+
| **Schema** | ${schema} |
549+
`
550+
this.dispatcher.sendChatMessage(new ChatMessage({ message, messageType: 'prompt' }, tabID))
551+
}
552+
553+
public sendSQLConversionMetadataReceivedMessage(tabID: any) {
554+
const message = `### Transformation details
555+
-------------
556+
| | |
557+
| :------------------- | -------: |
558+
| **Source DB** | ${transformByQState.getSourceDB()} |
559+
| **Target DB** | ${transformByQState.getTargetDB()} |
560+
| **Host** | ${transformByQState.getSourceServerName()} |
561+
`
562+
this.dispatcher.sendChatMessage(
563+
new ChatMessage(
564+
{ message: CodeWhispererConstants.sqlMetadataFileReceived, messageType: 'ai-prompt' },
565+
tabID
566+
)
567+
)
568+
this.dispatcher.sendChatMessage(new ChatMessage({ message, messageType: 'ai-prompt' }, tabID))
569+
}
570+
463571
public sendSkipTestsSelectionMessage(skipTestsSelection: string, tabID: string) {
464572
const message = `Okay, I will ${skipTestsSelection.toLowerCase()} when building your project.`
465573
this.dispatcher.sendChatMessage(new ChatMessage({ message, messageType: 'ai-prompt' }, tabID))
@@ -612,4 +720,32 @@ ${codeSnippet}
612720
)
613721
)
614722
}
723+
724+
public async sendSelectSQLMetadataFileMessage(tabID: string) {
725+
const message = CodeWhispererConstants.selectSQLMetadataFileHelpMessage
726+
const buttons: ChatItemButton[] = []
727+
728+
buttons.push({
729+
keepCardAfterClick: true,
730+
text: 'Select metadata file',
731+
id: ButtonActions.SELECT_SQL_CONVERSION_METADATA_FILE,
732+
})
733+
734+
buttons.push({
735+
keepCardAfterClick: false,
736+
text: 'Cancel',
737+
id: ButtonActions.CANCEL_TRANSFORMATION_FORM,
738+
})
739+
740+
this.dispatcher.sendChatMessage(
741+
new ChatMessage(
742+
{
743+
message,
744+
messageType: 'ai-prompt',
745+
buttons,
746+
},
747+
tabID
748+
)
749+
)
750+
}
615751
}

packages/core/src/amazonqGumby/chat/controller/messenger/messengerUtils.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,12 @@ import DependencyVersions from '../../../models/dependencies'
1313
export enum ButtonActions {
1414
STOP_TRANSFORMATION_JOB = 'gumbyStopTransformationJob',
1515
VIEW_TRANSFORMATION_HUB = 'gumbyViewTransformationHub',
16-
CONFIRM_TRANSFORMATION_FORM = 'gumbyTransformFormConfirm',
16+
CONFIRM_LANGUAGE_UPGRADE_TRANSFORMATION_FORM = 'gumbyLanguageUpgradeTransformFormConfirm',
17+
CONFIRM_SQL_CONVERSION_TRANSFORMATION_FORM = 'gumbySQLConversionTransformFormConfirm',
18+
CANCEL_TRANSFORMATION_FORM = 'gumbyTransformFormCancel', // shared between Language Upgrade & SQL Conversion
1719
CONFIRM_SKIP_TESTS_FORM = 'gumbyTransformSkipTestsFormConfirm',
18-
CANCEL_TRANSFORMATION_FORM = 'gumbyTransformFormCancel',
1920
CANCEL_SKIP_TESTS_FORM = 'gumbyTransformSkipTestsFormCancel',
21+
SELECT_SQL_CONVERSION_METADATA_FILE = 'gumbySQLConversionMetadataTransformFormConfirm',
2022
CONFIRM_DEPENDENCY_FORM = 'gumbyTransformDependencyFormConfirm',
2123
CANCEL_DEPENDENCY_FORM = 'gumbyTransformDependencyFormCancel',
2224
CONFIRM_JAVA_HOME_FORM = 'gumbyJavaHomeFormConfirm',
@@ -63,7 +65,7 @@ export default class MessengerUtils {
6365
}
6466
}
6567

66-
static createTransformationConfirmationPrompt = (detectedJavaVersions: Array<JDKVersion | undefined>): string => {
68+
static createLanguageUpgradeConfirmationPrompt = (detectedJavaVersions: Array<JDKVersion | undefined>): string => {
6769
let javaVersionString = 'Java project'
6870
const uniqueJavaOptions = new Set(detectedJavaVersions)
6971

packages/core/src/amazonqGumby/chat/session/session.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ export enum ConversationState {
1010
PROMPT_JAVA_HOME,
1111
COMPILING,
1212
JOB_SUBMITTED,
13-
WAITING_FOR_INPUT,
13+
WAITING_FOR_HIL_INPUT,
14+
WAITING_FOR_TRANSFORMATION_OBJECTIVE,
1415
}
1516

1617
export interface ProjectDetails {

packages/core/src/amazonqGumby/chat/views/connector/connector.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,8 @@ export class ChatPrompt extends UiMessage {
117117
keepCardAfterClick: false,
118118
waitMandatoryFormItems: false,
119119
text: 'Cancel',
120-
id: `gumby${promptIDPrefix}Cancel`,
120+
// makes the Cancel button shared in all forms, which is fine since we respond the same exact way each time
121+
id: 'gumbyTransformFormCancel',
121122
})
122123
}
123124
}

0 commit comments

Comments
 (0)