@sap/cds-compiler 2.15.2 → 3.0.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 +66 -1590
- package/bin/cdsc.js +42 -46
- 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 +312 -143
- package/lib/api/options.js +15 -85
- package/lib/api/validate.js +6 -10
- package/lib/base/keywords.js +280 -110
- package/lib/base/message-registry.js +80 -24
- package/lib/base/messages.js +103 -52
- package/lib/base/model.js +44 -2
- package/lib/base/optionProcessorHelper.js +53 -21
- package/lib/checks/actionsFunctions.js +7 -5
- package/lib/checks/annotationsOData.js +1 -1
- 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 +2 -1
- package/lib/compiler/assert-consistency.js +15 -10
- package/lib/compiler/builtins.js +127 -10
- package/lib/compiler/define.js +6 -4
- package/lib/compiler/extend.js +63 -12
- package/lib/compiler/finalize-parse-cdl.js +20 -9
- package/lib/compiler/index.js +25 -11
- package/lib/compiler/moduleLayers.js +7 -0
- package/lib/compiler/populate.js +16 -14
- package/lib/compiler/propagator.js +3 -3
- package/lib/compiler/resolve.js +194 -222
- package/lib/compiler/shared.js +56 -76
- package/lib/compiler/tweak-assocs.js +9 -10
- package/lib/compiler/utils.js +7 -2
- package/lib/edm/annotations/genericTranslation.js +60 -6
- package/lib/edm/annotations/preprocessAnnotations.js +10 -11
- package/lib/edm/csn2edm.js +39 -41
- package/lib/edm/edm.js +22 -15
- package/lib/edm/edmPreprocessor.js +66 -69
- package/lib/edm/edmUtils.js +12 -62
- package/lib/gen/Dictionary.json +8 -6
- package/lib/gen/language.checksum +1 -1
- package/lib/gen/language.interp +8 -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 +20717 -22376
- package/lib/json/from-csn.js +73 -68
- package/lib/json/to-csn.js +13 -10
- package/lib/language/antlrParser.js +2 -2
- package/lib/language/docCommentParser.js +61 -38
- package/lib/language/errorStrategy.js +52 -40
- package/lib/language/genericAntlrParser.js +333 -259
- package/lib/language/language.g4 +600 -645
- package/lib/language/multiLineStringParser.js +14 -42
- package/lib/language/textUtils.js +44 -0
- package/lib/main.d.ts +27 -42
- package/lib/main.js +104 -81
- package/lib/model/csnRefs.js +2 -1
- package/lib/model/csnUtils.js +183 -285
- package/lib/model/revealInternalProperties.js +32 -9
- package/lib/model/sortViews.js +32 -31
- package/lib/optionProcessor.js +64 -57
- 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 +334 -339
- package/lib/render/toHdbcds.js +20 -16
- package/lib/render/toRename.js +44 -22
- package/lib/render/toSql.js +60 -54
- package/lib/render/utils/common.js +15 -1
- package/lib/render/utils/sql.js +20 -19
- package/lib/sql-identifier.js +6 -0
- package/lib/transform/db/.eslintrc.json +3 -2
- package/lib/transform/db/cdsPersistence.js +5 -15
- package/lib/transform/db/constraints.js +1 -1
- package/lib/transform/db/expansion.js +7 -6
- package/lib/transform/db/flattening.js +18 -19
- package/lib/transform/db/views.js +3 -3
- 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 +19 -22
- package/lib/transform/forOdataNew.js +13 -15
- package/lib/transform/localized.js +35 -25
- package/lib/transform/odata/toFinalBaseType.js +11 -9
- package/lib/transform/odata/typesExposure.js +3 -3
- package/lib/transform/odata/utils.js +1 -38
- package/lib/transform/transformUtilsNew.js +63 -77
- package/lib/transform/translateAssocsToJoins.js +6 -2
- package/lib/transform/universalCsn/.eslintrc.json +2 -2
- package/lib/transform/universalCsn/coreComputed.js +11 -6
- package/lib/transform/universalCsn/universalCsnEnricher.js +33 -5
- package/lib/utils/file.js +31 -21
- package/lib/utils/timetrace.js +20 -21
- package/package.json +34 -4
- package/share/messages/syntax-expected-integer.md +9 -8
- 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
|
@@ -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
|
|
|
@@ -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,10 @@ function revealInternalProperties( model, nameOrPath ) {
|
|
|
129
131
|
|
|
130
132
|
path = path.split('/');
|
|
131
133
|
if (path.length === 1) {
|
|
132
|
-
|
|
134
|
+
const def = xsn.definitions?.[path[0]] || xsn.vocabularies?.[path[0]];
|
|
135
|
+
if (!def)
|
|
136
|
+
throw new Error(`reveal xsn: Unknown definition: “${path[0]}”`)
|
|
137
|
+
return reveal( def );
|
|
133
138
|
}
|
|
134
139
|
|
|
135
140
|
// with the code below, we might miss the right transformer function
|
|
@@ -149,7 +154,7 @@ function revealInternalProperties( model, nameOrPath ) {
|
|
|
149
154
|
|
|
150
155
|
function shortenName( node, parent ) {
|
|
151
156
|
const name = reveal( node, parent );
|
|
152
|
-
if (name && typeof name === 'object' && name.absolute) {
|
|
157
|
+
if (name && typeof name === 'object' && name.absolute && node.kind) {
|
|
153
158
|
const text = artifactIdentifier( parent );
|
|
154
159
|
delete name.absolute;
|
|
155
160
|
delete name.select;
|
|
@@ -178,11 +183,20 @@ function revealInternalProperties( model, nameOrPath ) {
|
|
|
178
183
|
return r;
|
|
179
184
|
}
|
|
180
185
|
|
|
186
|
+
function $annotation( anno ) { // property for cds-lsp
|
|
187
|
+
const { name, $flatten } = anno.value || anno;
|
|
188
|
+
const value = ($flatten)
|
|
189
|
+
? { name: reveal( name ), $flatten: $flatten.map( $annotation ) }
|
|
190
|
+
: `@${name?.absolute}`;
|
|
191
|
+
return { value, location: locationString( anno.location || anno.name.location ) };
|
|
192
|
+
}
|
|
193
|
+
|
|
181
194
|
function columns( nodes, query ) {
|
|
182
195
|
// If we will have specified elements, we need another test to see columns in --parse-cdl
|
|
183
|
-
return nodes &&
|
|
184
|
-
|
|
185
|
-
|
|
196
|
+
return nodes && array( nodes,
|
|
197
|
+
c => (c._parent && c._parent.elements)
|
|
198
|
+
? artifactIdentifier( c, query )
|
|
199
|
+
: reveal( c, nodes ) );
|
|
186
200
|
}
|
|
187
201
|
|
|
188
202
|
function elements( dict, parent ) {
|
|
@@ -215,7 +229,7 @@ function revealInternalProperties( model, nameOrPath ) {
|
|
|
215
229
|
if (!node || typeof node !== 'object')
|
|
216
230
|
return primOrString( node );
|
|
217
231
|
if (Array.isArray(node)) // with args
|
|
218
|
-
return
|
|
232
|
+
return array( node, reveal );
|
|
219
233
|
// Make unexpected prototype visible with node-10+:
|
|
220
234
|
const r = Object.create( Object.getPrototypeOf(node)
|
|
221
235
|
? NOT_A_DICTIONARY.prototype
|
|
@@ -225,6 +239,8 @@ function revealInternalProperties( model, nameOrPath ) {
|
|
|
225
239
|
}
|
|
226
240
|
if (node[$inferred] && !node['[$inferred]'])
|
|
227
241
|
r['[$inferred]'] = node[$inferred];
|
|
242
|
+
if (node[$location] && !node['[$location]'])
|
|
243
|
+
r['[$location]'] = locationString( node[$location] );
|
|
228
244
|
return r;
|
|
229
245
|
}
|
|
230
246
|
|
|
@@ -239,7 +255,7 @@ function revealInternalProperties( model, nameOrPath ) {
|
|
|
239
255
|
if (node == null || typeof node !== 'object' )
|
|
240
256
|
return primOrString( node );
|
|
241
257
|
if (Array.isArray(node))
|
|
242
|
-
return
|
|
258
|
+
return array( node, revealNonEnum );
|
|
243
259
|
|
|
244
260
|
if (Object.getPrototypeOf( node ))
|
|
245
261
|
return artifactIdentifier( node, parent );
|
|
@@ -250,7 +266,7 @@ function revealInternalProperties( model, nameOrPath ) {
|
|
|
250
266
|
if (node == null || typeof node !== 'object' )
|
|
251
267
|
return node
|
|
252
268
|
if (Array.isArray(node))
|
|
253
|
-
return
|
|
269
|
+
return array( node, n => reveal( n, node, name ) );
|
|
254
270
|
|
|
255
271
|
const asLinkTest = kindsRepresentedAsLinks[ node.kind ];
|
|
256
272
|
if (asLinkTest && asLinkTest( node, parent, name ))
|
|
@@ -280,6 +296,13 @@ function revealInternalProperties( model, nameOrPath ) {
|
|
|
280
296
|
}
|
|
281
297
|
}
|
|
282
298
|
|
|
299
|
+
function array( node, fn ) {
|
|
300
|
+
const r = node.map( n => fn( n, node ) );
|
|
301
|
+
if (node[$location])
|
|
302
|
+
r.push( { $location: locationString( node[$location] ) } );
|
|
303
|
+
return r;
|
|
304
|
+
}
|
|
305
|
+
|
|
283
306
|
function artifactIdentifier( node, parent ) {
|
|
284
307
|
if (Array.isArray(node))
|
|
285
308
|
return node.map( a => artifactIdentifier( a, node ) );
|
|
@@ -335,7 +358,7 @@ function primOrString( node ) {
|
|
|
335
358
|
if (node == null || typeof node !== 'object')
|
|
336
359
|
return node
|
|
337
360
|
if (Array.isArray(node))
|
|
338
|
-
return
|
|
361
|
+
return array( node, primOrString );
|
|
339
362
|
if (Object.getPrototypeOf( node ))
|
|
340
363
|
return '' + node;
|
|
341
364
|
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
|
*
|
package/lib/optionProcessor.js
CHANGED
|
@@ -19,10 +19,7 @@ optionProcessor
|
|
|
19
19
|
.option(' --color <mode>', ['auto', 'always', 'never'])
|
|
20
20
|
.option('-o, --out <dir>')
|
|
21
21
|
.option(' --cds-home <dir>')
|
|
22
|
-
.option(' --lint-mode')
|
|
23
22
|
.option(' --fuzzy-csn-error')
|
|
24
|
-
.option(' --trace-parser')
|
|
25
|
-
.option(' --trace-parser-amb')
|
|
26
23
|
.option(' --trace-fs')
|
|
27
24
|
.option(' --error <id-list>')
|
|
28
25
|
.option(' --warn <id-list>')
|
|
@@ -34,9 +31,7 @@ optionProcessor
|
|
|
34
31
|
.option(' --beta-mode')
|
|
35
32
|
.option(' --beta <list>')
|
|
36
33
|
.option(' --deprecated <list>')
|
|
37
|
-
.option(' --hana-flavor')
|
|
38
34
|
.option(' --direct-backend')
|
|
39
|
-
.option(' --parse-only')
|
|
40
35
|
.option(' --fallback-parser <type>', ['cdl', 'csn', 'csn!'])
|
|
41
36
|
.option(' --test-mode')
|
|
42
37
|
.option(' --test-sort-csn')
|
|
@@ -79,7 +74,6 @@ optionProcessor
|
|
|
79
74
|
never:
|
|
80
75
|
-o, --out <dir> Place generated files in directory <dir>, default is "-" for <stdout>
|
|
81
76
|
--cds-home <dir> When set, modules starting with '@sap/cds/' are searched in <dir>
|
|
82
|
-
--lint-mode Generate nothing, just produce messages if any (for use by editors)
|
|
83
77
|
--fuzzy-csn-error Report free-style CSN properties as errors
|
|
84
78
|
-- Indicate the end of options (helpful if source names start with "-")
|
|
85
79
|
|
|
@@ -88,8 +82,6 @@ optionProcessor
|
|
|
88
82
|
--default-string-length <length> Default 'length' for 'cds.String'
|
|
89
83
|
|
|
90
84
|
Diagnostic options
|
|
91
|
-
--trace-parser Trace parser
|
|
92
|
-
--trace-parser-amb Trace parser ambiguities
|
|
93
85
|
--trace-fs Trace file system access caused by "using from"
|
|
94
86
|
|
|
95
87
|
Severity options
|
|
@@ -107,22 +99,12 @@ optionProcessor
|
|
|
107
99
|
--beta-mode Enable all unsupported, incomplete (beta) features
|
|
108
100
|
--beta <list> Comma separated list of unsupported, incomplete (beta) features to use.
|
|
109
101
|
Valid values are:
|
|
110
|
-
addTextsLanguageAssoc
|
|
111
102
|
hanaAssocRealCardinality
|
|
112
103
|
mapAssocToJoinCardinality
|
|
113
104
|
ignoreAssocPublishingInUnion
|
|
114
105
|
--deprecated <list> Comma separated list of deprecated options.
|
|
115
106
|
Valid values are:
|
|
116
|
-
|
|
117
|
-
v1KeysForTemporal
|
|
118
|
-
parensAsStrings
|
|
119
|
-
projectionAsQuery
|
|
120
|
-
renderVirtualElements
|
|
121
|
-
unmanagedUpInComponent
|
|
122
|
-
createLocalizedViews
|
|
123
|
-
redirectInSubQueries
|
|
124
|
-
--hana-flavor Compile with backward compatibility for HANA CDS (incomplete)
|
|
125
|
-
--parse-only Stop compilation after parsing and write result to <stdout>
|
|
107
|
+
eagerPersistenceForGeneratedEntities
|
|
126
108
|
--fallback-parser <type> If the language cannot be deduced by the file's extensions, use this
|
|
127
109
|
parser as a fallback. Valid values are:
|
|
128
110
|
cdl : Use CDL parser
|
|
@@ -151,6 +133,8 @@ optionProcessor
|
|
|
151
133
|
toCsn [options] <files...> (default) Generate original model as CSN
|
|
152
134
|
parseCdl [options] <file> Generate a CSN that is close to the CDL source.
|
|
153
135
|
explain <message-id> Explain a compiler message.
|
|
136
|
+
parseOnly [options] <files...> (internal) Stop compilation after parsing, write messages to <stderr>,
|
|
137
|
+
per default no output.
|
|
154
138
|
toRename [options] <files...> (internal) Generate SQL DDL rename statements
|
|
155
139
|
manageConstraints [options] <files...> (internal) Generate ALTER TABLE statements to
|
|
156
140
|
add / modify referential constraints.
|
|
@@ -159,7 +143,7 @@ optionProcessor
|
|
|
159
143
|
// ----------- toHana -----------
|
|
160
144
|
optionProcessor.command('H, toHana')
|
|
161
145
|
.option('-h, --help')
|
|
162
|
-
.option('-n, --
|
|
146
|
+
.option('-n, --sql-mapping <style>', ['plain', 'quoted', 'hdbcds'], { aliases: ['--names'] })
|
|
163
147
|
.option(' --render-virtual')
|
|
164
148
|
.option(' --joinfk')
|
|
165
149
|
.option('-u, --user <user>')
|
|
@@ -176,7 +160,7 @@ optionProcessor.command('H, toHana')
|
|
|
176
160
|
|
|
177
161
|
Options
|
|
178
162
|
-h, --help Show this help text
|
|
179
|
-
-n, --
|
|
163
|
+
-n, --sql-mapping <style> Naming style for generated entity and element names:
|
|
180
164
|
plain : (default) Produce HANA entity and element names in
|
|
181
165
|
uppercase and flattened with underscores. Do not generate
|
|
182
166
|
structured types.
|
|
@@ -207,7 +191,7 @@ optionProcessor.command('H, toHana')
|
|
|
207
191
|
|
|
208
192
|
optionProcessor.command('O, toOdata')
|
|
209
193
|
.option('-h, --help')
|
|
210
|
-
.option('-v, --version <version>', ['v2', 'v4', 'v4x'])
|
|
194
|
+
.option('-v, --odata-version <version>', ['v2', 'v4', 'v4x'], { aliases: ['--version'] })
|
|
211
195
|
.option('-x, --xml')
|
|
212
196
|
.option('-j, --json')
|
|
213
197
|
.option(' --odata-containment')
|
|
@@ -217,7 +201,7 @@ optionProcessor.command('O, toOdata')
|
|
|
217
201
|
.option(' --odata-v2-partial-constr')
|
|
218
202
|
.option('-c, --csn')
|
|
219
203
|
.option('-f, --odata-format <format>', ['flat', 'structured'])
|
|
220
|
-
.option('-n, --
|
|
204
|
+
.option('-n, --sql-mapping <style>', ['plain', 'quoted', 'hdbcds'], { aliases: [ '--names' ] })
|
|
221
205
|
.option('-s, --service-names <list>')
|
|
222
206
|
.help(`
|
|
223
207
|
Usage: cdsc toOdata [options] <files...>
|
|
@@ -226,10 +210,10 @@ optionProcessor.command('O, toOdata')
|
|
|
226
210
|
|
|
227
211
|
Options
|
|
228
212
|
-h, --help Show this help text
|
|
229
|
-
-v, --version <version> ODATA version
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
213
|
+
-v, --odata-version <version> ODATA version
|
|
214
|
+
v2: ODATA V2
|
|
215
|
+
v4: (default) ODATA V4
|
|
216
|
+
v4x: { version: 'v4', odataContainment:true, format:'structured' }
|
|
233
217
|
-x, --xml (default) Generate XML output (separate or combined)
|
|
234
218
|
-j, --json Generate JSON output as "<svc>.json" (not available for v2)
|
|
235
219
|
-c, --csn Generate "odata_csn.json" with ODATA-preprocessed model
|
|
@@ -242,15 +226,15 @@ optionProcessor.command('O, toOdata')
|
|
|
242
226
|
--odata-foreign-keys Render foreign keys in structured format (V4 only)
|
|
243
227
|
--odata-v2-partial-constr Render referential constraints also for partial principal key tuple
|
|
244
228
|
(Not spec compliant and V2 only)
|
|
245
|
-
-n, --
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
229
|
+
-n, --sql-mapping <style> Annotate artifacts and elements with "@cds.persistence.name", which is
|
|
230
|
+
the corresponding database name (see "--sql-mapping" for "toHana or "toSql")
|
|
231
|
+
plain : (default) Names in uppercase and flattened with underscores
|
|
232
|
+
quoted : Names in original case as in CDL. Entity names with dots,
|
|
233
|
+
but element names flattened with underscores
|
|
234
|
+
hdbcds : Names as HANA CDS would generate them from the same CDS
|
|
235
|
+
source (like "quoted", but using element names with dots)
|
|
252
236
|
-s, --service-names <list> List of comma-separated service names to be rendered
|
|
253
|
-
(default) empty, all services are rendered
|
|
237
|
+
(default) empty, all services are rendered
|
|
254
238
|
`);
|
|
255
239
|
|
|
256
240
|
optionProcessor.command('C, toCdl')
|
|
@@ -266,10 +250,10 @@ optionProcessor.command('C, toCdl')
|
|
|
266
250
|
|
|
267
251
|
optionProcessor.command('Q, toSql')
|
|
268
252
|
.option('-h, --help')
|
|
269
|
-
.option('-n, --
|
|
253
|
+
.option('-n, --sql-mapping <style>', ['plain', 'quoted', 'hdbcds'], { aliases: [ '--names' ] })
|
|
254
|
+
.option('-d, --sql-dialect <dialect>', ['hana', 'sqlite', 'plain', 'postgres'], { aliases: [ '--dialect' ] })
|
|
270
255
|
.option(' --render-virtual')
|
|
271
256
|
.option(' --joinfk')
|
|
272
|
-
.option('-d, --dialect <dialect>', ['hana', 'sqlite', 'plain'])
|
|
273
257
|
.option('-u, --user <user>')
|
|
274
258
|
.option('-l, --locale <locale>')
|
|
275
259
|
.option('-s, --src <style>', ['sql', 'hdi'])
|
|
@@ -286,7 +270,7 @@ optionProcessor.command('Q, toSql')
|
|
|
286
270
|
|
|
287
271
|
Options
|
|
288
272
|
-h, --help Show this help text
|
|
289
|
-
-n, --
|
|
273
|
+
-n, --sql-mapping <style> Naming style for generated entity and element names:
|
|
290
274
|
plain : (default) Produce SQL table and view names in
|
|
291
275
|
flattened with underscores format (no quotes required)
|
|
292
276
|
quoted : Produce SQL table and view names in original case as in
|
|
@@ -299,10 +283,11 @@ optionProcessor.command('Q, toSql')
|
|
|
299
283
|
combination with "hana" dialect.
|
|
300
284
|
--render-virtual Render virtual elements in views and draft tables
|
|
301
285
|
--joinfk Create JOINs for foreign key accesses
|
|
302
|
-
-d, --dialect <dialect>
|
|
303
|
-
plain
|
|
304
|
-
hana
|
|
305
|
-
sqlite
|
|
286
|
+
-d, --sql-dialect <dialect> SQL dialect to be generated:
|
|
287
|
+
plain : (default) Common SQL - no assumptions about DB restrictions
|
|
288
|
+
hana : SQL with HANA specific language features
|
|
289
|
+
sqlite : Common SQL for sqlite
|
|
290
|
+
postgres : Common SQL for postgres - beta-feature
|
|
306
291
|
-u, --user <user> Value for the "$user" variable
|
|
307
292
|
-l, --locale <locale> Value for the "$user.locale" variable in "sqlite"/"plain" dialect
|
|
308
293
|
-s, --src <style> Generate SQL source files as <artifact>.<suffix>
|
|
@@ -329,28 +314,29 @@ optionProcessor.command('Q, toSql')
|
|
|
329
314
|
|
|
330
315
|
optionProcessor.command('toRename')
|
|
331
316
|
.option('-h, --help')
|
|
332
|
-
.option('-n, --
|
|
317
|
+
.option('-n, --sql-mapping <style>', ['quoted', 'hdbcds'], { aliases: ['--names'] })
|
|
333
318
|
.help(`
|
|
334
319
|
Usage: cdsc toRename [options] <files...>
|
|
335
320
|
|
|
336
321
|
(internal, subject to change): Generate SQL stored procedure containing DDL statements to
|
|
337
322
|
"storedProcedure.sql" that allows to rename existing tables and their columns so that they
|
|
338
|
-
match the result of "toHana" or "toSql" with the "--
|
|
323
|
+
match the result of "toHana" or "toSql" with the "--sql-mapping plain" option.
|
|
339
324
|
|
|
340
325
|
Options
|
|
341
326
|
-h, --help Display this help text
|
|
342
|
-
-n, --
|
|
327
|
+
-n, --sql-mapping <style>
|
|
328
|
+
Assume existing tables were generated with "--sql-mapping <style>":
|
|
343
329
|
quoted : Assume existing SQL tables and views were named in original
|
|
344
330
|
case as in CDL (with dots), but column names were flattened
|
|
345
|
-
with underscores (e.g. resulting from "toHana --
|
|
331
|
+
with underscores (e.g. resulting from "toHana --sql-mapping quoted")
|
|
346
332
|
hdbcds : (default) Assume existing SQL tables, views and columns were
|
|
347
333
|
generated by HANA CDS from the same CDS source (or resulting
|
|
348
|
-
from "toHana --
|
|
334
|
+
from "toHana --sql-mapping hdbcds")
|
|
349
335
|
`);
|
|
350
336
|
|
|
351
337
|
optionProcessor.command('manageConstraints')
|
|
352
338
|
.option('-h, --help')
|
|
353
|
-
.option('-n, --
|
|
339
|
+
.option('-n, --sql-mapping <style>', ['plain', 'quoted', 'hdbcds'], { aliases: ['--names'] })
|
|
354
340
|
.option('-s, --src <style>', ['sql', 'hdi'])
|
|
355
341
|
.option(' --drop')
|
|
356
342
|
.option(' --alter')
|
|
@@ -366,7 +352,8 @@ optionProcessor.command('manageConstraints')
|
|
|
366
352
|
|
|
367
353
|
Options
|
|
368
354
|
-h, --help Display this help text
|
|
369
|
-
-n, --
|
|
355
|
+
-n, --sql-mapping <style>
|
|
356
|
+
Assume existing tables were generated with "--sql-mapping <style>":
|
|
370
357
|
plain : (default) Assume SQL tables were flattened and dots were
|
|
371
358
|
replaced by underscores
|
|
372
359
|
quoted : Assume existing SQL tables and views were named in original
|
|
@@ -388,7 +375,7 @@ optionProcessor.command('manageConstraints')
|
|
|
388
375
|
|
|
389
376
|
optionProcessor.command('toCsn')
|
|
390
377
|
.option('-h, --help')
|
|
391
|
-
.option('-f, --flavor <flavor>', ['client', 'gensrc', 'universal'])
|
|
378
|
+
.option('-f, --csn-flavor <flavor>', ['client', 'gensrc', 'universal'], { aliases: ['--flavor'] })
|
|
392
379
|
.option(' --with-localized')
|
|
393
380
|
.help(`
|
|
394
381
|
Usage: cdsc toCsn [options] <files...>
|
|
@@ -397,13 +384,13 @@ optionProcessor.command('toCsn')
|
|
|
397
384
|
|
|
398
385
|
Options
|
|
399
386
|
-h, --help Show this help text
|
|
400
|
-
-f, --flavor <flavor> Generate CSN in one of two flavors:
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
387
|
+
-f, --csn-flavor <flavor> Generate CSN in one of two flavors:
|
|
388
|
+
client : (default) Standard CSN consumable by clients and backends
|
|
389
|
+
gensrc : CSN specifically for use as a source, e.g. for
|
|
390
|
+
combination with additional "extend" or "annotate"
|
|
391
|
+
statements, but not suitable for consumption by clients or
|
|
392
|
+
backends
|
|
393
|
+
universal: in development (BETA)
|
|
407
394
|
|
|
408
395
|
Internal options (for testing only, may be changed/removed at any time)
|
|
409
396
|
--with-localized Add localized convenience views to the CSN output.
|
|
@@ -422,6 +409,26 @@ optionProcessor.command('parseCdl')
|
|
|
422
409
|
-h, --help Show this help text
|
|
423
410
|
`);
|
|
424
411
|
|
|
412
|
+
optionProcessor.command('parseOnly')
|
|
413
|
+
.option('-h, --help')
|
|
414
|
+
.option(' --trace-parser')
|
|
415
|
+
.option(' --trace-parser-amb')
|
|
416
|
+
.positionalArgument('<file>')
|
|
417
|
+
.help(`
|
|
418
|
+
Usage: cdsc parseOnly [options] <files...>
|
|
419
|
+
|
|
420
|
+
(internal): Stop compilation after parsing and write messages to <stderr>.
|
|
421
|
+
Per default, nothing is printed. With \`--raw-output +\`, XSN is printed
|
|
422
|
+
to <stdout>.
|
|
423
|
+
|
|
424
|
+
Options
|
|
425
|
+
-h, --help Show this help text
|
|
426
|
+
|
|
427
|
+
Diagnostic options
|
|
428
|
+
--trace-parser Trace parser
|
|
429
|
+
--trace-parser-amb Trace parser ambiguities
|
|
430
|
+
`);
|
|
431
|
+
|
|
425
432
|
optionProcessor.command('explain')
|
|
426
433
|
.option('-h, --help')
|
|
427
434
|
.positionalArgument('<message-id>')
|
|
@@ -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
|
};
|