Skip to content

Commit b52271c

Browse files
authored
Merge pull request #391 from janfh/fix/rpg_ds_names
RPG symbol name using name or label. Remove non-alphanum chars
2 parents 8b83b2e + a121713 commit b52271c

File tree

6 files changed

+96
-6
lines changed

6 files changed

+96
-6
lines changed

package-lock.json

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

package.json

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,26 @@
135135
}
136136
}
137137
},
138+
{
139+
"id": "vscode-db2i.codegen",
140+
"title": "Code generation",
141+
"properties": {
142+
"vscode-db2i.codegen.rpgSymbolicNameSource": {
143+
"type": "string",
144+
"order": 0,
145+
"description": "Descriptor to use for RPG symbolic names in data structure",
146+
"default": "Name",
147+
"enum": [
148+
"Name",
149+
"Label"
150+
],
151+
"enumDescriptions": [
152+
"Use the column name",
153+
"Use the column label\n'Extended metadata' must be set to true in the JDBC configuration"
154+
]
155+
}
156+
}
157+
},
138158
{
139159
"id": "vscode-db2i.visualExplain",
140160
"title": "Visual Explain",

src/views/results/codegen.test.ts

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,35 @@
11
import { assert, expect, test } from 'vitest'
2-
import { columnToRpgDefinition, queryResultToRpgDs } from './codegen';
2+
import { columnToRpgDefinition, columnToRpgFieldName, queryResultToRpgDs } from './codegen';
33
import { QueryResult } from '@ibm/mapepire-js';
44

5+
test('Column to RPG symbol', () => {
6+
let name;
7+
8+
name = columnToRpgFieldName({display_size: 0, label: 'änderungs- benutzer ', name: 'ANDBEN', type: 'CHAR', precision: 10, scale: 0}, 'Label');
9+
expect(name).toBe('anderungs_benutzer');
10+
11+
name = columnToRpgFieldName({display_size: 0, label: 'änderungs- benutzer ', name: 'ANDBEN', type: 'CHAR', precision: 10, scale: 0}, 'Name');
12+
expect(name).toBe('andben');
13+
14+
name = columnToRpgFieldName({display_size: 0, label: 'Cust.number....:', name: 'CUSNUM', type: 'CHAR', precision: 10, scale: 0}, 'Label');
15+
expect(name).toBe('cust_number');
16+
17+
name = columnToRpgFieldName({display_size: 0, label: 'Cust. name.... : ', name: 'CUSNAM', type: 'CHAR', precision: 10, scale: 0}, 'Label');
18+
expect(name).toBe('cust_name');
19+
20+
name = columnToRpgFieldName({display_size: 0, label: 'Country:', name: 'C1', type: 'CHAR', precision: 10, scale: 0}, 'Label');
21+
expect(name).toBe('country');
22+
23+
name = columnToRpgFieldName({display_size: 0, label: 'På bærtur', name: 'PB1', type: 'CHAR', precision: 10, scale: 0}, 'Label');
24+
expect(name).toBe('paa_baertur');
25+
26+
name = columnToRpgFieldName({display_size: 0, label: 'öäß', name: 'ABCD', type: 'CHAR', precision: 10, scale: 0}, 'Label');
27+
expect(name).toBe('oas');
28+
29+
name = columnToRpgFieldName({display_size: 0, label: '', name: '0001', type: 'INTEGER', precision: 0, scale: 0}, 'Name');
30+
expect(name).toBe('col0001');
31+
});
32+
533
test('Column to RPG definition', () => {
634
let rpgdef;
735

src/views/results/codegen.ts

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,36 @@
11
import { ColumnMetaData, QueryResult } from "@ibm/mapepire-js";
22

3-
export function queryResultToRpgDs(result: QueryResult<any>) : string {
3+
export function queryResultToRpgDs(result: QueryResult<any>, source: string = 'Name') : string {
44
let content = `dcl-ds row_t qualified template;\n`;
55
for (let i = 0; i < result.metadata.column_count; i++) {
6-
const name = `${isNaN(+result.metadata.columns[i].label.charAt(0)) ? '' : 'col'}${result.metadata.columns[i].label.toLowerCase()}`
6+
const name = columnToRpgFieldName(result.metadata.columns[i], source);
77
content += ` ${name} ${columnToRpgDefinition(result.metadata.columns[i])};\n`;
88
}
99
content += `end-ds;\n`;
1010
return content;
1111
}
1212

13+
export function columnToRpgFieldName(column: ColumnMetaData, source: string = 'Name') : string {
14+
let name = source === 'Label' ? column.label.toLowerCase().trim() : column.name.toLowerCase().trim();
15+
name = name.replace(/\u00fc/g, "u") // ü -> u
16+
.replace(/\u00e4/g, "a") // ä -> a
17+
.replace(/\u00f6/g, "o") // ö -> o
18+
.replace(/\u00df/g, "s") // sharp s/Eszett -> s
19+
.replace(/\u00e6/g, "ae") // æ -> ae
20+
.replace(/\u00f8/g, "oe") // ø -> oe
21+
.replace(/\u00e5/g, "aa") // å -> aa
22+
.replace(/[ .:]+$/g, "") // remove trailing space, "." and ":"
23+
.replace(/[.]/g, "_") // "." between words to underscore
24+
.replace(/\s+/g, "_") // remaining whitespaces to underscore
25+
.replace(/[^a-zA-Z0-9_]/g, "") // remove non-alphanumeric chars
26+
.replace(/\_+/i, "_") // replace multiple underscores with single underscore
27+
.trim();
28+
if (!isNaN(+name.charAt(0))) {
29+
name = `col` + name;
30+
}
31+
return name;
32+
}
33+
1334
export function columnToRpgDefinition(column: ColumnMetaData) : string {
1435
switch (column.type) {
1536
case `NUMERIC`:

src/views/results/contributes.json

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,26 @@
2525
"default": false
2626
}
2727
}
28+
},
29+
{
30+
"id": "vscode-db2i.codegen",
31+
"title": "Code generation",
32+
"properties": {
33+
"vscode-db2i.codegen.rpgSymbolicNameSource": {
34+
"type": "string",
35+
"order": 0,
36+
"description": "Descriptor to use for RPG symbolic names in data structure",
37+
"default": "Name",
38+
"enum": [
39+
"Name",
40+
"Label"
41+
],
42+
"enumDescriptions": [
43+
"Use the column name",
44+
"Use the column label\n'Extended metadata' must be set to true in the JDBC configuration"
45+
]
46+
}
47+
}
2848
}
2949
],
3050
"views": {

src/views/results/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import { updateStatusBar } from "../jobManager/statusBar";
1818
import { DbCache } from "../../language/providers/logic/cache";
1919
import { ExplainType } from "../../connection/types";
2020
import { queryResultToRpgDs } from "./codegen";
21+
import Configuration from "../../configuration";
2122

2223
export type StatementQualifier = "statement" | "update" | "explain" | "onlyexplain" | "json" | "csv" | "cl" | "sql" | "rpg";
2324

@@ -390,7 +391,7 @@ async function runHandler(options?: StatementInfo) {
390391
let content = `**free\n\n`
391392
+ `// statement: ${statementDetail.content}\n\n`
392393
+ `// Row data structure\n`
393-
+ queryResultToRpgDs(result);
394+
+ queryResultToRpgDs(result, Configuration.get(`codegen.rpgSymbolicNameSource`));
394395
const textDoc = await vscode.workspace.openTextDocument({ language: 'rpgle', content });
395396
await vscode.window.showTextDocument(textDoc);
396397
chosenView.setLoadingText(`RPG data structure generated.`, false);

0 commit comments

Comments
 (0)