@abaplint/runtime 2.10.81 → 2.10.83
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/build/src/expand_dynamic.d.ts +1 -1
- package/build/src/expand_dynamic.js +4 -4
- package/build/src/statements/index.d.ts +2 -4
- package/build/src/statements/index.js +2 -59
- package/build/src/statements/loop.d.ts +4 -0
- package/build/src/statements/loop.js +40 -0
- package/build/src/trace.d.ts +12 -0
- package/build/src/trace.js +78 -0
- package/package.json +1 -1
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { FieldSymbol } from "./types";
|
|
2
|
-
export declare function expandDynamic(code: string,
|
|
2
|
+
export declare function expandDynamic(code: string, evaluate: (name: string) => FieldSymbol | undefined): string;
|
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.expandDynamic = expandDynamic;
|
|
4
4
|
const expand_in_1 = require("./expand_in");
|
|
5
5
|
const types_1 = require("./types");
|
|
6
|
-
function expandDynamic(code,
|
|
6
|
+
function expandDynamic(code, evaluate) {
|
|
7
7
|
// console.dir(code);
|
|
8
8
|
if (code === "") {
|
|
9
9
|
return "1 = 1";
|
|
@@ -18,7 +18,7 @@ function expandDynamic(code, ev) {
|
|
|
18
18
|
if (match && match[1] && match[2] && match[3]) {
|
|
19
19
|
let name = "fs_" + match[2] + "_";
|
|
20
20
|
name = name.toLowerCase();
|
|
21
|
-
let found =
|
|
21
|
+
let found = evaluate(name);
|
|
22
22
|
if (found instanceof types_1.FieldSymbol) {
|
|
23
23
|
found = found.get()[match[3].toLowerCase()];
|
|
24
24
|
if (found === undefined) {
|
|
@@ -38,7 +38,7 @@ function expandDynamic(code, ev) {
|
|
|
38
38
|
if (match && match[1] && match[2]) {
|
|
39
39
|
let name = "fs_" + match[1] + "_";
|
|
40
40
|
name = name.toLowerCase();
|
|
41
|
-
let found =
|
|
41
|
+
let found = evaluate(name);
|
|
42
42
|
if (found instanceof types_1.FieldSymbol) {
|
|
43
43
|
found = found.get()[match[2].toLowerCase()];
|
|
44
44
|
if (found === undefined) {
|
|
@@ -58,7 +58,7 @@ function expandDynamic(code, ev) {
|
|
|
58
58
|
if (match && match[1]) {
|
|
59
59
|
let name = "fs_" + match[1] + "_";
|
|
60
60
|
name = name.toLowerCase();
|
|
61
|
-
const found =
|
|
61
|
+
const found = evaluate(name);
|
|
62
62
|
if (found instanceof types_1.FieldSymbol) {
|
|
63
63
|
code = code.replace(regex, " '" + found.get() + "'");
|
|
64
64
|
}
|
|
@@ -50,6 +50,7 @@ import { FieldSymbol, Structure, Table } from "../types";
|
|
|
50
50
|
import { INumeric } from "../types/_numeric";
|
|
51
51
|
import { ICallFunctionOptions } from "./call_function";
|
|
52
52
|
import { SelectDatabaseOptions, SelectRuntimeOptions } from "../db/db";
|
|
53
|
+
import { Trace } from "../trace";
|
|
53
54
|
export declare class Statements {
|
|
54
55
|
append: typeof append;
|
|
55
56
|
assert: typeof assert;
|
|
@@ -91,11 +92,8 @@ export declare class Statements {
|
|
|
91
92
|
receive: typeof receive;
|
|
92
93
|
callTransaction: typeof callTransaction;
|
|
93
94
|
private readonly context;
|
|
94
|
-
private readonly traceTotals;
|
|
95
95
|
constructor(context: Context);
|
|
96
|
-
|
|
97
|
-
private _traceAsync;
|
|
98
|
-
_setTrace(min?: number, totals?: boolean): void;
|
|
96
|
+
_setTrace(min?: number, totals?: boolean): Trace;
|
|
99
97
|
openCursor(target: INumeric, select: string, options: IOpenCursorDatabaseOptions): Promise<void>;
|
|
100
98
|
fetchNextCursor(cursor: INumeric, target: any, packageSize?: INumeric): Promise<void>;
|
|
101
99
|
closeCursor(cursor: INumeric): Promise<void>;
|
|
@@ -51,7 +51,7 @@ const call_transaction_1 = require("./call_transaction");
|
|
|
51
51
|
const update_database_1 = require("./update_database");
|
|
52
52
|
const write_1 = require("./write");
|
|
53
53
|
const call_function_1 = require("./call_function");
|
|
54
|
-
const
|
|
54
|
+
const trace_1 = require("../trace");
|
|
55
55
|
// this is a class, as statements like SELECT needs access to the database object instance
|
|
56
56
|
// and WRITE will access the Console
|
|
57
57
|
class Statements {
|
|
@@ -96,66 +96,9 @@ class Statements {
|
|
|
96
96
|
this.receive = receive_1.receive;
|
|
97
97
|
this.callTransaction = call_transaction_1.callTransaction;
|
|
98
98
|
this.context = context;
|
|
99
|
-
this.traceTotals = {};
|
|
100
|
-
}
|
|
101
|
-
_trace(func, name, min, totals) {
|
|
102
|
-
const tt = this.traceTotals;
|
|
103
|
-
const exec = (...options) => {
|
|
104
|
-
const start = Date.now();
|
|
105
|
-
const result = func.bind(this)(...options);
|
|
106
|
-
const runtime = Date.now() - start;
|
|
107
|
-
if (totals === true) {
|
|
108
|
-
if (tt[name] === undefined) {
|
|
109
|
-
tt[name] = 0;
|
|
110
|
-
}
|
|
111
|
-
tt[name] += runtime;
|
|
112
|
-
}
|
|
113
|
-
if (runtime >= min) {
|
|
114
|
-
console.log(`STATEMENT: ${name}, ${runtime} ms`);
|
|
115
|
-
if (totals === true) {
|
|
116
|
-
console.log(JSON.stringify(tt));
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
return result;
|
|
120
|
-
};
|
|
121
|
-
return exec;
|
|
122
|
-
}
|
|
123
|
-
_traceAsync(func, name, min, totals) {
|
|
124
|
-
const tt = this.traceTotals;
|
|
125
|
-
const exec = async (...options) => {
|
|
126
|
-
const start = Date.now();
|
|
127
|
-
const result = await func.bind(this)(...options);
|
|
128
|
-
const runtime = Date.now() - start;
|
|
129
|
-
if (totals === true) {
|
|
130
|
-
if (tt[name] === undefined) {
|
|
131
|
-
tt[name] = 0;
|
|
132
|
-
}
|
|
133
|
-
tt[name] += runtime;
|
|
134
|
-
}
|
|
135
|
-
if (runtime >= min) {
|
|
136
|
-
console.log(`STATEMENT: ${name}, ${runtime} ms`);
|
|
137
|
-
if (totals === true) {
|
|
138
|
-
console.log(JSON.stringify(tt));
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
return result;
|
|
142
|
-
};
|
|
143
|
-
return exec;
|
|
144
99
|
}
|
|
145
100
|
_setTrace(min = 10, totals = false) {
|
|
146
|
-
|
|
147
|
-
for (const c of candidates) {
|
|
148
|
-
if (c === "context" || c === "constructor" || c.startsWith("_") || c === "loop") {
|
|
149
|
-
continue;
|
|
150
|
-
}
|
|
151
|
-
const func = this[c];
|
|
152
|
-
if ((0, types_1.isAsyncFunction)(func)) {
|
|
153
|
-
this[c] = this._traceAsync(func, c, min, totals);
|
|
154
|
-
}
|
|
155
|
-
else {
|
|
156
|
-
this[c] = this._trace(func, c, min, totals);
|
|
157
|
-
}
|
|
158
|
-
}
|
|
101
|
+
return new trace_1.Trace().setTrace(min, totals, this);
|
|
159
102
|
}
|
|
160
103
|
async openCursor(target, select, options) {
|
|
161
104
|
const num = await (0, open_cursor_1.openCursor)(this.context, select, options);
|
|
@@ -10,6 +10,10 @@ export interface ILoopOptions {
|
|
|
10
10
|
from?: Integer;
|
|
11
11
|
to?: Integer;
|
|
12
12
|
topEquals?: topType;
|
|
13
|
+
dynamicWhere?: {
|
|
14
|
+
condition: string;
|
|
15
|
+
evaluate: (name: string) => FieldSymbol | undefined;
|
|
16
|
+
};
|
|
13
17
|
}
|
|
14
18
|
export declare function loop(table: Table | HashedTable | FieldSymbol | undefined, options?: ILoopOptions): AsyncGenerator<any, void, unknown>;
|
|
15
19
|
export {};
|
|
@@ -23,6 +23,38 @@ function determineFromTo(array, topEquals, key) {
|
|
|
23
23
|
to: to,
|
|
24
24
|
};
|
|
25
25
|
}
|
|
26
|
+
// todo: rewrite, this is a mess & hack & slow
|
|
27
|
+
function dynamicToWhere(condition, evaluate) {
|
|
28
|
+
// console.dir(condition);
|
|
29
|
+
let text = condition.replace(/ AND /gi, " && ").replace(/ OR /gi, " || ").replace(/ = /gi, " EQ ").replace(/ <> /gi, " NE ");
|
|
30
|
+
// console.dir(text);
|
|
31
|
+
let regex = /([\w-]+)\s+(\w+)\s+([<>\w-]+)/gi;
|
|
32
|
+
let matches = text.matchAll(regex);
|
|
33
|
+
for (const match of matches) {
|
|
34
|
+
const left = match[1];
|
|
35
|
+
const comparator = match[2].toLowerCase();
|
|
36
|
+
const right = match[3];
|
|
37
|
+
// console.dir({left, right});
|
|
38
|
+
const cleft = "i." + left.toLowerCase().replace(/-/g, ".get().");
|
|
39
|
+
const cright = right;
|
|
40
|
+
const cnew = `abap.compare.${comparator}(${cleft}, ${cright})`;
|
|
41
|
+
text = text.replace(match[0], cnew);
|
|
42
|
+
}
|
|
43
|
+
regex = / <(\w+)>-(\w+)/gi;
|
|
44
|
+
matches = text.matchAll(regex);
|
|
45
|
+
for (const match of matches) {
|
|
46
|
+
const name = "fs_" + match[1].toLowerCase() + "_";
|
|
47
|
+
const value = evaluate(name)?.get()?.[match[2].toLowerCase()]?.get();
|
|
48
|
+
text = text.replace(match[0], " '" + value + "'");
|
|
49
|
+
}
|
|
50
|
+
// console.dir(text);
|
|
51
|
+
// @ts-ignore
|
|
52
|
+
return async (i) => {
|
|
53
|
+
// console.dir(i);
|
|
54
|
+
// eslint-disable-next-line no-eval
|
|
55
|
+
return eval(text);
|
|
56
|
+
};
|
|
57
|
+
}
|
|
26
58
|
async function* loop(table, options) {
|
|
27
59
|
if (table === undefined) {
|
|
28
60
|
throw new Error("LOOP at undefined");
|
|
@@ -35,6 +67,14 @@ async function* loop(table, options) {
|
|
|
35
67
|
yield* loop(pnt, options);
|
|
36
68
|
return;
|
|
37
69
|
}
|
|
70
|
+
if (options?.dynamicWhere) {
|
|
71
|
+
const dynamicWhere = options.dynamicWhere;
|
|
72
|
+
const newOptions = { ...options };
|
|
73
|
+
delete newOptions.dynamicWhere;
|
|
74
|
+
newOptions.where = dynamicToWhere(dynamicWhere.condition, dynamicWhere.evaluate);
|
|
75
|
+
yield* loop(table, newOptions);
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
38
78
|
const length = table.getArrayLength();
|
|
39
79
|
if (length === 0) {
|
|
40
80
|
// @ts-ignore
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export declare class Trace {
|
|
2
|
+
private readonly traceTotals;
|
|
3
|
+
setTrace(min: number, totals: boolean, statements: any): this;
|
|
4
|
+
getTotals(): {
|
|
5
|
+
[name: string]: {
|
|
6
|
+
calls: number;
|
|
7
|
+
totalRuntime: number;
|
|
8
|
+
};
|
|
9
|
+
};
|
|
10
|
+
private _trace;
|
|
11
|
+
private _traceAsync;
|
|
12
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Trace = void 0;
|
|
4
|
+
const types_1 = require("util/types");
|
|
5
|
+
const statements_1 = require("./statements");
|
|
6
|
+
class Trace {
|
|
7
|
+
constructor() {
|
|
8
|
+
this.traceTotals = {};
|
|
9
|
+
}
|
|
10
|
+
setTrace(min, totals, statements) {
|
|
11
|
+
const candidates = [...Object.keys(statements), ...Object.getOwnPropertyNames(statements_1.Statements.prototype)];
|
|
12
|
+
for (const c of candidates) {
|
|
13
|
+
if (c === "context" || c === "constructor" || c.startsWith("_") || c === "loop") {
|
|
14
|
+
continue;
|
|
15
|
+
}
|
|
16
|
+
const func = statements[c];
|
|
17
|
+
if ((0, types_1.isAsyncFunction)(func)) {
|
|
18
|
+
statements[c] = this._traceAsync(func, c, min, totals);
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
statements[c] = this._trace(func, c, min, totals);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return this;
|
|
25
|
+
}
|
|
26
|
+
getTotals() {
|
|
27
|
+
return this.traceTotals;
|
|
28
|
+
}
|
|
29
|
+
//////////////////////////////////////////
|
|
30
|
+
_trace(func, name, min, totals) {
|
|
31
|
+
const tt = this.traceTotals;
|
|
32
|
+
const exec1 = (...options) => {
|
|
33
|
+
const start = Date.now();
|
|
34
|
+
const result = func.bind(this)(...options);
|
|
35
|
+
const runtime = Date.now() - start;
|
|
36
|
+
if (totals === true) {
|
|
37
|
+
if (tt[name] === undefined) {
|
|
38
|
+
tt[name] = { calls: 0, totalRuntime: 0 };
|
|
39
|
+
}
|
|
40
|
+
tt[name].totalRuntime += runtime;
|
|
41
|
+
tt[name].calls++;
|
|
42
|
+
}
|
|
43
|
+
if (min > 0 && runtime >= min) {
|
|
44
|
+
console.log(`STATEMENT: ${name}, ${runtime} ms`);
|
|
45
|
+
if (totals === true) {
|
|
46
|
+
console.log(JSON.stringify(tt));
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return result;
|
|
50
|
+
};
|
|
51
|
+
return exec1;
|
|
52
|
+
}
|
|
53
|
+
_traceAsync(func, name, min, totals) {
|
|
54
|
+
const tt = this.traceTotals;
|
|
55
|
+
const exec2 = async (...options) => {
|
|
56
|
+
const start = Date.now();
|
|
57
|
+
const result = await func.bind(this)(...options);
|
|
58
|
+
const runtime = Date.now() - start;
|
|
59
|
+
if (totals === true) {
|
|
60
|
+
if (tt[name] === undefined) {
|
|
61
|
+
tt[name] = { calls: 0, totalRuntime: 0 };
|
|
62
|
+
}
|
|
63
|
+
tt[name].totalRuntime += runtime;
|
|
64
|
+
tt[name].calls++;
|
|
65
|
+
}
|
|
66
|
+
if (min > 0 && runtime >= min) {
|
|
67
|
+
console.log(`STATEMENT: ${name}, ${runtime} ms`);
|
|
68
|
+
if (totals === true) {
|
|
69
|
+
console.log(JSON.stringify(tt));
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return result;
|
|
73
|
+
};
|
|
74
|
+
return exec2;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
exports.Trace = Trace;
|
|
78
|
+
//# sourceMappingURL=trace.js.map
|