@sap/cds-compiler 5.4.4 → 5.5.2
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/CHANGELOG.md +22 -1
- package/bin/cds_remove_invalid_whitespace.js +4 -4
- package/bin/cds_update_annotations.js +3 -3
- package/bin/cds_update_identifiers.js +3 -3
- package/lib/api/main.js +18 -30
- package/lib/api/validate.js +6 -1
- package/lib/base/lazyload.js +28 -0
- package/lib/base/location.js +1 -0
- package/lib/base/message-registry.js +47 -11
- package/lib/base/messages.js +17 -3
- package/lib/checks/cdsMap.js +27 -0
- package/lib/checks/{dbFeatureFlags.js → featureFlags.js} +1 -1
- package/lib/checks/parameters.js +61 -4
- package/lib/checks/validator.js +17 -7
- package/lib/compiler/define.js +1 -0
- package/lib/compiler/index.js +7 -7
- package/lib/gen/BaseParser.js +345 -235
- package/lib/gen/CdlParser.js +4438 -4492
- package/lib/gen/Dictionary.json +2 -2
- package/lib/language/antlrParser.js +2 -111
- package/lib/main.js +16 -37
- package/lib/model/cloneCsn.js +1 -5
- package/lib/modelCompare/utils/filter.js +47 -21
- package/lib/parsers/AstBuildingParser.js +92 -73
- package/lib/parsers/CdlGrammar.g4 +110 -137
- package/lib/parsers/index.js +123 -0
- package/lib/render/toSql.js +8 -2
- package/lib/render/utils/delta.js +33 -1
- package/lib/transform/db/{transformExists.js → assocsToQueries/transformExists.js} +12 -407
- package/lib/transform/db/assocsToQueries/utils.js +440 -0
- package/lib/transform/db/expansion.js +2 -2
- package/lib/transform/draft/db.js +14 -3
- package/lib/transform/effective/annotations.js +3 -3
- package/lib/transform/effective/main.js +5 -7
- package/lib/transform/featureFlags.js +5 -0
- package/lib/transform/forRelationalDB.js +125 -192
- package/lib/transform/transformUtils.js +0 -51
- package/lib/utils/objectUtils.js +13 -0
- package/package.json +2 -2
- package/lib/transform/db/featureFlags.js +0 -5
package/lib/gen/Dictionary.json
CHANGED
|
@@ -1089,8 +1089,7 @@
|
|
|
1089
1089
|
"Type": "Core.Tag",
|
|
1090
1090
|
"AppliesTo": [
|
|
1091
1091
|
"EntityContainer"
|
|
1092
|
-
]
|
|
1093
|
-
"$experimental": true
|
|
1092
|
+
]
|
|
1094
1093
|
},
|
|
1095
1094
|
"Common.mediaUploadLink": {
|
|
1096
1095
|
"Type": "Edm.String",
|
|
@@ -4475,6 +4474,7 @@
|
|
|
4475
4474
|
"$kind": "ComplexType",
|
|
4476
4475
|
"BaseType": "UI.DataFieldAbstract",
|
|
4477
4476
|
"Properties": {
|
|
4477
|
+
"ID": "Edm.String",
|
|
4478
4478
|
"Actions": "Collection(UI.DataFieldForActionAbstract)",
|
|
4479
4479
|
"Label": "Edm.String",
|
|
4480
4480
|
"Criticality": "UI.CriticalityType",
|
|
@@ -17,11 +17,6 @@ const { XsnSource } = require('../compiler/xsn-model');
|
|
|
17
17
|
const Parser = require('../gen/languageParser').default;
|
|
18
18
|
const Lexer = require('../gen/languageLexer').default;
|
|
19
19
|
|
|
20
|
-
const CdlLexer = require( '../parsers/Lexer' );
|
|
21
|
-
const CdlParser = require( '../gen/CdlParser' );
|
|
22
|
-
const { createMessageFunctions } = require( '../base/messages' );
|
|
23
|
-
const { CompilerAssertion } = require( '../base/error' );
|
|
24
|
-
|
|
25
20
|
// Error listener used for ANTLR4-generated parser
|
|
26
21
|
class ErrorListener extends antlr4.error.ErrorListener {
|
|
27
22
|
// method which is called by generated parser with --trace-parser[-amg]:
|
|
@@ -125,18 +120,7 @@ function tokenTypeOf( recognizer, literalName ) {
|
|
|
125
120
|
// the AST locations and error messages. If provided, `options` are compile
|
|
126
121
|
// options.
|
|
127
122
|
|
|
128
|
-
|
|
129
|
-
cdl: { func: 'start', returns: 'source', $frontend: 'cdl' },
|
|
130
|
-
query: { func: 'queryEOF', returns: 'query' },
|
|
131
|
-
expr: { func: 'conditionEOF', returns: 'cond' }, // yes, condition
|
|
132
|
-
};
|
|
133
|
-
|
|
134
|
-
function parse( source, filename = '<undefined>.cds',
|
|
135
|
-
options = {}, messageFunctions = null,
|
|
136
|
-
rule = 'cdl' ) {
|
|
137
|
-
if (options.newParser)
|
|
138
|
-
return parseWithNewParser( source, filename, options, messageFunctions, rule );
|
|
139
|
-
|
|
123
|
+
function parse( source, filename, options, messageFunctions, rulespec ) {
|
|
140
124
|
const lexer = new Lexer( new antlr4.InputStream(source) );
|
|
141
125
|
const tokenStream = new RewriteTypeTokenStream(lexer);
|
|
142
126
|
/** @type {object} */
|
|
@@ -179,10 +163,9 @@ function parse( source, filename = '<undefined>.cds',
|
|
|
179
163
|
parser.addParseListener(options.parseListener);
|
|
180
164
|
|
|
181
165
|
|
|
182
|
-
const rulespec = rules[rule];
|
|
183
166
|
let tree;
|
|
184
167
|
try {
|
|
185
|
-
tree =
|
|
168
|
+
tree = parser[rulespec.func]();
|
|
186
169
|
}
|
|
187
170
|
catch (e) {
|
|
188
171
|
if (e instanceof RangeError && e.message.match(/Maximum.*exceeded$/i)) {
|
|
@@ -219,96 +202,4 @@ function parse( source, filename = '<undefined>.cds',
|
|
|
219
202
|
return ast;
|
|
220
203
|
}
|
|
221
204
|
|
|
222
|
-
function parseWithNewParser( source, filename, options, messageFunctions, rule ) {
|
|
223
|
-
if (CdlParser.tracingParser) // tracing → direct console output of message
|
|
224
|
-
messageFunctions = createMessageFunctions( {}, 'parse', {} );
|
|
225
|
-
const lexer = new CdlLexer( filename, source );
|
|
226
|
-
const parser = new CdlParser( lexer, options, messageFunctions ).init();
|
|
227
|
-
parser.filename = filename; // LSP compatibility
|
|
228
|
-
|
|
229
|
-
const { parseListener, attachTokens } = options;
|
|
230
|
-
if (parseListener || attachTokens) {
|
|
231
|
-
const combined = [];
|
|
232
|
-
const { tokens, comments, docComments } = parser;
|
|
233
|
-
const length = tokens.length + comments.length + docComments.length;
|
|
234
|
-
let tokenIdx = 0;
|
|
235
|
-
let commentIdx = 0;
|
|
236
|
-
let docCommentIdx = 0;
|
|
237
|
-
for (let index = 0; index < length; ++index) {
|
|
238
|
-
if (tokens[tokenIdx].location.tokenIndex === index) // EOF has largest tokenIndex
|
|
239
|
-
combined.push( tokens[tokenIdx++] );
|
|
240
|
-
else if (comments[commentIdx]?.location.tokenIndex === index)
|
|
241
|
-
combined.push( comments[commentIdx++] );
|
|
242
|
-
else
|
|
243
|
-
combined.push( docComments[docCommentIdx++] );
|
|
244
|
-
}
|
|
245
|
-
if (!combined.at( -1 ))
|
|
246
|
-
throw new CompilerAssertion( 'Invalid values for `tokenIndex`' );
|
|
247
|
-
for (const tok of combined)
|
|
248
|
-
tok.start = lexer.characterPos( tok.location.line, tok.location.col );
|
|
249
|
-
|
|
250
|
-
parser._input = { tokens: combined, lexer }; // lexer for characterPos() in cdshi.js
|
|
251
|
-
parser.getTokenStream = function getTokenStream() {
|
|
252
|
-
return this._input;
|
|
253
|
-
};
|
|
254
|
-
}
|
|
255
|
-
// LSP feature: provide parse listener with ANTLR-like context:
|
|
256
|
-
if (parseListener) {
|
|
257
|
-
// TODO LSP: we could also call different listener methods: then LSP could
|
|
258
|
-
// have dedicated methods for ANTLR-based and new parser
|
|
259
|
-
parser.rule_ = function rule_( ...args ) {
|
|
260
|
-
CdlParser.prototype.rule_.apply( this, args );
|
|
261
|
-
let state = this.s;
|
|
262
|
-
while (typeof this.table[--state] !== 'string')
|
|
263
|
-
;
|
|
264
|
-
const $ctx = { // TODO LSP: more to add?
|
|
265
|
-
parser: this, // set in generated ANTLR parser for each rule context
|
|
266
|
-
ruleName: this.table[state], // instead of ruleIndex
|
|
267
|
-
start: this.la(), // set in Parser#enterRule
|
|
268
|
-
stop: null,
|
|
269
|
-
};
|
|
270
|
-
parser.stack.at( -1 ).$ctx = $ctx;
|
|
271
|
-
parseListener.enterEveryRule( $ctx );
|
|
272
|
-
};
|
|
273
|
-
parser.exit_ = function exit_( ...args ) {
|
|
274
|
-
const { $ctx } = parser.stack.at( -1 );
|
|
275
|
-
// TODO: what should we do in case of errors?
|
|
276
|
-
$ctx.stop = this.lb();
|
|
277
|
-
parseListener.exitEveryRule( $ctx );
|
|
278
|
-
return CdlParser.prototype.exit_.apply( this, args );
|
|
279
|
-
};
|
|
280
|
-
parser.c = function c( ...args ) { // consume
|
|
281
|
-
const symbol = this.la();
|
|
282
|
-
const result = CdlParser.prototype.c.apply( this, args );
|
|
283
|
-
if (result)
|
|
284
|
-
parseListener.visitTerminal( { symbol } );
|
|
285
|
-
return result;
|
|
286
|
-
};
|
|
287
|
-
parser.skipToken_ = function skipToken_( ...args ) { // skip token in error recovery
|
|
288
|
-
const symbol = this.la();
|
|
289
|
-
CdlParser.prototype.skipToken_.apply( this, args ); // = `++this.tokenIdx`
|
|
290
|
-
parseListener.visitErrorNode( { symbol } );
|
|
291
|
-
};
|
|
292
|
-
}
|
|
293
|
-
const result = {};
|
|
294
|
-
const rulespec = rules[rule];
|
|
295
|
-
if (rulespec) {
|
|
296
|
-
try {
|
|
297
|
-
parser[rulespec.func]( result );
|
|
298
|
-
}
|
|
299
|
-
catch (e) {
|
|
300
|
-
if (!(e instanceof RangeError && /Maximum.*exceeded$/i.test( e.message )))
|
|
301
|
-
throw e;
|
|
302
|
-
messageFunctions.error('syntax-invalid-source', { file: filename },
|
|
303
|
-
{ '#': 'cdl-stackoverflow' } );
|
|
304
|
-
result[rulespec.returns] = undefined;
|
|
305
|
-
}
|
|
306
|
-
}
|
|
307
|
-
const ast = result[rulespec?.returns] || (rule === 'cdl' ? new XsnSource( 'cdl' ) : {} );
|
|
308
|
-
ast.options = options;
|
|
309
|
-
if (attachTokens === true || attachTokens === filename)
|
|
310
|
-
ast.tokenStream = parser._input;
|
|
311
|
-
return ast;
|
|
312
|
-
}
|
|
313
|
-
|
|
314
205
|
module.exports = parse;
|
package/lib/main.js
CHANGED
|
@@ -1,19 +1,23 @@
|
|
|
1
|
-
// Main entry point for the CDS Compiler
|
|
1
|
+
// Main entry point for the CDS Compiler (API)
|
|
2
2
|
//
|
|
3
|
-
//
|
|
4
|
-
// require('cdsv');
|
|
3
|
+
// Other NPM modules must not require any other files than this one.
|
|
5
4
|
|
|
6
5
|
// Proposed intra-module lib dependencies:
|
|
7
6
|
// - lib/base/<file>.js: can be required by all others, requires no other
|
|
8
|
-
// of this project
|
|
7
|
+
// of this project, except a lib/base/<other-file>.js
|
|
8
|
+
// - lib/util/<file>.js: TODO - clarify diff to lib/base/
|
|
9
9
|
// - lib/<dir>/<file>.js: can be required by other files lib/<dir>/,
|
|
10
|
-
// can require other files lib/<dir>/ and lib/base/<file>.js
|
|
10
|
+
// can require other files in lib/<dir>/ and lib/base/<file>.js,
|
|
11
|
+
// and lib/<other-dir>/ (the index.js in <other-dir>).
|
|
11
12
|
// - lib/main.js (this file): can be required by none in lib/ (only in
|
|
12
13
|
// bin/ and test/), can require any other
|
|
13
14
|
|
|
14
15
|
'use strict';
|
|
15
16
|
|
|
17
|
+
const lazyload = require('./base/lazyload')( module );
|
|
18
|
+
|
|
16
19
|
const { traceApi } = require('./api/trace');
|
|
20
|
+
|
|
17
21
|
const snapi = lazyload('./api/main');
|
|
18
22
|
const csnUtils = lazyload('./model/csnUtils');
|
|
19
23
|
const model_api = lazyload('./model/api');
|
|
@@ -22,7 +26,7 @@ const sqlIdentifier = lazyload('./sql-identifier');
|
|
|
22
26
|
const keywords = lazyload( './base/keywords' );
|
|
23
27
|
const toCdl = lazyload('./render/toCdl');
|
|
24
28
|
|
|
25
|
-
const
|
|
29
|
+
const parsers = lazyload('./parsers');
|
|
26
30
|
const compiler = lazyload('./compiler');
|
|
27
31
|
const shared = lazyload('./compiler/shared');
|
|
28
32
|
const define = lazyload('./compiler/define');
|
|
@@ -43,8 +47,8 @@ function parseCdl( cdlSource, filename, options = {} ) {
|
|
|
43
47
|
const messageFunctions = messages.createMessageFunctions( options, 'parse', model );
|
|
44
48
|
model.$messageFunctions = messageFunctions;
|
|
45
49
|
|
|
46
|
-
const xsn =
|
|
47
|
-
|
|
50
|
+
const xsn = parsers.parseCdl( cdlSource, filename, Object.assign( { parseOnly: true }, options ),
|
|
51
|
+
messageFunctions );
|
|
48
52
|
sources[filename] = xsn;
|
|
49
53
|
shared.fns( model );
|
|
50
54
|
define( model );
|
|
@@ -55,16 +59,16 @@ function parseCdl( cdlSource, filename, options = {} ) {
|
|
|
55
59
|
|
|
56
60
|
function parseCql( cdlSource, filename = '<query>.cds', options = {} ) {
|
|
57
61
|
const messageFunctions = messages.createMessageFunctions( options, 'parse' );
|
|
58
|
-
const xsn =
|
|
59
|
-
|
|
62
|
+
const xsn = parsers.parseCdl( cdlSource, filename, Object.assign( { parseOnly: true }, options ),
|
|
63
|
+
messageFunctions, 'query' );
|
|
60
64
|
messageFunctions.throwWithError();
|
|
61
65
|
return toCsn.compactQuery( xsn );
|
|
62
66
|
}
|
|
63
67
|
|
|
64
68
|
function parseExpr( cdlSource, filename = '<expr>.cds', options = {} ) {
|
|
65
69
|
const messageFunctions = messages.createMessageFunctions( options, 'parse' );
|
|
66
|
-
const xsn =
|
|
67
|
-
|
|
70
|
+
const xsn = parsers.parseCdl( cdlSource, filename, Object.assign( { parseOnly: true }, options ),
|
|
71
|
+
messageFunctions, 'expr' );
|
|
68
72
|
messageFunctions.throwWithError();
|
|
69
73
|
return toCsn.compactExpr( xsn );
|
|
70
74
|
}
|
|
@@ -191,28 +195,3 @@ module.exports = {
|
|
|
191
195
|
isInReservedNamespace: (...args) => builtins.isInReservedNamespace(...args),
|
|
192
196
|
},
|
|
193
197
|
};
|
|
194
|
-
|
|
195
|
-
/**
|
|
196
|
-
* Load the module on-demand and not immediately.
|
|
197
|
-
*
|
|
198
|
-
* @param {string} moduleName Name of the module to load - like with require
|
|
199
|
-
* @returns {object} A Proxy that handles the on-demand loading
|
|
200
|
-
*/
|
|
201
|
-
function lazyload(moduleName) {
|
|
202
|
-
let module;
|
|
203
|
-
return new Proxy(((...args) => {
|
|
204
|
-
if (!module)
|
|
205
|
-
module = require(moduleName);
|
|
206
|
-
|
|
207
|
-
if (module.apply && typeof module.apply === 'function')
|
|
208
|
-
return module.apply(this, args);
|
|
209
|
-
return module; // for destructured calls
|
|
210
|
-
}), {
|
|
211
|
-
get(target, name) {
|
|
212
|
-
if (!module)
|
|
213
|
-
module = require(moduleName);
|
|
214
|
-
|
|
215
|
-
return module[name];
|
|
216
|
-
},
|
|
217
|
-
});
|
|
218
|
-
}
|
package/lib/model/cloneCsn.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
const { csnPropertyOrder } = require('../json/to-csn');
|
|
4
4
|
const { ModelError } = require('../base/error');
|
|
5
|
-
const { setHidden } = require('../utils/objectUtils');
|
|
5
|
+
const { setHidden, hasNonEnumerable } = require('../utils/objectUtils');
|
|
6
6
|
const { isAnnotationExpression } = require('../base/builtins');
|
|
7
7
|
|
|
8
8
|
const csnDictionaries = {
|
|
@@ -110,10 +110,6 @@ function cloneCsn( csn, options, sort ) {
|
|
|
110
110
|
return r;
|
|
111
111
|
}
|
|
112
112
|
|
|
113
|
-
function hasNonEnumerable( object, property ) {
|
|
114
|
-
return Object.prototype.hasOwnProperty.call( object, property ) &&
|
|
115
|
-
!Object.prototype.propertyIsEnumerable.call( object, property );
|
|
116
|
-
}
|
|
117
113
|
|
|
118
114
|
/**
|
|
119
115
|
* Deeply clone the given CSN dictionary and return it.
|
|
@@ -61,6 +61,7 @@ module.exports = {
|
|
|
61
61
|
function getFilterObject( options, dialect, extensionCallback, migrationCallback, removeConstraintsCallback, primaryKeyCallback ) {
|
|
62
62
|
const context = { hasLossyChanges: false };
|
|
63
63
|
const raiseErrorOrMarkAsLossy = getSafeguardManager(context, options);
|
|
64
|
+
const messageVariant = options.script ? 'script' : 'std';
|
|
64
65
|
return {
|
|
65
66
|
// will be called with a simple Array.filter, as we need to filter constraint `ADD` for SQLite
|
|
66
67
|
extension: ({
|
|
@@ -69,7 +70,7 @@ function getFilterObject( options, dialect, extensionCallback, migrationCallback
|
|
|
69
70
|
let returnValue = true;
|
|
70
71
|
forEach(elements, (name, element) => {
|
|
71
72
|
if (dialect !== 'sqlite' && isKey(element))
|
|
72
|
-
message('
|
|
73
|
+
message('migration-unsupported-key-change', [ 'definitions', extend, 'elements', name ], { id: name, '#': 'std' } );
|
|
73
74
|
else if (extensionCallback && !extensionCallback(extend, name, element, { error, warning }))
|
|
74
75
|
returnValue = false;
|
|
75
76
|
});
|
|
@@ -82,23 +83,31 @@ function getFilterObject( options, dialect, extensionCallback, migrationCallback
|
|
|
82
83
|
// will be called with a Array.forEach
|
|
83
84
|
migration: (migrations, { error, warning, message }) => {
|
|
84
85
|
forEach(migrations.remove, (name, migration) => {
|
|
85
|
-
raiseErrorOrMarkAsLossy(migration,
|
|
86
|
+
raiseErrorOrMarkAsLossy(name, migration, 'migration-unsupported-element-drop', id => message(id, [ 'definitions', migrations.migrate, 'elements', name ], { '#': messageVariant }));
|
|
86
87
|
});
|
|
87
88
|
|
|
88
89
|
forEach(migrations.change, (name, migration) => {
|
|
89
90
|
const loc = [ 'definitions', migrations.migrate, 'elements', name ];
|
|
90
|
-
if (migration.new.type === migration.old.type && migration.new.length < migration.old.length)
|
|
91
|
-
raiseErrorOrMarkAsLossy(migration,
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
else if (migration.new.type
|
|
97
|
-
raiseErrorOrMarkAsLossy(migration,
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
91
|
+
if (migration.new.type === migration.old.type && migration.new.length < migration.old.length) {
|
|
92
|
+
raiseErrorOrMarkAsLossy(name, migration, 'migration-unsupported-length-change', id => message(id, loc, { '#': messageVariant, id: name }));
|
|
93
|
+
}
|
|
94
|
+
else if (migration.new.type === migration.old.type && migration.new.scale !== migration.old.scale) {
|
|
95
|
+
raiseErrorOrMarkAsLossy(name, migration, 'migration-unsupported-scale-change', id => message(id, loc, { '#': messageVariant, id: name }));
|
|
96
|
+
}
|
|
97
|
+
else if (migration.new.type === migration.old.type && migration.new.precision !== migration.old.scale) {
|
|
98
|
+
raiseErrorOrMarkAsLossy(name, migration, 'migration-unsupported-precision-change', id => message(id, loc, { '#': messageVariant, id: name }));
|
|
99
|
+
}
|
|
100
|
+
else if (migration.new.type !== migration.old.type && typeChangeIsNotCompatible(dialect, migration.old.type, migration.new.type)) {
|
|
101
|
+
raiseErrorOrMarkAsLossy(name, migration, 'migration-unsupported-change', id => message(id, loc, {
|
|
102
|
+
'#': messageVariant, id: name, name: migration.old.type, type: migration.new.type,
|
|
103
|
+
}));
|
|
104
|
+
}
|
|
105
|
+
else if (dialect !== 'sqlite' && isKey(migration.new) && !isKey(migration.old)) { // key added/changed - pg, hana and sqlite do not support it, h2 probably also - issues when data is in the table already
|
|
106
|
+
raiseErrorOrMarkAsLossy(name, migration, 'migration-unsupported-key-change', id => message( id, [ 'definitions', migrations.migrate, 'elements', name ], { id: name, '#': 'changed' } ));
|
|
107
|
+
}
|
|
108
|
+
else if (migrationCallback) {
|
|
101
109
|
migrationCallback(migrations.migrate, name, migration, migrations.change, error);
|
|
110
|
+
}
|
|
102
111
|
|
|
103
112
|
if (options.script && migration.lossy && migrationCallback)
|
|
104
113
|
migrationCallback(migrations.migrate, name, migration, migrations.change, error);
|
|
@@ -115,9 +124,9 @@ function getFilterObject( options, dialect, extensionCallback, migrationCallback
|
|
|
115
124
|
});
|
|
116
125
|
}
|
|
117
126
|
},
|
|
118
|
-
deletion: ([ artifactName, artifact ],
|
|
127
|
+
deletion: ([ artifactName, artifact ], { message }) => {
|
|
119
128
|
if (isPersistedAsTable(artifact))
|
|
120
|
-
raiseErrorOrMarkAsLossy(artifact,
|
|
129
|
+
raiseErrorOrMarkAsLossy(artifactName, artifact, 'migration-unsupported-table-drop', id => message(id, [ 'definitions', artifactName ], { '#': messageVariant }));
|
|
121
130
|
},
|
|
122
131
|
changedPrimaryKeys: (changedPrimaryKeyArtifactName) => {
|
|
123
132
|
if (primaryKeyCallback)
|
|
@@ -191,13 +200,30 @@ function filterCsn( csn ) {
|
|
|
191
200
|
}
|
|
192
201
|
|
|
193
202
|
function getSafeguardManager( context, options ) {
|
|
194
|
-
return function raiseErrorOrMarkAsLossy(migration,
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
migration.lossy =
|
|
203
|
+
return function raiseErrorOrMarkAsLossy(name, migration, id, raiseMessage) {
|
|
204
|
+
raiseMessage(id);
|
|
205
|
+
|
|
206
|
+
if (options.script) {
|
|
207
|
+
migration.details = getDetails(id, name);
|
|
208
|
+
migration.lossy = id !== 'migration-unsupported-key-change';
|
|
200
209
|
context.hasLossyChanges = true;
|
|
201
210
|
}
|
|
202
211
|
};
|
|
203
212
|
}
|
|
213
|
+
|
|
214
|
+
const details = {
|
|
215
|
+
'migration-unsupported-element-drop': 'drop of element',
|
|
216
|
+
'migration-unsupported-length-change': 'length reduction of element',
|
|
217
|
+
'migration-unsupported-scale-change': 'scale reduction of element',
|
|
218
|
+
'migration-unsupported-precision-change': 'precision reduction of element',
|
|
219
|
+
'migration-unsupported-change': 'incompatible type change of element',
|
|
220
|
+
'migration-unsupported-key-change': 'key property change of element',
|
|
221
|
+
'migration-unsupported-table-drop': 'drop of entity',
|
|
222
|
+
};
|
|
223
|
+
|
|
224
|
+
function getDetails(id, name) {
|
|
225
|
+
if (details[id])
|
|
226
|
+
return `${details[id] } "${ name }" - check warnings for details`;
|
|
227
|
+
|
|
228
|
+
return null;
|
|
229
|
+
}
|