@sap/cds-compiler 2.13.8 → 3.0.0
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 +155 -1594
- package/bin/cdsc.js +144 -66
- package/doc/CHANGELOG_ARCHIVE.md +1592 -0
- package/doc/CHANGELOG_BETA.md +3 -4
- package/doc/CHANGELOG_DEPRECATED.md +35 -1
- package/doc/{DeprecatedOptions.md → DeprecatedOptions_v2.md} +3 -1
- package/doc/Versioning.md +20 -1
- package/lib/api/.eslintrc.json +2 -2
- package/lib/api/main.js +237 -122
- package/lib/api/options.js +17 -88
- package/lib/api/validate.js +12 -16
- package/lib/base/keywords.js +216 -109
- package/lib/base/message-registry.js +152 -37
- package/lib/base/messages.js +145 -83
- package/lib/base/model.js +44 -2
- package/lib/base/optionProcessorHelper.js +19 -0
- package/lib/checks/actionsFunctions.js +7 -5
- package/lib/checks/annotationsOData.js +11 -32
- package/lib/checks/arrayOfs.js +1 -34
- package/lib/checks/cdsPersistence.js +1 -0
- package/lib/checks/elements.js +6 -6
- package/lib/checks/invalidTarget.js +1 -1
- package/lib/checks/nonexpandableStructured.js +1 -1
- package/lib/checks/queryNoDbArtifacts.js +2 -1
- package/lib/checks/selectItems.js +5 -1
- package/lib/checks/types.js +4 -2
- package/lib/checks/utils.js +2 -2
- package/lib/checks/validator.js +4 -5
- package/lib/compiler/assert-consistency.js +16 -10
- package/lib/compiler/base.js +1 -0
- package/lib/compiler/builtins.js +98 -9
- package/lib/compiler/checks.js +22 -70
- package/lib/compiler/define.js +61 -13
- package/lib/compiler/extend.js +79 -14
- package/lib/compiler/finalize-parse-cdl.js +46 -29
- package/lib/compiler/index.js +100 -37
- package/lib/compiler/moduleLayers.js +7 -0
- package/lib/compiler/populate.js +19 -18
- package/lib/compiler/propagator.js +7 -4
- package/lib/compiler/resolve.js +297 -234
- package/lib/compiler/shared.js +107 -102
- package/lib/compiler/tweak-assocs.js +16 -11
- package/lib/compiler/utils.js +5 -0
- package/lib/edm/annotations/genericTranslation.js +93 -21
- package/lib/edm/csn2edm.js +230 -115
- package/lib/edm/edm.js +305 -226
- package/lib/edm/edmPreprocessor.js +509 -438
- package/lib/edm/edmUtils.js +31 -45
- package/lib/gen/Dictionary.json +98 -22
- package/lib/gen/language.checksum +1 -1
- package/lib/gen/language.interp +10 -30
- package/lib/gen/language.tokens +105 -114
- package/lib/gen/languageLexer.interp +1 -34
- package/lib/gen/languageLexer.js +889 -1007
- package/lib/gen/languageLexer.tokens +95 -106
- package/lib/gen/languageParser.js +20786 -22199
- package/lib/json/csnVersion.js +10 -11
- package/lib/json/from-csn.js +59 -51
- package/lib/json/to-csn.js +10 -10
- package/lib/language/antlrParser.js +2 -2
- package/lib/language/docCommentParser.js +62 -39
- package/lib/language/errorStrategy.js +52 -40
- package/lib/language/genericAntlrParser.js +348 -229
- package/lib/language/language.g4 +629 -653
- package/lib/language/multiLineStringParser.js +14 -42
- package/lib/language/textUtils.js +44 -0
- package/lib/main.d.ts +46 -43
- package/lib/main.js +108 -79
- package/lib/model/csnRefs.js +34 -7
- package/lib/model/csnUtils.js +337 -332
- package/lib/model/enrichCsn.js +1 -0
- package/lib/model/revealInternalProperties.js +30 -10
- package/lib/model/sortViews.js +32 -31
- package/lib/modelCompare/compare.js +6 -6
- package/lib/optionProcessor.js +73 -46
- package/lib/render/.eslintrc.json +1 -1
- package/lib/render/DuplicateChecker.js +4 -7
- package/lib/render/manageConstraints.js +70 -2
- package/lib/render/toCdl.js +1042 -882
- package/lib/render/toHdbcds.js +195 -245
- package/lib/render/toRename.js +44 -22
- package/lib/render/toSql.js +225 -241
- package/lib/render/utils/common.js +145 -15
- package/lib/render/utils/sql.js +20 -19
- package/lib/sql-identifier.js +6 -0
- package/lib/transform/db/.eslintrc.json +4 -3
- package/lib/transform/db/associations.js +2 -2
- package/lib/transform/db/cdsPersistence.js +5 -15
- package/lib/transform/db/constraints.js +4 -2
- package/lib/transform/db/expansion.js +22 -16
- package/lib/transform/db/flattening.js +109 -80
- package/lib/transform/db/transformExists.js +7 -7
- package/lib/transform/db/views.js +9 -6
- package/lib/transform/draft/.eslintrc.json +2 -2
- package/lib/transform/draft/db.js +6 -6
- package/lib/transform/draft/odata.js +6 -7
- package/lib/transform/forHanaNew.js +62 -48
- package/lib/transform/forOdataNew.js +49 -50
- package/lib/transform/localized.js +31 -20
- package/lib/transform/odata/toFinalBaseType.js +16 -14
- package/lib/transform/odata/typesExposure.js +146 -198
- package/lib/transform/odata/utils.js +1 -38
- package/lib/transform/transformUtilsNew.js +67 -84
- package/lib/transform/translateAssocsToJoins.js +7 -3
- package/lib/transform/universalCsn/.eslintrc.json +2 -2
- package/lib/transform/universalCsn/coreComputed.js +16 -9
- package/lib/transform/universalCsn/universalCsnEnricher.js +60 -10
- package/lib/utils/file.js +3 -3
- package/lib/utils/moduleResolve.js +13 -6
- package/lib/utils/timetrace.js +20 -21
- package/package.json +35 -4
- package/share/messages/message-explanations.json +2 -1
- package/share/messages/syntax-expected-integer.md +37 -0
- package/doc/ApiMigration.md +0 -237
- package/doc/CommandLineMigration.md +0 -58
- package/doc/ErrorMessages.md +0 -175
- package/doc/FioriAnnotations.md +0 -94
- package/doc/ODataTransformation.md +0 -273
- package/lib/backends.js +0 -529
- package/lib/fix_antlr4-8_warning.js +0 -56
- package/lib/transform/odata/attachPath.js +0 -96
- package/lib/transform/odata/expandStructKeysInAssociations.js +0 -59
- package/lib/transform/odata/generateForeignKeyElements.js +0 -261
- package/lib/transform/odata/referenceFlattener.js +0 -296
- package/lib/transform/odata/sortByAssociationDependency.js +0 -105
- package/lib/transform/odata/structuralPath.js +0 -72
- package/lib/transform/odata/structureFlattener.js +0 -171
package/lib/model/enrichCsn.js
CHANGED
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
const msg = require('../base/messages');
|
|
15
15
|
|
|
16
16
|
const $inferred = Symbol.for('cds.$inferred');
|
|
17
|
+
const $location = Symbol.for('cds.$location');
|
|
17
18
|
|
|
18
19
|
class NOT_A_DICTIONARY {} // used for consol.log display
|
|
19
20
|
|
|
@@ -36,7 +37,7 @@ const kindsRepresentedAsLinks = {
|
|
|
36
37
|
// represent table alias in from / join-args property as link:
|
|
37
38
|
$tableAlias: tableAliasAsLink,
|
|
38
39
|
// represent "navigation elemens" in _combined as links:
|
|
39
|
-
$navElement: (art, parent) => art._parent && parent !== art._parent.elements,
|
|
40
|
+
$navElement: (art, parent) => art._parent && parent !== art._parent.elements && art._parent.kind !== 'aspect',
|
|
40
41
|
// represent mixin in $tableAliases as link:
|
|
41
42
|
mixin: tableAliasAsLink,
|
|
42
43
|
// represent $projection as link, as it is just another search name for $self:
|
|
@@ -96,6 +97,7 @@ function revealInternalProperties( model, nameOrPath ) {
|
|
|
96
97
|
_annotate: reveal,
|
|
97
98
|
_deps: dependencyInfo,
|
|
98
99
|
_status: primOrString, // is a string anyway
|
|
100
|
+
$annotations: as => as.map( $annotation ),
|
|
99
101
|
$messageFunctions: () => '‹some functions›',
|
|
100
102
|
}
|
|
101
103
|
unique_id = 1;
|
|
@@ -129,7 +131,7 @@ function revealInternalProperties( model, nameOrPath ) {
|
|
|
129
131
|
|
|
130
132
|
path = path.split('/');
|
|
131
133
|
if (path.length === 1) {
|
|
132
|
-
return reveal( xsn.definitions[path] );
|
|
134
|
+
return reveal( xsn.definitions[path] || xsn.vocabularies && xsn.vocabularies[path] );
|
|
133
135
|
}
|
|
134
136
|
|
|
135
137
|
// with the code below, we might miss the right transformer function
|
|
@@ -149,7 +151,7 @@ function revealInternalProperties( model, nameOrPath ) {
|
|
|
149
151
|
|
|
150
152
|
function shortenName( node, parent ) {
|
|
151
153
|
const name = reveal( node, parent );
|
|
152
|
-
if (name && typeof name === 'object' && name.absolute) {
|
|
154
|
+
if (name && typeof name === 'object' && name.absolute && node.kind) {
|
|
153
155
|
const text = artifactIdentifier( parent );
|
|
154
156
|
delete name.absolute;
|
|
155
157
|
delete name.select;
|
|
@@ -178,11 +180,20 @@ function revealInternalProperties( model, nameOrPath ) {
|
|
|
178
180
|
return r;
|
|
179
181
|
}
|
|
180
182
|
|
|
183
|
+
function $annotation( anno ) { // property for cds-lsp
|
|
184
|
+
const { name, $flatten } = anno.value || anno;
|
|
185
|
+
const value = ($flatten)
|
|
186
|
+
? { name: reveal( name ), $flatten: $flatten.map( $annotation ) }
|
|
187
|
+
: `@${name?.absolute}`;
|
|
188
|
+
return { value, location: locationString( anno.location || anno.name.location ) };
|
|
189
|
+
}
|
|
190
|
+
|
|
181
191
|
function columns( nodes, query ) {
|
|
182
192
|
// If we will have specified elements, we need another test to see columns in --parse-cdl
|
|
183
|
-
return nodes &&
|
|
184
|
-
|
|
185
|
-
|
|
193
|
+
return nodes && array( nodes,
|
|
194
|
+
c => (c._parent && c._parent.elements)
|
|
195
|
+
? artifactIdentifier( c, query )
|
|
196
|
+
: reveal( c, nodes ) );
|
|
186
197
|
}
|
|
187
198
|
|
|
188
199
|
function elements( dict, parent ) {
|
|
@@ -215,7 +226,7 @@ function revealInternalProperties( model, nameOrPath ) {
|
|
|
215
226
|
if (!node || typeof node !== 'object')
|
|
216
227
|
return primOrString( node );
|
|
217
228
|
if (Array.isArray(node)) // with args
|
|
218
|
-
return
|
|
229
|
+
return array( node, reveal );
|
|
219
230
|
// Make unexpected prototype visible with node-10+:
|
|
220
231
|
const r = Object.create( Object.getPrototypeOf(node)
|
|
221
232
|
? NOT_A_DICTIONARY.prototype
|
|
@@ -225,6 +236,8 @@ function revealInternalProperties( model, nameOrPath ) {
|
|
|
225
236
|
}
|
|
226
237
|
if (node[$inferred] && !node['[$inferred]'])
|
|
227
238
|
r['[$inferred]'] = node[$inferred];
|
|
239
|
+
if (node[$location] && !node['[$location]'])
|
|
240
|
+
r['[$location]'] = locationString( node[$location] );
|
|
228
241
|
return r;
|
|
229
242
|
}
|
|
230
243
|
|
|
@@ -239,7 +252,7 @@ function revealInternalProperties( model, nameOrPath ) {
|
|
|
239
252
|
if (node == null || typeof node !== 'object' )
|
|
240
253
|
return primOrString( node );
|
|
241
254
|
if (Array.isArray(node))
|
|
242
|
-
return
|
|
255
|
+
return array( node, revealNonEnum );
|
|
243
256
|
|
|
244
257
|
if (Object.getPrototypeOf( node ))
|
|
245
258
|
return artifactIdentifier( node, parent );
|
|
@@ -250,7 +263,7 @@ function revealInternalProperties( model, nameOrPath ) {
|
|
|
250
263
|
if (node == null || typeof node !== 'object' )
|
|
251
264
|
return node
|
|
252
265
|
if (Array.isArray(node))
|
|
253
|
-
return
|
|
266
|
+
return array( node, n => reveal( n, node, name ) );
|
|
254
267
|
|
|
255
268
|
const asLinkTest = kindsRepresentedAsLinks[ node.kind ];
|
|
256
269
|
if (asLinkTest && asLinkTest( node, parent, name ))
|
|
@@ -280,6 +293,13 @@ function revealInternalProperties( model, nameOrPath ) {
|
|
|
280
293
|
}
|
|
281
294
|
}
|
|
282
295
|
|
|
296
|
+
function array( node, fn ) {
|
|
297
|
+
const r = node.map( n => fn( n, node ) );
|
|
298
|
+
if (node[$location])
|
|
299
|
+
r.push( { $location: locationString( node[$location] ) } );
|
|
300
|
+
return r;
|
|
301
|
+
}
|
|
302
|
+
|
|
283
303
|
function artifactIdentifier( node, parent ) {
|
|
284
304
|
if (Array.isArray(node))
|
|
285
305
|
return node.map( a => artifactIdentifier( a, node ) );
|
|
@@ -335,7 +355,7 @@ function primOrString( node ) {
|
|
|
335
355
|
if (node == null || typeof node !== 'object')
|
|
336
356
|
return node
|
|
337
357
|
if (Array.isArray(node))
|
|
338
|
-
return
|
|
358
|
+
return array( node, primOrString );
|
|
339
359
|
if (Object.getPrototypeOf( node ))
|
|
340
360
|
return '' + node;
|
|
341
361
|
else
|
package/lib/model/sortViews.js
CHANGED
|
@@ -21,7 +21,7 @@ const { ModelError } = require("../base/error");
|
|
|
21
21
|
*/
|
|
22
22
|
function sortTopologically(csn, _dependents, _dependencies){
|
|
23
23
|
const layers = [];
|
|
24
|
-
let { zero, nonZero } =
|
|
24
|
+
let { zero, nonZero } = _calculateDepth(Object.entries(csn.definitions), _dependents, _dependencies);
|
|
25
25
|
while (zero.length !== 0){
|
|
26
26
|
const currentLayer = [];
|
|
27
27
|
zero.forEach(([artifactName, artifact]) => {
|
|
@@ -34,46 +34,46 @@ function sortTopologically(csn, _dependents, _dependencies){
|
|
|
34
34
|
}
|
|
35
35
|
});
|
|
36
36
|
layers.push(currentLayer);
|
|
37
|
-
({zero, nonZero} =
|
|
37
|
+
({zero, nonZero} = _findWithXPointers(nonZero, 0, _dependents, _dependencies));
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
return { layers, leftover: nonZero };
|
|
41
|
+
}
|
|
41
42
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
43
|
+
function _calculateDepth(definitionsArray, _dependents, _dependencies) {
|
|
44
|
+
const zero = [];
|
|
45
|
+
const nonZero = [];
|
|
45
46
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
}
|
|
54
|
-
});
|
|
55
|
-
return {
|
|
56
|
-
zero,
|
|
57
|
-
nonZero
|
|
47
|
+
definitionsArray.forEach(([artifactName, artifact]) => {
|
|
48
|
+
if(artifact[_dependencies]) {
|
|
49
|
+
artifact.$pointers = artifact[_dependencies].size;
|
|
50
|
+
nonZero.push([artifactName, artifact]);
|
|
51
|
+
} else {
|
|
52
|
+
artifact.$pointers = 0;
|
|
53
|
+
zero.push([artifactName, artifact]);
|
|
58
54
|
}
|
|
55
|
+
});
|
|
56
|
+
return {
|
|
57
|
+
zero,
|
|
58
|
+
nonZero
|
|
59
59
|
}
|
|
60
|
+
}
|
|
60
61
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
definitionsArray.forEach(([artifactName, artifact]) => {
|
|
66
|
-
if(artifact.$pointers !== undefined && artifact.$pointers === x) {
|
|
67
|
-
zero.push([artifactName, artifact]);
|
|
68
|
-
} else {
|
|
69
|
-
nonZero.push([artifactName, artifact]);
|
|
70
|
-
}
|
|
71
|
-
});
|
|
62
|
+
function _findWithXPointers(definitionsArray, x, _dependents, _dependencies){
|
|
63
|
+
const zero = [];
|
|
64
|
+
const nonZero = [];
|
|
72
65
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
66
|
+
definitionsArray.forEach(([artifactName, artifact]) => {
|
|
67
|
+
if(artifact.$pointers !== undefined && artifact.$pointers === x) {
|
|
68
|
+
zero.push([artifactName, artifact]);
|
|
69
|
+
} else {
|
|
70
|
+
nonZero.push([artifactName, artifact]);
|
|
76
71
|
}
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
return {
|
|
75
|
+
zero,
|
|
76
|
+
nonZero
|
|
77
77
|
}
|
|
78
78
|
}
|
|
79
79
|
|
|
@@ -83,6 +83,7 @@ function sortTopologically(csn, _dependents, _dependencies){
|
|
|
83
83
|
* be run beforehand to resolve association usages.
|
|
84
84
|
*
|
|
85
85
|
* @param {object} sql Map of <object name>: "CREATE STATEMENT"
|
|
86
|
+
* @param {CSN.Model} csn
|
|
86
87
|
*
|
|
87
88
|
* @returns {{name: string, sql: string}[]} Sorted array of artifact name / "CREATE STATEMENTS" pairs
|
|
88
89
|
*
|
|
@@ -45,19 +45,19 @@ function validateCsnVersions(beforeModel, afterModel, options) {
|
|
|
45
45
|
let afterVersionParts = afterVersion && afterVersion.split('.');
|
|
46
46
|
|
|
47
47
|
if (!beforeVersionParts || beforeVersionParts.length < 2) {
|
|
48
|
-
const { error,
|
|
48
|
+
const { error, throwWithAnyError } = makeMessageFunction(beforeModel, options, 'modelCompare');
|
|
49
49
|
error(null, null, `Invalid CSN version: ${beforeVersion}`);
|
|
50
|
-
|
|
50
|
+
throwWithAnyError();
|
|
51
51
|
}
|
|
52
52
|
if (!afterVersionParts || afterVersionParts.length < 2) {
|
|
53
|
-
const { error,
|
|
53
|
+
const { error, throwWithAnyError } = makeMessageFunction(afterModel, options, 'modelCompare');
|
|
54
54
|
error(null, null, `Invalid CSN version: ${afterVersion}`);
|
|
55
|
-
|
|
55
|
+
throwWithAnyError();
|
|
56
56
|
}
|
|
57
57
|
if (beforeVersionParts[0] > afterVersionParts[0] && !(options && options.allowCsnDowngrade)) {
|
|
58
|
-
const { error,
|
|
58
|
+
const { error, throwWithAnyError } = makeMessageFunction(afterModel, options, 'modelCompare');
|
|
59
59
|
error(null, null, `Incompatible CSN versions: ${afterVersion} is a major downgrade from ${beforeVersion}. Is @sap/cds-compiler version ${require('../../package.json').version} outdated?`);
|
|
60
|
-
|
|
60
|
+
throwWithAnyError();
|
|
61
61
|
}
|
|
62
62
|
}
|
|
63
63
|
|
package/lib/optionProcessor.js
CHANGED
|
@@ -11,7 +11,9 @@ const optionProcessor = createOptionProcessor();
|
|
|
11
11
|
optionProcessor
|
|
12
12
|
.option('-h, --help')
|
|
13
13
|
.option('-v, --version')
|
|
14
|
+
.option(' --options <file>')
|
|
14
15
|
.option('-w, --warning <level>', ['0', '1', '2', '3'])
|
|
16
|
+
.option(' --quiet')
|
|
15
17
|
.option(' --show-message-id')
|
|
16
18
|
.option(' --no-message-context')
|
|
17
19
|
.option(' --color <mode>', ['auto', 'always', 'never'])
|
|
@@ -22,18 +24,16 @@ optionProcessor
|
|
|
22
24
|
.option(' --trace-parser')
|
|
23
25
|
.option(' --trace-parser-amb')
|
|
24
26
|
.option(' --trace-fs')
|
|
27
|
+
.option(' --error <id-list>')
|
|
28
|
+
.option(' --warn <id-list>')
|
|
29
|
+
.option(' --info <id-list>')
|
|
30
|
+
.option(' --debug <id-list>')
|
|
25
31
|
.option('-E, --enrich-csn')
|
|
26
32
|
.option('-R, --raw-output <name>')
|
|
27
33
|
.option(' --internal-msg')
|
|
28
34
|
.option(' --beta-mode')
|
|
29
35
|
.option(' --beta <list>')
|
|
30
|
-
.option(' --integrity-not-validated')
|
|
31
|
-
.option(' --integrity-not-enforced')
|
|
32
|
-
.option(' --assert-integrity <mode>', [ 'true', 'false', 'individual' ])
|
|
33
|
-
.option(' --assert-integrity-type <type>', [ 'RT', 'DB' ], { ignoreCase: true })
|
|
34
|
-
.option(' --constraints-in-create-table')
|
|
35
36
|
.option(' --deprecated <list>')
|
|
36
|
-
.option(' --hana-flavor')
|
|
37
37
|
.option(' --direct-backend')
|
|
38
38
|
.option(' --parse-only')
|
|
39
39
|
.option(' --fallback-parser <type>', ['cdl', 'csn', 'csn!'])
|
|
@@ -59,17 +59,21 @@ optionProcessor
|
|
|
59
59
|
General options
|
|
60
60
|
-h, --help Show this help text
|
|
61
61
|
-v, --version Display version number and exit
|
|
62
|
+
--quiet Don't emit anything, neither results nor messages.
|
|
62
63
|
-w, --warning <level> Show messages up to <level>
|
|
63
64
|
0: Error
|
|
64
65
|
1: Warnings
|
|
65
66
|
2: (default) Info
|
|
66
67
|
3: Debug
|
|
68
|
+
--options <file> Use the given JSON file as input options.
|
|
69
|
+
The key 'cdsc' of 'cds' is used. If not present 'cdsc' is used.
|
|
70
|
+
Otherwise, the JSON as-is is used as options.
|
|
67
71
|
--show-message-id Show message ID in error, warning and info messages
|
|
68
72
|
--no-message-context Print messages as single lines without code context (useful for
|
|
69
|
-
redirecting output to other processes). Default is to print human
|
|
73
|
+
redirecting output to other processes). Default is to print human-
|
|
70
74
|
readable text similar to Rust's compiler with a code excerpt.
|
|
71
75
|
--color <mode> Use colors for warnings. Modes are:
|
|
72
|
-
auto: (default) Detect color support of the
|
|
76
|
+
auto: (default) Detect color support of the TTY.
|
|
73
77
|
always:
|
|
74
78
|
never:
|
|
75
79
|
-o, --out <dir> Place generated files in directory <dir>, default is "-" for <stdout>
|
|
@@ -87,6 +91,13 @@ optionProcessor
|
|
|
87
91
|
--trace-parser-amb Trace parser ambiguities
|
|
88
92
|
--trace-fs Trace file system access caused by "using from"
|
|
89
93
|
|
|
94
|
+
Severity options
|
|
95
|
+
Use these options to reclassify messages. Option argument is a comma separated list of message IDs.
|
|
96
|
+
--error <id-list> IDs that should be reclassified to errors.
|
|
97
|
+
--warn <id-list> IDs that should be reclassified to warnings.
|
|
98
|
+
--info <id-list> IDs that should be reclassified to info messages.
|
|
99
|
+
--debug <id-list> IDs that should be reclassified to debug messages.
|
|
100
|
+
|
|
90
101
|
Internal options (for testing only, may be changed/removed at any time)
|
|
91
102
|
-E, --enrich-csn Show non-enumerable CSN properties and locations of references
|
|
92
103
|
-R, --raw-output <name> Write XSN for definition "name" and error output to <stdout>,
|
|
@@ -95,37 +106,12 @@ optionProcessor
|
|
|
95
106
|
--beta-mode Enable all unsupported, incomplete (beta) features
|
|
96
107
|
--beta <list> Comma separated list of unsupported, incomplete (beta) features to use.
|
|
97
108
|
Valid values are:
|
|
98
|
-
addTextsLanguageAssoc
|
|
99
109
|
hanaAssocRealCardinality
|
|
100
110
|
mapAssocToJoinCardinality
|
|
101
111
|
ignoreAssocPublishingInUnion
|
|
102
|
-
--integrity-not-enforced If this option is supplied, referential constraints are NOT ENFORCED.
|
|
103
|
-
This option is also applied to result of "cdsc manageConstraints"
|
|
104
|
-
--integrity-not-validated If this option is supplied, referential constraints are NOT VALIDATED.
|
|
105
|
-
This option is also applied to result of "cdsc manageConstraints"
|
|
106
|
-
--assert-integrity <mode> Turn DB constraints on/off:
|
|
107
|
-
true : (default) Constraints will be generated for all associations if
|
|
108
|
-
the assert-integrity-type is set to DB
|
|
109
|
-
false : No constraints will be generated
|
|
110
|
-
individual : Constraints will be generated for selected associations
|
|
111
|
-
--assert-integrity-type <type> Specifies how the referential integrity checks should be performed:
|
|
112
|
-
RT : (default) No database constraint for an association
|
|
113
|
-
if not explicitly demanded via annotation
|
|
114
|
-
DB : Create database constraints for associations
|
|
115
|
-
--constraints-in-create-table If set, the foreign key constraints will be rendered as
|
|
116
|
-
part of the "CREATE TABLE" statements rather than as separate
|
|
117
|
-
"ALTER TABLE ADD CONSTRAINT" statements
|
|
118
112
|
--deprecated <list> Comma separated list of deprecated options.
|
|
119
113
|
Valid values are:
|
|
120
|
-
|
|
121
|
-
v1KeysForTemporal
|
|
122
|
-
parensAsStrings
|
|
123
|
-
projectionAsQuery
|
|
124
|
-
renderVirtualElements
|
|
125
|
-
unmanagedUpInComponent
|
|
126
|
-
createLocalizedViews
|
|
127
|
-
redirectInSubQueries
|
|
128
|
-
--hana-flavor Compile with backward compatibility for HANA CDS (incomplete)
|
|
114
|
+
eagerPersistenceForGeneratedEntities
|
|
129
115
|
--parse-only Stop compilation after parsing and write result to <stdout>
|
|
130
116
|
--fallback-parser <type> If the language cannot be deduced by the file's extensions, use this
|
|
131
117
|
parser as a fallback. Valid values are:
|
|
@@ -169,6 +155,10 @@ optionProcessor.command('H, toHana')
|
|
|
169
155
|
.option('-u, --user <user>')
|
|
170
156
|
.option('-s, --src')
|
|
171
157
|
.option('-c, --csn')
|
|
158
|
+
.option(' --integrity-not-validated')
|
|
159
|
+
.option(' --integrity-not-enforced')
|
|
160
|
+
.option(' --assert-integrity <mode>', ['true', 'false', 'individual'])
|
|
161
|
+
.option(' --assert-integrity-type <type>', ['RT', 'DB'], { ignoreCase: true })
|
|
172
162
|
.help(`
|
|
173
163
|
Usage: cdsc toHana [options] <files...>
|
|
174
164
|
|
|
@@ -192,11 +182,22 @@ optionProcessor.command('H, toHana')
|
|
|
192
182
|
-u, --user <user> Value for the "$user" variable
|
|
193
183
|
-s, --src (default) Generate HANA CDS source files "<artifact>.hdbcds"
|
|
194
184
|
-c, --csn Generate "hana_csn.json" with HANA-preprocessed model
|
|
185
|
+
--integrity-not-enforced If this option is supplied, referential constraints are NOT ENFORCED.
|
|
186
|
+
--integrity-not-validated If this option is supplied, referential constraints are NOT VALIDATED.
|
|
187
|
+
--assert-integrity <mode> Turn DB constraints on/off:
|
|
188
|
+
true : (default) Constraints will be generated for all associations if
|
|
189
|
+
the assert-integrity-type is set to DB
|
|
190
|
+
false : No constraints will be generated
|
|
191
|
+
individual : Constraints will be generated for selected associations
|
|
192
|
+
--assert-integrity-type <type> Specifies how the referential integrity checks should be performed:
|
|
193
|
+
RT : (default) No database constraint for an association
|
|
194
|
+
if not explicitly demanded via annotation
|
|
195
|
+
DB : Create database constraints for associations
|
|
195
196
|
`);
|
|
196
197
|
|
|
197
198
|
optionProcessor.command('O, toOdata')
|
|
198
199
|
.option('-h, --help')
|
|
199
|
-
.option('-v, --version <version>', ['v2', 'v4', 'v4x'])
|
|
200
|
+
.option('-v, --odata-version <version>', ['v2', 'v4', 'v4x'])
|
|
200
201
|
.option('-x, --xml')
|
|
201
202
|
.option('-j, --json')
|
|
202
203
|
.option(' --odata-containment')
|
|
@@ -207,6 +208,7 @@ optionProcessor.command('O, toOdata')
|
|
|
207
208
|
.option('-c, --csn')
|
|
208
209
|
.option('-f, --odata-format <format>', ['flat', 'structured'])
|
|
209
210
|
.option('-n, --names <style>', ['plain', 'quoted', 'hdbcds'])
|
|
211
|
+
.option('-s, --service-names <list>')
|
|
210
212
|
.help(`
|
|
211
213
|
Usage: cdsc toOdata [options] <files...>
|
|
212
214
|
|
|
@@ -214,10 +216,10 @@ optionProcessor.command('O, toOdata')
|
|
|
214
216
|
|
|
215
217
|
Options
|
|
216
218
|
-h, --help Show this help text
|
|
217
|
-
-v, --version <version> ODATA version
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
219
|
+
-v, --odata-version <version> ODATA version
|
|
220
|
+
v2: ODATA V2
|
|
221
|
+
v4: (default) ODATA V4
|
|
222
|
+
v4x: { version: 'v4', odataContainment:true, format:'structured' }
|
|
221
223
|
-x, --xml (default) Generate XML output (separate or combined)
|
|
222
224
|
-j, --json Generate JSON output as "<svc>.json" (not available for v2)
|
|
223
225
|
-c, --csn Generate "odata_csn.json" with ODATA-preprocessed model
|
|
@@ -237,6 +239,8 @@ optionProcessor.command('O, toOdata')
|
|
|
237
239
|
but element names flattened with underscores
|
|
238
240
|
hdbcds : Names as HANA CDS would generate them from the same CDS
|
|
239
241
|
source (like "quoted", but using element names with dots)
|
|
242
|
+
-s, --service-names <list> List of comma-separated service names to be rendered
|
|
243
|
+
(default) empty, all services are rendered
|
|
240
244
|
`);
|
|
241
245
|
|
|
242
246
|
optionProcessor.command('C, toCdl')
|
|
@@ -255,11 +259,16 @@ optionProcessor.command('Q, toSql')
|
|
|
255
259
|
.option('-n, --names <style>', ['plain', 'quoted', 'hdbcds'])
|
|
256
260
|
.option(' --render-virtual')
|
|
257
261
|
.option(' --joinfk')
|
|
258
|
-
.option('-d, --dialect <dialect>', ['hana', 'sqlite', 'plain'])
|
|
262
|
+
.option('-d, --dialect <dialect>', ['hana', 'sqlite', 'plain', 'postgres'])
|
|
259
263
|
.option('-u, --user <user>')
|
|
260
264
|
.option('-l, --locale <locale>')
|
|
261
265
|
.option('-s, --src <style>', ['sql', 'hdi'])
|
|
262
266
|
.option('-c, --csn')
|
|
267
|
+
.option(' --integrity-not-validated')
|
|
268
|
+
.option(' --integrity-not-enforced')
|
|
269
|
+
.option(' --assert-integrity <mode>', ['true', 'false', 'individual'])
|
|
270
|
+
.option(' --assert-integrity-type <type>', ['RT', 'DB'], { ignoreCase: true })
|
|
271
|
+
.option(' --constraints-in-create-table')
|
|
263
272
|
.help(`
|
|
264
273
|
Usage: cdsc toSql [options] <files...>
|
|
265
274
|
|
|
@@ -281,9 +290,10 @@ optionProcessor.command('Q, toSql')
|
|
|
281
290
|
--render-virtual Render virtual elements in views and draft tables
|
|
282
291
|
--joinfk Create JOINs for foreign key accesses
|
|
283
292
|
-d, --dialect <dialect> SQL dialect to be generated:
|
|
284
|
-
plain
|
|
285
|
-
hana
|
|
286
|
-
sqlite
|
|
293
|
+
plain : (default) Common SQL - no assumptions about DB restrictions
|
|
294
|
+
hana : SQL with HANA specific language features
|
|
295
|
+
sqlite : Common SQL for sqlite
|
|
296
|
+
postgres : Common SQL for postgres - beta-feature
|
|
287
297
|
-u, --user <user> Value for the "$user" variable
|
|
288
298
|
-l, --locale <locale> Value for the "$user.locale" variable in "sqlite"/"plain" dialect
|
|
289
299
|
-s, --src <style> Generate SQL source files as <artifact>.<suffix>
|
|
@@ -292,6 +302,20 @@ optionProcessor.command('Q, toSql')
|
|
|
292
302
|
the HDI plugin name. Can only be used in combination with
|
|
293
303
|
"hana" dialect.
|
|
294
304
|
-c, --csn Generate "sql_csn.json" with SQL-preprocessed model
|
|
305
|
+
--integrity-not-enforced If this option is supplied, referential constraints are NOT ENFORCED.
|
|
306
|
+
--integrity-not-validated If this option is supplied, referential constraints are NOT VALIDATED.
|
|
307
|
+
--assert-integrity <mode> Turn DB constraints on/off:
|
|
308
|
+
true : (default) Constraints will be generated for all associations if
|
|
309
|
+
the assert-integrity-type is set to DB
|
|
310
|
+
false : No constraints will be generated
|
|
311
|
+
individual : Constraints will be generated for selected associations
|
|
312
|
+
--assert-integrity-type <type> Specifies how the referential integrity checks should be performed:
|
|
313
|
+
RT : (default) No database constraint for an association
|
|
314
|
+
if not explicitly demanded via annotation
|
|
315
|
+
DB : Create database constraints for associations
|
|
316
|
+
--constraints-in-create-table If set, the foreign key constraints will be rendered as
|
|
317
|
+
part of the "CREATE TABLE" statements rather than as separate
|
|
318
|
+
"ALTER TABLE ADD CONSTRAINT" statements
|
|
295
319
|
`);
|
|
296
320
|
|
|
297
321
|
optionProcessor.command('toRename')
|
|
@@ -322,13 +346,14 @@ optionProcessor.command('manageConstraints')
|
|
|
322
346
|
.option(' --drop')
|
|
323
347
|
.option(' --alter')
|
|
324
348
|
.option(' --violations')
|
|
349
|
+
.option(' --integrity-not-validated')
|
|
350
|
+
.option(' --integrity-not-enforced')
|
|
325
351
|
.help(`
|
|
326
352
|
Usage: cdsc manageConstraints [options] <files...>
|
|
327
353
|
|
|
328
354
|
(internal, subject to change): Generate SQL DDL ALTER TABLE statements to add / modify
|
|
329
|
-
referential constraints on an existing model.
|
|
330
|
-
|
|
331
|
-
to switch off foreign key constraint enforcement / validation.
|
|
355
|
+
referential constraints on an existing model. This can also be used to
|
|
356
|
+
generate SELECT statements which list all referential integrity violations.
|
|
332
357
|
|
|
333
358
|
Options
|
|
334
359
|
-h, --help Display this help text
|
|
@@ -348,6 +373,8 @@ optionProcessor.command('manageConstraints')
|
|
|
348
373
|
--alter Generate "ALTER TABLE <table> ALTER CONSTRAINT <constraint>" statements
|
|
349
374
|
--violations Generates SELECT statements which can be used to list
|
|
350
375
|
referential integrity violations on the existing data
|
|
376
|
+
--integrity-not-enforced If this option is supplied, referential constraints are NOT ENFORCED.
|
|
377
|
+
--integrity-not-validated If this option is supplied, referential constraints are NOT VALIDATED.
|
|
351
378
|
`);
|
|
352
379
|
|
|
353
380
|
optionProcessor.command('toCsn')
|
|
@@ -2,12 +2,14 @@
|
|
|
2
2
|
* Usage: Create an instance to process artifacts which should be checked for collision.
|
|
3
3
|
* First call addArtifact to specify the current artifact,
|
|
4
4
|
* then call addElement to register the elements of the current artifact.
|
|
5
|
-
* Finally call the "done" function to check for duplicates.
|
|
6
|
-
* In addition the internal structures will be reinitialized to enable reuse of the instance.
|
|
5
|
+
* Finally, call the "done" function to check for duplicates.
|
|
6
|
+
* In addition, the internal structures will be reinitialized to enable reuse of the instance.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
'use strict';
|
|
10
10
|
|
|
11
|
+
const { forEach } = require('../utils/objectUtils');
|
|
12
|
+
|
|
11
13
|
/**
|
|
12
14
|
* database name - uppercase if not quoted
|
|
13
15
|
*
|
|
@@ -121,9 +123,4 @@ class DuplicateChecker {
|
|
|
121
123
|
}
|
|
122
124
|
}
|
|
123
125
|
|
|
124
|
-
function forEach(obj, callback) {
|
|
125
|
-
for (const key in obj)
|
|
126
|
-
callback(key, obj[key]);
|
|
127
|
-
}
|
|
128
|
-
|
|
129
126
|
module.exports = DuplicateChecker;
|
|
@@ -6,11 +6,78 @@ const {
|
|
|
6
6
|
getResultingName,
|
|
7
7
|
} = require('../model/csnUtils');
|
|
8
8
|
const { forEach } = require('../utils/objectUtils');
|
|
9
|
+
const { makeMessageFunction } = require('../base/messages');
|
|
10
|
+
const { optionProcessor } = require('../optionProcessor');
|
|
11
|
+
const { transformForHanaWithCsn } = require('../transform/forHanaNew');
|
|
9
12
|
|
|
10
13
|
const {
|
|
11
14
|
renderReferentialConstraint, getIdentifierUtils,
|
|
12
15
|
} = require('./utils/sql');
|
|
13
16
|
|
|
17
|
+
/**
|
|
18
|
+
* Used only by `cdsc manageConstraints`.
|
|
19
|
+
* Not part of our API, yet.
|
|
20
|
+
*
|
|
21
|
+
* @param {CSN.Model} csn
|
|
22
|
+
* @param {CSN.Options} options
|
|
23
|
+
*/
|
|
24
|
+
function alterConstraintsWithCsn(csn, options) {
|
|
25
|
+
const { error } = makeMessageFunction(csn, options, 'manageConstraints');
|
|
26
|
+
|
|
27
|
+
const {
|
|
28
|
+
drop, alter, names, src, violations,
|
|
29
|
+
} = options.manageConstraints || {};
|
|
30
|
+
|
|
31
|
+
if (drop && alter)
|
|
32
|
+
error(null, null, 'Option “--drop” can\'t be combined with “--alter”');
|
|
33
|
+
|
|
34
|
+
options.sqlDialect = 'hana';
|
|
35
|
+
options.sqlMapping = names || 'plain';
|
|
36
|
+
|
|
37
|
+
// Of course we want the database constraints
|
|
38
|
+
options.assertIntegrityType = 'DB';
|
|
39
|
+
|
|
40
|
+
const transformedOptions = _transformSqlOptions(csn, options);
|
|
41
|
+
const forSqlCsn = transformForHanaWithCsn(csn, transformedOptions, 'to.sql');
|
|
42
|
+
|
|
43
|
+
if (violations && src && src !== 'sql')
|
|
44
|
+
error(null, null, `Option “--violations“ can't be combined with source style “${src}“`);
|
|
45
|
+
|
|
46
|
+
let intermediateResult;
|
|
47
|
+
if (violations)
|
|
48
|
+
intermediateResult = listReferentialIntegrityViolations(forSqlCsn, transformedOptions);
|
|
49
|
+
else
|
|
50
|
+
intermediateResult = manageConstraints(forSqlCsn, transformedOptions);
|
|
51
|
+
|
|
52
|
+
return intermediateResult;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function _transformSqlOptions(model, options) {
|
|
56
|
+
// Merge options with defaults.
|
|
57
|
+
options = Object.assign({ sqlMapping: 'plain', sqlDialect: 'plain' }, options);
|
|
58
|
+
options.toSql = true;
|
|
59
|
+
|
|
60
|
+
if (!options.src && !options.csn)
|
|
61
|
+
options.src = 'sql';
|
|
62
|
+
|
|
63
|
+
const { warning, error } = makeMessageFunction(model, options, 'to.sql');
|
|
64
|
+
|
|
65
|
+
optionProcessor.verifyOptions(options, 'toSql', true)
|
|
66
|
+
.forEach(complaint => warning(null, null, `${complaint}`));
|
|
67
|
+
|
|
68
|
+
if (options.sqlDialect !== 'hana') {
|
|
69
|
+
// CDXCORE-465, 'quoted' and 'hdbcds' are to be used in combination with dialect 'hana' only
|
|
70
|
+
if (options.sqlMapping === 'quoted' || options.sqlMapping === 'hdbcds')
|
|
71
|
+
error(null, null, `Option "{ sqlDialect: '${options.sqlDialect}' }" can't be combined with "{ sqlMapping: '${options.sqlMapping}' }"`);
|
|
72
|
+
|
|
73
|
+
// No non-HANA SQL for HDI
|
|
74
|
+
if (options.src === 'hdi')
|
|
75
|
+
error(null, null, `Option "{ sqlDialect: '${options.sqlDialect}' }" can't be used for HDI"`);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return options;
|
|
79
|
+
}
|
|
80
|
+
|
|
14
81
|
/**
|
|
15
82
|
* This render middleware can be used to generate SQL DDL ALTER TABLE <table> ALTER / ADD / DROP CONSTRAINT <constraint> statements for a given CDL model.
|
|
16
83
|
* Moreover, it can be used to generate .hdbconstraint artifacts.
|
|
@@ -38,7 +105,7 @@ function manageConstraints(csn, options) {
|
|
|
38
105
|
return;
|
|
39
106
|
}
|
|
40
107
|
let alterTableStatement = '';
|
|
41
|
-
alterTableStatement += `${indent}ALTER TABLE ${quoteSqlId(getResultingName(csn, options.
|
|
108
|
+
alterTableStatement += `${indent}ALTER TABLE ${quoteSqlId(getResultingName(csn, options.sqlMapping, constraint.dependentTable))}`;
|
|
42
109
|
if (renderAlterConstraintStatement)
|
|
43
110
|
alterTableStatement += `\n${indent}ALTER ${renderedConstraint};`;
|
|
44
111
|
else if (drop)
|
|
@@ -172,7 +239,7 @@ function listReferentialIntegrityViolations(csn, options) {
|
|
|
172
239
|
}
|
|
173
240
|
|
|
174
241
|
function quoteAndGetResultingName(id) {
|
|
175
|
-
return quoteSqlId(getResultingName(csn, options.
|
|
242
|
+
return quoteSqlId(getResultingName(csn, options.sqlMapping, id));
|
|
176
243
|
}
|
|
177
244
|
|
|
178
245
|
return resultArtifacts;
|
|
@@ -192,6 +259,7 @@ function getListOfAllConstraints(csn) {
|
|
|
192
259
|
}
|
|
193
260
|
|
|
194
261
|
module.exports = {
|
|
262
|
+
alterConstraintsWithCsn,
|
|
195
263
|
manageConstraints,
|
|
196
264
|
listReferentialIntegrityViolations,
|
|
197
265
|
};
|