@abaplint/transpiler 2.7.88 → 2.7.90
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/build/src/db/database_setup_result.d.ts +1 -0
- package/build/src/db/index.d.ts +1 -0
- package/build/src/db/index.js +28 -8
- package/build/src/db/schema_generation/database_schema_generator.d.ts +5 -0
- package/build/src/db/schema_generation/database_schema_generator.js +3 -0
- package/build/src/db/schema_generation/pg_database_schema.d.ts +9 -0
- package/build/src/db/{pg_database_schema.js → schema_generation/pg_database_schema.js} +0 -20
- package/build/src/db/schema_generation/snowflake_database_schema.d.ts +9 -0
- package/build/src/db/schema_generation/snowflake_database_schema.js +102 -0
- package/build/src/db/schema_generation/sqlite_database_schema.d.ts +9 -0
- package/build/src/db/{sqlite_database_schema.js → schema_generation/sqlite_database_schema.js} +0 -19
- package/build/src/expressions/sql_field_name.js +7 -2
- package/package.json +1 -1
- package/build/src/db/pg_database_schema.d.ts +0 -9
- package/build/src/db/sqlite_database_schema.d.ts +0 -9
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2020 Lars Hvam Petersen
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/build/src/db/index.d.ts
CHANGED
package/build/src/db/index.js
CHANGED
|
@@ -3,8 +3,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.DatabaseSetup = void 0;
|
|
4
4
|
/* eslint-disable max-len */
|
|
5
5
|
const abaplint = require("@abaplint/core");
|
|
6
|
-
const sqlite_database_schema_1 = require("./sqlite_database_schema");
|
|
7
|
-
const pg_database_schema_1 = require("./pg_database_schema");
|
|
6
|
+
const sqlite_database_schema_1 = require("./schema_generation/sqlite_database_schema");
|
|
7
|
+
const pg_database_schema_1 = require("./schema_generation/pg_database_schema");
|
|
8
|
+
const snowflake_database_schema_1 = require("./schema_generation/snowflake_database_schema");
|
|
8
9
|
/////////////////////////
|
|
9
10
|
// NOTES
|
|
10
11
|
/////////////////////////
|
|
@@ -17,21 +18,40 @@ class DatabaseSetup {
|
|
|
17
18
|
run(options) {
|
|
18
19
|
return {
|
|
19
20
|
schemas: {
|
|
20
|
-
sqlite: new sqlite_database_schema_1.SQLiteDatabaseSchema(this.reg)
|
|
21
|
+
sqlite: this.driver(new sqlite_database_schema_1.SQLiteDatabaseSchema(this.reg)),
|
|
21
22
|
hdb: ["todo"],
|
|
22
|
-
pg: new pg_database_schema_1.PGDatabaseSchema(this.reg)
|
|
23
|
+
pg: this.driver(new pg_database_schema_1.PGDatabaseSchema(this.reg)),
|
|
24
|
+
snowflake: this.driver(new snowflake_database_schema_1.SnowflakeDatabaseSchema(this.reg)),
|
|
23
25
|
},
|
|
24
26
|
insert: this.buildInsert(options),
|
|
25
27
|
};
|
|
26
28
|
}
|
|
27
29
|
////////////////////
|
|
30
|
+
driver(schemaGenerator) {
|
|
31
|
+
const statements = [];
|
|
32
|
+
// CREATE TABLEs
|
|
33
|
+
for (const obj of this.reg.getObjects()) {
|
|
34
|
+
if (obj instanceof abaplint.Objects.Table
|
|
35
|
+
&& obj.getTableCategory() === abaplint.Objects.TableCategory.Transparent) {
|
|
36
|
+
statements.push(schemaGenerator.buildTABL(obj).trim());
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
// CREATE VIEWs after TABLEs
|
|
40
|
+
// todo: what if the view is based on another view?
|
|
41
|
+
for (const obj of this.reg.getObjects()) {
|
|
42
|
+
if (obj instanceof abaplint.Objects.View) {
|
|
43
|
+
statements.push(schemaGenerator.buildVIEW(obj).trim());
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return statements;
|
|
47
|
+
}
|
|
28
48
|
buildInsert(options) {
|
|
29
49
|
// note: avoid hitting maximum statement size by splitting into multiple statements
|
|
30
50
|
const insert = [];
|
|
31
51
|
// INSERT data
|
|
32
52
|
for (const obj of this.reg.getObjects()) {
|
|
33
53
|
if (obj instanceof abaplint.Objects.MessageClass) {
|
|
34
|
-
insert.push(this.insertT100(obj));
|
|
54
|
+
insert.push(...this.insertT100(obj));
|
|
35
55
|
}
|
|
36
56
|
else if (obj instanceof abaplint.Objects.Class
|
|
37
57
|
|| obj instanceof abaplint.Objects.Interface) {
|
|
@@ -73,11 +93,11 @@ class DatabaseSetup {
|
|
|
73
93
|
// ignore if T100 is unknown
|
|
74
94
|
const obj = this.reg.getObject("TABL", "T100");
|
|
75
95
|
if (obj === undefined) {
|
|
76
|
-
return
|
|
96
|
+
return [];
|
|
77
97
|
}
|
|
78
|
-
|
|
98
|
+
const ret = [];
|
|
79
99
|
for (const m of msag.getMessages()) {
|
|
80
|
-
ret
|
|
100
|
+
ret.push(`INSERT INTO "t100" ("sprsl", "arbgb", "msgnr", "text") VALUES ('E', '${msag.getName().padEnd(20, " ")}', '${m.getNumber()}', '${this.escape(m.getMessage().padEnd(73, " "))}');`);
|
|
81
101
|
}
|
|
82
102
|
return ret;
|
|
83
103
|
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import * as abaplint from "@abaplint/core";
|
|
2
|
+
import { DatabaseSchemaGenerator } from "./database_schema_generator";
|
|
3
|
+
export declare class PGDatabaseSchema implements DatabaseSchemaGenerator {
|
|
4
|
+
private readonly reg;
|
|
5
|
+
constructor(reg: abaplint.IRegistry);
|
|
6
|
+
buildVIEW(view: abaplint.Objects.View): string;
|
|
7
|
+
buildTABL(tabl: abaplint.Objects.Table): string;
|
|
8
|
+
private toType;
|
|
9
|
+
}
|
|
@@ -6,26 +6,6 @@ class PGDatabaseSchema {
|
|
|
6
6
|
constructor(reg) {
|
|
7
7
|
this.reg = reg;
|
|
8
8
|
}
|
|
9
|
-
run() {
|
|
10
|
-
const statements = [];
|
|
11
|
-
// CREATE TABLEs
|
|
12
|
-
for (const obj of this.reg.getObjects()) {
|
|
13
|
-
if (obj instanceof abaplint.Objects.Table
|
|
14
|
-
&& obj.getTableCategory() === abaplint.Objects.TableCategory.Transparent) {
|
|
15
|
-
statements.push(this.buildTABL(obj).trim());
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
// CREATE VIEWs after TABLEs
|
|
19
|
-
// todo: what if the view is based on another view?
|
|
20
|
-
for (const obj of this.reg.getObjects()) {
|
|
21
|
-
if (obj instanceof abaplint.Objects.View) {
|
|
22
|
-
statements.push(this.buildVIEW(obj).trim());
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
return statements;
|
|
26
|
-
}
|
|
27
|
-
//////////////////
|
|
28
|
-
// https://www.sqlite.org/lang_createview.html
|
|
29
9
|
buildVIEW(view) {
|
|
30
10
|
const fields = view.getFields();
|
|
31
11
|
let firstTabname = "";
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import * as abaplint from "@abaplint/core";
|
|
2
|
+
import { DatabaseSchemaGenerator } from "./database_schema_generator";
|
|
3
|
+
export declare class SnowflakeDatabaseSchema implements DatabaseSchemaGenerator {
|
|
4
|
+
private readonly reg;
|
|
5
|
+
constructor(reg: abaplint.IRegistry);
|
|
6
|
+
buildVIEW(view: abaplint.Objects.View): string;
|
|
7
|
+
buildTABL(tabl: abaplint.Objects.Table): string;
|
|
8
|
+
private toType;
|
|
9
|
+
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SnowflakeDatabaseSchema = void 0;
|
|
4
|
+
const abaplint = require("@abaplint/core");
|
|
5
|
+
class SnowflakeDatabaseSchema {
|
|
6
|
+
constructor(reg) {
|
|
7
|
+
this.reg = reg;
|
|
8
|
+
}
|
|
9
|
+
buildVIEW(view) {
|
|
10
|
+
const fields = view.getFields();
|
|
11
|
+
let firstTabname = "";
|
|
12
|
+
const columns = fields === null || fields === void 0 ? void 0 : fields.map((f) => {
|
|
13
|
+
firstTabname = "'" + f.TABNAME.toLowerCase() + "'";
|
|
14
|
+
return firstTabname + "." + f.FIELDNAME.toLowerCase() + " AS " + f.VIEWFIELD.toLowerCase();
|
|
15
|
+
}).join(", ");
|
|
16
|
+
let from = "";
|
|
17
|
+
let previous = "";
|
|
18
|
+
for (const j of view.getJoin() || []) {
|
|
19
|
+
if (previous === "") {
|
|
20
|
+
from += "'" + j.LTAB.toLowerCase() + "' INNER JOIN '" + j.RTAB.toLowerCase() + "' ON '" + j.LTAB.toLowerCase() + "'." + j.LFIELD.toLowerCase() + " = '" + j.RTAB.toLowerCase() + "'." + j.RFIELD.toLowerCase();
|
|
21
|
+
}
|
|
22
|
+
else if (previous === j.LTAB + "," + j.RTAB) {
|
|
23
|
+
from += " AND '" + j.LTAB.toLowerCase() + "'." + j.LFIELD.toLowerCase() + " = '" + j.RTAB.toLowerCase() + "'." + j.RFIELD.toLowerCase();
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
from += " INNER JOIN '" + j.RTAB.toLowerCase() + "' ON '" + j.LTAB.toLowerCase() + "'." + j.LFIELD.toLowerCase() + " = '" + j.RTAB.toLowerCase() + "'." + j.RFIELD.toLowerCase();
|
|
27
|
+
}
|
|
28
|
+
previous = j.LTAB + "," + j.RTAB;
|
|
29
|
+
}
|
|
30
|
+
from = from.trim();
|
|
31
|
+
if (from === "") {
|
|
32
|
+
from = firstTabname;
|
|
33
|
+
}
|
|
34
|
+
return `CREATE VIEW '${view.getName().toLowerCase()}' AS SELECT ${columns} FROM ${from};\n`;
|
|
35
|
+
}
|
|
36
|
+
buildTABL(tabl) {
|
|
37
|
+
const type = tabl.parseType(this.reg);
|
|
38
|
+
if (!(type instanceof abaplint.BasicTypes.StructureType)) {
|
|
39
|
+
return "";
|
|
40
|
+
}
|
|
41
|
+
const fields = [];
|
|
42
|
+
const fieldsRaw = [];
|
|
43
|
+
for (const field of type.getComponents()) {
|
|
44
|
+
if (field.type instanceof abaplint.BasicTypes.StructureType) {
|
|
45
|
+
// is a GROUP NAME
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
fieldsRaw.push(field.name.toLowerCase());
|
|
49
|
+
fields.push("\"" + field.name.toLowerCase() + "\" " + this.toType(field.type, field.name, tabl.getName()));
|
|
50
|
+
}
|
|
51
|
+
// assumption: all transparent tables have primary keys
|
|
52
|
+
// add single quotes to field names to allow for keywords as field names
|
|
53
|
+
const key = ", PRIMARY KEY(" + tabl.listKeys(this.reg)
|
|
54
|
+
.filter(e => fieldsRaw.includes(e.toLowerCase()))
|
|
55
|
+
.map(e => "\"" + e.toLowerCase() + "\"").join(",") + ")";
|
|
56
|
+
return `CREATE TABLE "${tabl.getName().toLowerCase()}" (${fields.join(", ")}${key});\n`;
|
|
57
|
+
}
|
|
58
|
+
// https://docs.snowflake.com/en/sql-reference/collation
|
|
59
|
+
toType(type, fieldname, errorInfo) {
|
|
60
|
+
if (type instanceof abaplint.BasicTypes.CharacterType) {
|
|
61
|
+
return `NCHAR(${type.getLength()}) COLLATE 'rtrim'`;
|
|
62
|
+
}
|
|
63
|
+
else if (type instanceof abaplint.BasicTypes.TimeType) {
|
|
64
|
+
return `NCHAR(6)`;
|
|
65
|
+
}
|
|
66
|
+
else if (type instanceof abaplint.BasicTypes.DateType) {
|
|
67
|
+
return `NCHAR(8)`;
|
|
68
|
+
}
|
|
69
|
+
else if (type instanceof abaplint.BasicTypes.NumericType) {
|
|
70
|
+
// it will be fine, the runtime representation of numc is also text
|
|
71
|
+
return `NCHAR(${type.getLength()})`;
|
|
72
|
+
}
|
|
73
|
+
else if (type instanceof abaplint.BasicTypes.StringType) {
|
|
74
|
+
return `TEXT`;
|
|
75
|
+
}
|
|
76
|
+
else if (type instanceof abaplint.BasicTypes.XStringType) {
|
|
77
|
+
// it will be fine, the runtime representation of xstring is also text
|
|
78
|
+
return `TEXT`;
|
|
79
|
+
}
|
|
80
|
+
else if (type instanceof abaplint.BasicTypes.HexType) {
|
|
81
|
+
return `NCHAR(${type.getLength() * 2})`;
|
|
82
|
+
}
|
|
83
|
+
else if (type instanceof abaplint.BasicTypes.IntegerType) {
|
|
84
|
+
return `INT`;
|
|
85
|
+
}
|
|
86
|
+
else if (type instanceof abaplint.BasicTypes.FloatType
|
|
87
|
+
|| type instanceof abaplint.BasicTypes.FloatingPointType) {
|
|
88
|
+
return `REAL`;
|
|
89
|
+
}
|
|
90
|
+
else if (type instanceof abaplint.BasicTypes.PackedType) {
|
|
91
|
+
return `DECIMAL(${type.getLength()},${type.getDecimals()})`;
|
|
92
|
+
}
|
|
93
|
+
else if (type instanceof abaplint.BasicTypes.VoidType) {
|
|
94
|
+
throw `Type of ${errorInfo}-${fieldname} is VoidType(${type.getVoided()}), make sure the type is known, enable strict syntax checking`;
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
throw "database_setup: " + errorInfo + "-" + fieldname + ", todo toType handle: " + type.constructor.name;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
exports.SnowflakeDatabaseSchema = SnowflakeDatabaseSchema;
|
|
102
|
+
//# sourceMappingURL=snowflake_database_schema.js.map
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import * as abaplint from "@abaplint/core";
|
|
2
|
+
import { DatabaseSchemaGenerator } from "./database_schema_generator";
|
|
3
|
+
export declare class SQLiteDatabaseSchema implements DatabaseSchemaGenerator {
|
|
4
|
+
private readonly reg;
|
|
5
|
+
constructor(reg: abaplint.IRegistry);
|
|
6
|
+
buildVIEW(view: abaplint.Objects.View): string;
|
|
7
|
+
buildTABL(tabl: abaplint.Objects.Table): string;
|
|
8
|
+
private toType;
|
|
9
|
+
}
|
package/build/src/db/{sqlite_database_schema.js → schema_generation/sqlite_database_schema.js}
RENAMED
|
@@ -6,25 +6,6 @@ class SQLiteDatabaseSchema {
|
|
|
6
6
|
constructor(reg) {
|
|
7
7
|
this.reg = reg;
|
|
8
8
|
}
|
|
9
|
-
run() {
|
|
10
|
-
const statements = [];
|
|
11
|
-
// CREATE TABLEs
|
|
12
|
-
for (const obj of this.reg.getObjects()) {
|
|
13
|
-
if (obj instanceof abaplint.Objects.Table
|
|
14
|
-
&& obj.getTableCategory() === abaplint.Objects.TableCategory.Transparent) {
|
|
15
|
-
statements.push(this.buildTABL(obj).trim());
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
// CREATE VIEWs after TABLEs
|
|
19
|
-
// todo: what if the view is based on another view?
|
|
20
|
-
for (const obj of this.reg.getObjects()) {
|
|
21
|
-
if (obj instanceof abaplint.Objects.View) {
|
|
22
|
-
statements.push(this.buildVIEW(obj).trim());
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
return statements;
|
|
26
|
-
}
|
|
27
|
-
//////////////////
|
|
28
9
|
// https://www.sqlite.org/lang_createview.html
|
|
29
10
|
buildVIEW(view) {
|
|
30
11
|
const fields = view.getFields();
|
|
@@ -6,9 +6,14 @@ class SQLFieldNameTranspiler {
|
|
|
6
6
|
transpile(node, _traversal) {
|
|
7
7
|
const chunk = new chunk_1.Chunk();
|
|
8
8
|
let concat = node.concatTokens();
|
|
9
|
+
/*
|
|
9
10
|
if (concat.includes("~") && concat.split("~")[0].includes("/")) {
|
|
10
|
-
|
|
11
|
-
}
|
|
11
|
+
concat = "'" + concat.replace("~", "'~");
|
|
12
|
+
} else {
|
|
13
|
+
*/
|
|
14
|
+
concat = concat.replace(/~/, `\\".\\"`);
|
|
15
|
+
concat = `\\"` + concat + `\\"`;
|
|
16
|
+
// }
|
|
12
17
|
chunk.appendString(concat);
|
|
13
18
|
return chunk;
|
|
14
19
|
}
|
package/package.json
CHANGED