@abaplint/core 2.102.48 → 2.102.50

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.
@@ -2001,6 +2001,7 @@ declare class ExpressionNode extends AbstractNode<ExpressionNode | TokenNode> {
2001
2001
  findDirectExpression(type: new () => IStatementRunnable): ExpressionNode | undefined;
2002
2002
  findExpressionAfterToken(text: string): ExpressionNode | undefined;
2003
2003
  findDirectExpressions(type: new () => IStatementRunnable): readonly ExpressionNode[];
2004
+ findDirectExpressionsMulti(type: (new () => IStatementRunnable)[]): ExpressionNode[];
2004
2005
  findDirectTokenByText(text: string): Token | undefined;
2005
2006
  findAllExpressionsRecursive(type: new () => IStatementRunnable): readonly ExpressionNode[];
2006
2007
  findAllExpressions(type: new () => IStatementRunnable): readonly ExpressionNode[];
@@ -2186,6 +2187,7 @@ declare namespace Expressions {
2186
2187
  SQLHaving,
2187
2188
  SQLHints,
2188
2189
  SQLIn,
2190
+ SQLIntoList,
2189
2191
  SQLIntoStructure,
2190
2192
  SQLIntoTable,
2191
2193
  SQLJoin,
@@ -5475,6 +5477,10 @@ declare class SQLIn extends Expression {
5475
5477
  getRunnable(): IStatementRunnable;
5476
5478
  }
5477
5479
 
5480
+ declare class SQLIntoList extends Expression {
5481
+ getRunnable(): IStatementRunnable;
5482
+ }
5483
+
5478
5484
  declare class SQLIntoStructure extends Expression {
5479
5485
  getRunnable(): IStatementRunnable;
5480
5486
  }
@@ -191,6 +191,7 @@ __exportStar(require("./sql_group_by"), exports);
191
191
  __exportStar(require("./sql_having"), exports);
192
192
  __exportStar(require("./sql_hints"), exports);
193
193
  __exportStar(require("./sql_in"), exports);
194
+ __exportStar(require("./sql_into_list"), exports);
194
195
  __exportStar(require("./sql_into_structure"), exports);
195
196
  __exportStar(require("./sql_into_table"), exports);
196
197
  __exportStar(require("./sql_join"), exports);
@@ -11,13 +11,13 @@ const sql_field_name_1 = require("./sql_field_name");
11
11
  const sql_up_to_1 = require("./sql_up_to");
12
12
  class Select extends combi_1.Expression {
13
13
  getRunnable() {
14
- const into = (0, combi_1.altPrio)(_1.SQLIntoTable, sql_into_structure_1.SQLIntoStructure);
14
+ const into = (0, combi_1.altPrio)(_1.SQLIntoTable, sql_into_structure_1.SQLIntoStructure, _1.SQLIntoList);
15
15
  const where = (0, combi_1.seq)("WHERE", _1.SQLCond);
16
16
  const offset = (0, combi_1.ver)(version_1.Version.v751, (0, combi_1.seq)("OFFSET", _1.SQLSource));
17
17
  const bypass = (0, combi_1.str)("BYPASSING BUFFER");
18
18
  const fields = (0, combi_1.ver)(version_1.Version.v750, _1.SQLFields);
19
19
  const perm = (0, combi_1.per)(_1.SQLFrom, into, _1.SQLForAllEntries, where, _1.SQLOrderBy, sql_up_to_1.SQLUpTo, offset, _1.SQLClient, _1.SQLHaving, bypass, sql_group_by_1.SQLGroupBy, fields, _1.DatabaseConnection);
20
- const permSingle = (0, combi_1.per)(_1.SQLFrom, sql_into_structure_1.SQLIntoStructure, where, _1.SQLClient, bypass, fields, _1.DatabaseConnection);
20
+ const permSingle = (0, combi_1.per)(_1.SQLFrom, (0, combi_1.altPrio)(sql_into_structure_1.SQLIntoStructure, _1.SQLIntoList), where, _1.SQLClient, bypass, fields, _1.DatabaseConnection);
21
21
  const paren = (0, combi_1.seq)((0, combi_1.tok)(tokens_1.WParenLeftW), sql_field_name_1.SQLFieldName, (0, combi_1.tok)(tokens_1.WParenRightW));
22
22
  const fieldList = (0, combi_1.optPrio)((0, combi_1.altPrio)(_1.SQLFieldList, paren));
23
23
  const single = (0, combi_1.seq)("SINGLE", (0, combi_1.optPrio)("FOR UPDATE"), fieldList, permSingle);
@@ -17,8 +17,9 @@ class SelectLoop extends combi_1.Expression {
17
17
  const pack = (0, combi_1.seq)("PACKAGE SIZE", _1.SQLSource);
18
18
  const tab = (0, combi_1.seq)(_1.SQLIntoTable, (0, combi_1.alt)(pack, (0, combi_1.seq)(_1.SQLFrom, pack), (0, combi_1.seq)(pack, _1.SQLFrom)));
19
19
  const packTab = (0, combi_1.seq)(pack, _1.SQLIntoTable);
20
- const perm = (0, combi_1.per)(_1.SQLFrom, where, sql_up_to_1.SQLUpTo, sql_order_by_1.SQLOrderBy, sql_having_1.SQLHaving, _1.SQLClient, bypass, _1.SQLGroupBy, _1.SQLForAllEntries, (0, combi_1.alt)(tab, sql_into_structure_1.SQLIntoStructure, packTab));
21
- const strict = (0, combi_1.seq)(_1.SQLFrom, (0, combi_1.ver)(version_1.Version.v750, _1.SQLFields), where, sql_into_structure_1.SQLIntoStructure, sql_up_to_1.SQLUpTo);
20
+ const into = (0, combi_1.altPrio)(sql_into_structure_1.SQLIntoStructure, _1.SQLIntoList);
21
+ const perm = (0, combi_1.per)(_1.SQLFrom, where, sql_up_to_1.SQLUpTo, sql_order_by_1.SQLOrderBy, sql_having_1.SQLHaving, _1.SQLClient, bypass, _1.SQLGroupBy, _1.SQLForAllEntries, (0, combi_1.alt)(tab, into, packTab));
22
+ const strict = (0, combi_1.seq)(_1.SQLFrom, (0, combi_1.ver)(version_1.Version.v750, _1.SQLFields), where, into, sql_up_to_1.SQLUpTo);
22
23
  const ret = (0, combi_1.seq)("SELECT", (0, combi_1.altPrio)((0, combi_1.seq)((0, combi_1.optPrio)("DISTINCT"), sql_field_list_loop_1.SQLFieldListLoop, perm), strict), (0, combi_1.optPrio)(sql_hints_1.SQLHints));
23
24
  return ret;
24
25
  }
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SQLIntoList = void 0;
4
+ const combi_1 = require("../combi");
5
+ const _1 = require(".");
6
+ const paren_left_1 = require("../../1_lexer/tokens/paren_left");
7
+ class SQLIntoList extends combi_1.Expression {
8
+ getRunnable() {
9
+ const intoList = (0, combi_1.seq)((0, combi_1.altPrio)((0, combi_1.tok)(paren_left_1.WParenLeft), (0, combi_1.tok)(paren_left_1.WParenLeftW)), (0, combi_1.starPrio)((0, combi_1.seq)(_1.SQLTarget, ",")), _1.SQLTarget, ")");
10
+ return (0, combi_1.seq)("INTO", intoList);
11
+ }
12
+ }
13
+ exports.SQLIntoList = SQLIntoList;
14
+ //# sourceMappingURL=sql_into_list.js.map
@@ -3,12 +3,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.SQLIntoStructure = void 0;
4
4
  const combi_1 = require("../combi");
5
5
  const _1 = require(".");
6
- const paren_left_1 = require("../../1_lexer/tokens/paren_left");
7
6
  class SQLIntoStructure extends combi_1.Expression {
8
7
  getRunnable() {
9
- const intoList = (0, combi_1.seq)((0, combi_1.altPrio)((0, combi_1.tok)(paren_left_1.WParenLeft), (0, combi_1.tok)(paren_left_1.WParenLeftW)), (0, combi_1.starPrio)((0, combi_1.seq)(_1.SQLTarget, ",")), _1.SQLTarget, ")");
10
8
  const intoSimple = (0, combi_1.seq)((0, combi_1.optPrio)("CORRESPONDING FIELDS OF"), _1.SQLTarget);
11
- return (0, combi_1.seq)("INTO", (0, combi_1.altPrio)(intoList, intoSimple));
9
+ return (0, combi_1.seq)("INTO", intoSimple);
12
10
  }
13
11
  }
14
12
  exports.SQLIntoStructure = SQLIntoStructure;
@@ -8,7 +8,7 @@ const sql_into_structure_1 = require("../expressions/sql_into_structure");
8
8
  class FetchNextCursor {
9
9
  getMatcher() {
10
10
  const size = (0, combi_1.seq)("PACKAGE SIZE", expressions_1.SQLSourceSimple);
11
- const ret = (0, combi_1.seq)("FETCH NEXT CURSOR", expressions_1.SQLSourceSimple, (0, combi_1.alt)(sql_into_structure_1.SQLIntoStructure, expressions_1.SQLIntoTable), (0, combi_1.optPrio)(size));
11
+ const ret = (0, combi_1.seq)("FETCH NEXT CURSOR", expressions_1.SQLSourceSimple, (0, combi_1.alt)(sql_into_structure_1.SQLIntoStructure, expressions_1.SQLIntoTable, expressions_1.SQLIntoList), (0, combi_1.optPrio)(size));
12
12
  return (0, combi_1.verNot)(version_1.Version.Cloud, ret);
13
13
  }
14
14
  }
@@ -10,6 +10,7 @@ const sql_for_all_entries_1 = require("./sql_for_all_entries");
10
10
  const _scope_type_1 = require("../_scope_type");
11
11
  const sql_source_1 = require("./sql_source");
12
12
  const sql_compare_1 = require("./sql_compare");
13
+ const isSimple = /^\w+$/;
13
14
  class Select {
14
15
  runSyntax(node, scope, filename, skipImplicitInto = false) {
15
16
  var _a, _b;
@@ -22,10 +23,7 @@ class Select {
22
23
  throw new Error(`fields missing`);
23
24
  }
24
25
  this.checkFields(fields, dbSources, scope);
25
- for (const inline of node.findAllExpressions(Expressions.InlineData)) {
26
- // todo, for now these are voided
27
- new inline_data_1.InlineData().runSyntax(inline, scope, filename, this.buildType(fields));
28
- }
26
+ this.handleInto(node, scope, filename, fields, dbSources);
29
27
  const fae = node.findDirectExpression(Expressions.SQLForAllEntries);
30
28
  if (fae) {
31
29
  scope.push(_scope_type_1.ScopeType.OpenSQL, "SELECT", token.getStart(), filename);
@@ -37,6 +35,7 @@ class Select {
37
35
  // check implicit into, the target field is implict equal to the table name
38
36
  if (skipImplicitInto === false
39
37
  && node.findDirectExpression(Expressions.SQLIntoTable) === undefined
38
+ && node.findDirectExpression(Expressions.SQLIntoList) === undefined
40
39
  && node.findDirectExpression(Expressions.SQLIntoStructure) === undefined) {
41
40
  const fields = (_a = node.findFirstExpression(Expressions.SQLAggregation)) === null || _a === void 0 ? void 0 : _a.concatTokens();
42
41
  const c = new RegExp(/^count\(\s*\*\s*\)$/, "i");
@@ -68,6 +67,54 @@ class Select {
68
67
  scope.pop(node.getLastToken().getEnd());
69
68
  }
70
69
  }
70
+ handleInto(node, scope, filename, fields, dbSources) {
71
+ const intoTable = node.findDirectExpression(Expressions.SQLIntoTable);
72
+ if (intoTable) {
73
+ const inline = intoTable.findFirstExpression(Expressions.InlineData);
74
+ if (inline) {
75
+ new inline_data_1.InlineData().runSyntax(inline, scope, filename, this.buildTableType(fields, dbSources, scope));
76
+ }
77
+ }
78
+ const intoStructure = node.findDirectExpression(Expressions.SQLIntoStructure);
79
+ if (intoStructure) {
80
+ for (const inline of intoStructure.findAllExpressions(Expressions.InlineData)) {
81
+ // todo, for now these are voided
82
+ new inline_data_1.InlineData().runSyntax(inline, scope, filename, new basic_1.VoidType("SELECT_todo"));
83
+ }
84
+ }
85
+ const intoList = node.findDirectExpression(Expressions.SQLIntoList);
86
+ if (intoList) {
87
+ const isDynamic = fields.length === 1 && fields[0].expression.findDirectExpression(Expressions.Dynamic) !== undefined;
88
+ const targets = intoList.findDirectExpressions(Expressions.SQLTarget);
89
+ if (targets.length !== fields.length && isDynamic !== true) {
90
+ throw new Error(`number of fields selected vs list does not match`);
91
+ }
92
+ for (let i = 0; i < targets.length; i++) {
93
+ const target = targets[i];
94
+ const field = fields[i];
95
+ const inline = target.findFirstExpression(Expressions.InlineData);
96
+ if (inline) {
97
+ if (isDynamic) {
98
+ throw new Error(`dynamic field list, inlining not possible`);
99
+ }
100
+ if (isSimple.test(field.code) && dbSources.length === 1 && dbSources[0] !== undefined) {
101
+ const dbType = dbSources[0].parseType(scope.getRegistry());
102
+ let type = new basic_1.VoidType("SELECT_todo");
103
+ if (dbType instanceof basic_1.StructureType) {
104
+ type = dbType.getComponentByName(field.code);
105
+ if (type === undefined) {
106
+ throw new Error(`handleInto, internal error, should be checked earlier`);
107
+ }
108
+ }
109
+ new inline_data_1.InlineData().runSyntax(inline, scope, filename, type);
110
+ }
111
+ else {
112
+ new inline_data_1.InlineData().runSyntax(inline, scope, filename, new basic_1.VoidType("SELECT_todo"));
113
+ }
114
+ }
115
+ }
116
+ }
117
+ }
71
118
  checkFields(fields, dbSources, scope) {
72
119
  if (dbSources.length > 1) {
73
120
  return;
@@ -84,7 +131,6 @@ class Select {
84
131
  if (!(type instanceof basic_1.StructureType)) {
85
132
  throw new Error("checkFields, expected structure, " + type.constructor.name);
86
133
  }
87
- const isSimple = /^\w+$/;
88
134
  for (const field of fields) {
89
135
  if (field.code === "*") {
90
136
  continue;
@@ -94,21 +140,44 @@ class Select {
94
140
  }
95
141
  }
96
142
  }
97
- buildType(_fields) {
143
+ buildTableType(fields, dbSources, scope) {
144
+ if (dbSources.length !== 1) {
145
+ return new basic_1.VoidType("SELECT_todo");
146
+ }
147
+ if (dbSources[0] === undefined) {
148
+ // then its a voided table
149
+ return new basic_1.VoidType("SELECT_todo");
150
+ }
151
+ const dbType = dbSources[0].parseType(scope.getRegistry());
152
+ if (!(dbType instanceof basic_1.StructureType)) {
153
+ return new basic_1.VoidType("SELECT_todo");
154
+ }
155
+ if (fields.length === 1 && fields[0].code === "*") {
156
+ return new basic_1.TableType(dbType, { withHeader: false, keyType: basic_1.TableKeyType.default }, undefined);
157
+ }
158
+ const allFieldsSimple = fields.every(f => isSimple.test(f.code));
159
+ if (allFieldsSimple === true) {
160
+ const components = [];
161
+ for (const field of fields) {
162
+ const type = dbType.getComponentByName(field.code);
163
+ if (type === undefined) {
164
+ return new basic_1.VoidType("SELECT_todo");
165
+ }
166
+ components.push({ name: field.code, type });
167
+ }
168
+ return new basic_1.TableType(new basic_1.StructureType(components), { withHeader: false, keyType: basic_1.TableKeyType.default }, undefined);
169
+ }
98
170
  return new basic_1.VoidType("SELECT_todo");
99
171
  }
100
172
  findFields(node) {
101
173
  var _a;
102
174
  let expr = undefined;
103
175
  const ret = [];
104
- expr = node.findDirectExpression(Expressions.SQLFieldList);
105
- if (expr === undefined) {
106
- expr = node.findDirectExpression(Expressions.SQLFields);
107
- }
176
+ expr = node.findFirstExpression(Expressions.SQLFieldList);
108
177
  if (expr === undefined) {
109
- node.findDirectExpression(Expressions.SQLFieldName);
178
+ expr = node.findDirectExpression(Expressions.SQLFieldListLoop);
110
179
  }
111
- for (const field of (expr === null || expr === void 0 ? void 0 : expr.findAllExpressions(Expressions.SQLField)) || []) {
180
+ for (const field of (expr === null || expr === void 0 ? void 0 : expr.findDirectExpressionsMulti([Expressions.SQLField, Expressions.SQLFieldName])) || []) {
112
181
  let code = field.concatTokens().toUpperCase();
113
182
  const as = ((_a = field.findDirectExpression(Expressions.SQLAsName)) === null || _a === void 0 ? void 0 : _a.concatTokens()) || "";
114
183
  if (as !== "") {
@@ -153,6 +153,20 @@ class ExpressionNode extends _abstract_node_1.AbstractNode {
153
153
  }
154
154
  return ret;
155
155
  }
156
+ findDirectExpressionsMulti(type) {
157
+ const ret = [];
158
+ for (const child of this.getChildren()) {
159
+ if (child instanceof ExpressionNode) {
160
+ for (const t of type) {
161
+ if (child.get() instanceof t) {
162
+ ret.push(child);
163
+ break;
164
+ }
165
+ }
166
+ }
167
+ }
168
+ return ret;
169
+ }
156
170
  findDirectTokenByText(text) {
157
171
  for (const child of this.getChildren()) {
158
172
  if (child instanceof token_node_1.TokenNode && child.get().getStr().toUpperCase() === text.toUpperCase()) {
@@ -65,7 +65,7 @@ class Registry {
65
65
  }
66
66
  static abaplintVersion() {
67
67
  // magic, see build script "version.sh"
68
- return "2.102.48";
68
+ return "2.102.50";
69
69
  }
70
70
  getDDICReferences() {
71
71
  return this.ddicReferences;
@@ -81,7 +81,7 @@ ENDIF.
81
81
  }
82
82
  ////////////////////
83
83
  analyzeInto(file, m) {
84
- const into = m.findFirstExpression(Expressions.SQLIntoStructure);
84
+ const into = m.findFirstExpression(Expressions.SQLIntoList);
85
85
  if (into === undefined) {
86
86
  return [];
87
87
  }
@@ -209,6 +209,7 @@ ENDIF.`,
209
209
  if (this.conf.selectWithoutInto
210
210
  && (sta instanceof Statements.Select || sta instanceof Statements.SelectLoop)
211
211
  && staNode.findFirstExpression(Expressions.SQLIntoStructure) === undefined
212
+ && staNode.findFirstExpression(Expressions.SQLIntoList) === undefined
212
213
  && staNode.findFirstExpression(Expressions.SQLIntoTable) === undefined) {
213
214
  const concat = (_a = staNode.findFirstExpression(Expressions.SQLFieldList)) === null || _a === void 0 ? void 0 : _a.concatTokens().toUpperCase();
214
215
  if (concat !== "COUNT(*)" && concat !== "COUNT( * )") {
@@ -55,6 +55,7 @@ Activates from v750 and up`,
55
55
  const where = expr === null || expr === void 0 ? void 0 : expr.findDirectExpression(Expressions.SQLCond);
56
56
  const order = expr === null || expr === void 0 ? void 0 : expr.findDirectExpression(Expressions.SQLOrderBy);
57
57
  const into = (expr === null || expr === void 0 ? void 0 : expr.findDirectExpression(Expressions.SQLIntoStructure))
58
+ || (expr === null || expr === void 0 ? void 0 : expr.findDirectExpression(Expressions.SQLIntoList))
58
59
  || (expr === null || expr === void 0 ? void 0 : expr.findDirectExpression(Expressions.SQLIntoTable));
59
60
  if (into === undefined || where === undefined) {
60
61
  continue;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abaplint/core",
3
- "version": "2.102.48",
3
+ "version": "2.102.50",
4
4
  "description": "abaplint - Core API",
5
5
  "main": "build/src/index.js",
6
6
  "typings": "build/abaplint.d.ts",
@@ -52,9 +52,9 @@
52
52
  "devDependencies": {
53
53
  "@microsoft/api-extractor": "^7.37.1",
54
54
  "@types/chai": "^4.3.6",
55
- "@types/mocha": "^10.0.1",
56
- "@types/node": "^20.7.0",
57
- "chai": "^4.3.8",
55
+ "@types/mocha": "^10.0.2",
56
+ "@types/node": "^20.7.1",
57
+ "chai": "^4.3.9",
58
58
  "eslint": "^8.50.0",
59
59
  "mocha": "^10.2.0",
60
60
  "c8": "^8.0.1",