@sap/cds-compiler 3.4.4 → 3.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 +58 -0
- package/README.md +1 -0
- package/bin/cds_update_identifiers.js +5 -5
- package/bin/cdsc.js +12 -12
- package/doc/CHANGELOG_ARCHIVE.md +1 -1
- package/doc/CHANGELOG_BETA.md +9 -1
- package/doc/CHANGELOG_DEPRECATED.md +2 -0
- package/lib/api/main.js +58 -59
- package/lib/api/options.js +4 -2
- package/lib/api/validate.js +2 -2
- package/lib/base/cleanSymbols.js +2 -3
- package/lib/base/dictionaries.js +6 -6
- package/lib/base/error.js +2 -2
- package/lib/base/keywords.js +6 -6
- package/lib/base/location.js +11 -12
- package/lib/base/message-registry.js +124 -28
- package/lib/base/messages.js +247 -179
- package/lib/base/model.js +14 -11
- package/lib/base/node-helpers.js +9 -10
- package/lib/base/optionProcessorHelper.js +138 -129
- package/lib/checks/actionsFunctions.js +5 -5
- package/lib/checks/annotationsOData.js +4 -4
- package/lib/checks/arrayOfs.js +1 -1
- package/lib/checks/cdsPersistence.js +1 -1
- package/lib/checks/checkForTypes.js +3 -3
- package/lib/checks/defaultValues.js +3 -3
- package/lib/checks/elements.js +7 -7
- package/lib/checks/emptyOrOnlyVirtual.js +2 -2
- package/lib/checks/foreignKeys.js +1 -1
- package/lib/checks/invalidTarget.js +4 -4
- package/lib/checks/managedInType.js +1 -1
- package/lib/checks/managedWithoutKeys.js +1 -1
- package/lib/checks/nonexpandableStructured.js +5 -3
- package/lib/checks/nullableKeys.js +1 -1
- package/lib/checks/onConditions.js +5 -6
- package/lib/checks/parameters.js +1 -1
- package/lib/checks/queryNoDbArtifacts.js +2 -2
- package/lib/checks/selectItems.js +4 -4
- package/lib/checks/sql-snippets.js +4 -4
- package/lib/checks/types.js +7 -7
- package/lib/checks/utils.js +4 -4
- package/lib/checks/validator.js +16 -13
- package/lib/compiler/.eslintrc.json +1 -1
- package/lib/compiler/assert-consistency.js +0 -1
- package/lib/compiler/builtins.js +1 -1
- package/lib/compiler/checks.js +73 -15
- package/lib/compiler/define.js +3 -7
- package/lib/compiler/extend.js +212 -32
- package/lib/compiler/finalize-parse-cdl.js +7 -2
- package/lib/compiler/index.js +17 -14
- package/lib/compiler/populate.js +2 -5
- package/lib/compiler/propagator.js +2 -0
- package/lib/compiler/shared.js +23 -12
- package/lib/compiler/tweak-assocs.js +5 -6
- package/lib/compiler/utils.js +6 -0
- package/lib/edm/annotations/genericTranslation.js +553 -319
- package/lib/edm/annotations/preprocessAnnotations.js +39 -35
- package/lib/edm/csn2edm.js +88 -75
- package/lib/edm/edm.js +17 -3
- package/lib/edm/edmAnnoPreprocessor.js +5 -5
- package/lib/edm/edmPreprocessor.js +106 -76
- package/lib/edm/edmUtils.js +41 -2
- package/lib/gen/Dictionary.json +34 -0
- package/lib/gen/language.checksum +1 -1
- package/lib/gen/language.interp +66 -63
- package/lib/gen/language.tokens +81 -81
- package/lib/gen/languageLexer.interp +4 -10
- package/lib/gen/languageLexer.js +854 -869
- package/lib/gen/languageLexer.tokens +79 -81
- package/lib/gen/languageParser.js +14360 -14146
- package/lib/inspect/inspectModelStatistics.js +2 -2
- package/lib/inspect/inspectPropagation.js +6 -6
- package/lib/inspect/inspectUtils.js +2 -2
- package/lib/json/from-csn.js +82 -40
- package/lib/json/to-csn.js +82 -157
- package/lib/language/.eslintrc.json +1 -4
- package/lib/language/genericAntlrParser.js +59 -38
- package/lib/language/language.g4 +1508 -1490
- package/lib/language/multiLineStringParser.js +1 -1
- package/lib/main.js +3 -3
- package/lib/model/csnUtils.js +130 -122
- package/lib/model/revealInternalProperties.js +1 -1
- package/lib/model/sortViews.js +4 -6
- package/lib/modelCompare/utils/filter.js +4 -3
- package/lib/optionProcessor.js +5 -0
- package/lib/render/DuplicateChecker.js +1 -1
- package/lib/render/manageConstraints.js +12 -12
- package/lib/render/toCdl.js +225 -159
- package/lib/render/toHdbcds.js +63 -63
- package/lib/render/toRename.js +5 -5
- package/lib/render/toSql.js +55 -65
- package/lib/render/utils/common.js +20 -37
- package/lib/render/utils/delta.js +3 -3
- package/lib/render/utils/sql.js +22 -6
- package/lib/render/utils/stringEscapes.js +3 -3
- package/lib/transform/db/applyTransformations.js +3 -3
- package/lib/transform/db/assertUnique.js +13 -12
- package/lib/transform/db/associations.js +5 -5
- package/lib/transform/db/cdsPersistence.js +10 -8
- package/lib/transform/db/constraints.js +14 -14
- package/lib/transform/db/expansion.js +20 -22
- package/lib/transform/db/flattening.js +24 -42
- package/lib/transform/db/groupByOrderBy.js +3 -3
- package/lib/transform/db/temporal.js +6 -6
- package/lib/transform/db/transformExists.js +23 -23
- package/lib/transform/db/views.js +16 -16
- package/lib/transform/draft/db.js +10 -10
- package/lib/transform/draft/odata.js +2 -2
- package/lib/transform/forOdataNew.js +12 -40
- package/lib/transform/forRelationalDB.js +17 -7
- package/lib/transform/localized.js +2 -2
- package/lib/transform/odata/toFinalBaseType.js +41 -27
- package/lib/transform/odata/typesExposure.js +106 -62
- package/lib/transform/parseExpr.js +209 -106
- package/lib/transform/transformUtilsNew.js +2 -2
- package/lib/transform/translateAssocsToJoins.js +24 -19
- package/lib/transform/universalCsn/coreComputed.js +10 -10
- package/lib/transform/universalCsn/universalCsnEnricher.js +26 -26
- package/lib/transform/universalCsn/utils.js +3 -3
- package/lib/utils/file.js +5 -5
- package/lib/utils/moduleResolve.js +13 -13
- package/lib/utils/objectUtils.js +6 -6
- package/lib/utils/term.js +5 -2
- package/lib/utils/timetrace.js +51 -24
- package/package.json +5 -7
- package/share/messages/check-proper-type-of.md +1 -1
- package/share/messages/message-explanations.json +1 -1
- package/share/messages/redirected-to-complex.md +4 -4
- package/share/messages/{syntax-expecting-integer.md → syntax-expecting-unsigned-int.md} +7 -4
package/lib/render/utils/sql.js
CHANGED
|
@@ -18,7 +18,7 @@ const { ModelError } = require('../../base/error');
|
|
|
18
18
|
*
|
|
19
19
|
* @returns {string} SQL statement which can be used to create the referential constraint on the db.
|
|
20
20
|
*/
|
|
21
|
-
function renderReferentialConstraint(constraint, indent, toUpperCase, csn, options, alterConstraint = false) {
|
|
21
|
+
function renderReferentialConstraint( constraint, indent, toUpperCase, csn, options, alterConstraint = false ) {
|
|
22
22
|
let quoteId;
|
|
23
23
|
// for to.hana we can't utilize the sql identifier utils
|
|
24
24
|
if (options.transformation === 'hdbcds') {
|
|
@@ -29,7 +29,7 @@ function renderReferentialConstraint(constraint, indent, toUpperCase, csn, optio
|
|
|
29
29
|
};
|
|
30
30
|
}
|
|
31
31
|
else {
|
|
32
|
-
quoteId = getIdentifierUtils(options).quoteSqlId;
|
|
32
|
+
quoteId = getIdentifierUtils(csn, options).quoteSqlId;
|
|
33
33
|
}
|
|
34
34
|
if (toUpperCase) {
|
|
35
35
|
constraint.identifier = constraint.identifier.toUpperCase();
|
|
@@ -81,8 +81,8 @@ function renderReferentialConstraint(constraint, indent, toUpperCase, csn, optio
|
|
|
81
81
|
* @param {CSN.Options} options
|
|
82
82
|
* @returns quoteSqlId and prepareIdentifier function
|
|
83
83
|
*/
|
|
84
|
-
function getIdentifierUtils(options) {
|
|
85
|
-
return { quoteSqlId, prepareIdentifier };
|
|
84
|
+
function getIdentifierUtils( csn, options ) {
|
|
85
|
+
return { quoteSqlId, prepareIdentifier, renderArtifactName };
|
|
86
86
|
/**
|
|
87
87
|
* Return 'name' with appropriate "-quotes.
|
|
88
88
|
* Additionally perform the following conversions on 'name'
|
|
@@ -95,7 +95,7 @@ function getIdentifierUtils(options) {
|
|
|
95
95
|
* @param {string} name Identifier to quote
|
|
96
96
|
* @returns {string} Quoted identifier
|
|
97
97
|
*/
|
|
98
|
-
function quoteSqlId(name) {
|
|
98
|
+
function quoteSqlId( name ) {
|
|
99
99
|
name = prepareIdentifier(name);
|
|
100
100
|
|
|
101
101
|
switch (options.sqlMapping) {
|
|
@@ -120,7 +120,7 @@ function getIdentifierUtils(options) {
|
|
|
120
120
|
* @param {string} name Identifier to prepare
|
|
121
121
|
* @returns {string} Identifier prepared for quoting
|
|
122
122
|
*/
|
|
123
|
-
function prepareIdentifier(name) {
|
|
123
|
+
function prepareIdentifier( name ) {
|
|
124
124
|
// Sanity check
|
|
125
125
|
if (options.sqlDialect === 'sqlite' && options.sqlMapping !== 'plain')
|
|
126
126
|
throw new ModelError(`Not expecting ${options.sqlMapping} names for 'sqlite' dialect`);
|
|
@@ -137,6 +137,22 @@ function getIdentifierUtils(options) {
|
|
|
137
137
|
throw new ModelError(`No matching rendering found for naming mode ${options.sqlMapping}`);
|
|
138
138
|
}
|
|
139
139
|
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Given the following artifact name: namespace.prefix.entity.with.dot, render the following,
|
|
143
|
+
* depending on the naming mode:
|
|
144
|
+
* - plain: NAMESPACE_PREFIX_ENTITY_WITH_DOT
|
|
145
|
+
* - quoted: namespace.prefix.entity_with_dot
|
|
146
|
+
* - hdbcds: namespace::prefix.entity_with_dot
|
|
147
|
+
*
|
|
148
|
+
*
|
|
149
|
+
* @param {string} artifactName Artifact name to render
|
|
150
|
+
*
|
|
151
|
+
* @returns {string} Artifact name
|
|
152
|
+
*/
|
|
153
|
+
function renderArtifactName( artifactName ) {
|
|
154
|
+
return quoteSqlId(getResultingName(csn, options.sqlMapping, artifactName));
|
|
155
|
+
}
|
|
140
156
|
}
|
|
141
157
|
|
|
142
158
|
|
|
@@ -16,7 +16,7 @@ const unpairedSurrogate = /[^\u{D800}-\u{DBFF}][\u{DC00}-\u{DFFF}]|[\u{D800}-\u{
|
|
|
16
16
|
* @param {string} str
|
|
17
17
|
* @return {boolean}
|
|
18
18
|
*/
|
|
19
|
-
function hasUnpairedUnicodeSurrogate(str) {
|
|
19
|
+
function hasUnpairedUnicodeSurrogate( str ) {
|
|
20
20
|
return unpairedSurrogate.test(str);
|
|
21
21
|
}
|
|
22
22
|
|
|
@@ -26,7 +26,7 @@ function hasUnpairedUnicodeSurrogate(str) {
|
|
|
26
26
|
* @param {string} str
|
|
27
27
|
* @return {boolean}
|
|
28
28
|
*/
|
|
29
|
-
function hasControlCharacters(str) {
|
|
29
|
+
function hasControlCharacters( str ) {
|
|
30
30
|
return controlCharacters.test(str);
|
|
31
31
|
}
|
|
32
32
|
|
|
@@ -60,7 +60,7 @@ function hasControlCharacters(str) {
|
|
|
60
60
|
* @param {object} escapes
|
|
61
61
|
* @returns {string}
|
|
62
62
|
*/
|
|
63
|
-
function escapeString(str, escapes) {
|
|
63
|
+
function escapeString( str, escapes ) {
|
|
64
64
|
const output = [];
|
|
65
65
|
|
|
66
66
|
for (let i = 0; i < str.length; ++i) {
|
|
@@ -22,7 +22,7 @@ const { setProp } = require('../../base/model');
|
|
|
22
22
|
* @param {CSN.Path} path Path to parent
|
|
23
23
|
* @returns {object} parent with transformations applied
|
|
24
24
|
*/
|
|
25
|
-
function applyTransformationsInternal(parent, prop, customTransformers, artifactTransformers, options, path = []) {
|
|
25
|
+
function applyTransformationsInternal( parent, prop, customTransformers, artifactTransformers, options, path = [] ) {
|
|
26
26
|
const transformers = {
|
|
27
27
|
elements: dictionary,
|
|
28
28
|
definitions: dictionary,
|
|
@@ -196,7 +196,7 @@ function applyTransformations( csn, customTransformers = {}, artifactTransformer
|
|
|
196
196
|
* @param {CSN.Path} path Path pointing to parent
|
|
197
197
|
* @returns {object} parent[prop] with transformations applied
|
|
198
198
|
*/
|
|
199
|
-
function applyTransformationsOnNonDictionary(parent, prop, customTransformers = {}, options = {}, path = []) {
|
|
199
|
+
function applyTransformationsOnNonDictionary( parent, prop, customTransformers = {}, options = {}, path = [] ) {
|
|
200
200
|
return applyTransformationsInternal(parent, prop, customTransformers, [], options, path)[prop];
|
|
201
201
|
}
|
|
202
202
|
|
|
@@ -217,7 +217,7 @@ function applyTransformationsOnNonDictionary(parent, prop, customTransformers =
|
|
|
217
217
|
* @param {CSN.Path} path Path pointing to parent
|
|
218
218
|
* @returns {object} dictionary with transformations applied
|
|
219
219
|
*/
|
|
220
|
-
function applyTransformationsOnDictionary(dictionary, customTransformers = {}, options = {}, path = []) {
|
|
220
|
+
function applyTransformationsOnDictionary( dictionary, customTransformers = {}, options = {}, path = [] ) {
|
|
221
221
|
return applyTransformationsInternal(dictionary, null, customTransformers, [], { directDict: true, ...options }, path);
|
|
222
222
|
}
|
|
223
223
|
|
|
@@ -20,7 +20,7 @@ const { pathName } = require('../../compiler/utils');
|
|
|
20
20
|
* @param {Function} error Message function for errors
|
|
21
21
|
* @param {Function} info Message function for info
|
|
22
22
|
*/
|
|
23
|
-
function processAssertUnique(csn, options, error, info) {
|
|
23
|
+
function processAssertUnique( csn, options, error, info ) {
|
|
24
24
|
const { resolvePath, flattenPath } = getTransformers(csn, options);
|
|
25
25
|
|
|
26
26
|
forEachDefinition(csn, handleAssertUnique);
|
|
@@ -30,7 +30,7 @@ function processAssertUnique(csn, options, error, info) {
|
|
|
30
30
|
* @param {CSN.Artifact} artifact
|
|
31
31
|
* @param {string} artifactName
|
|
32
32
|
*/
|
|
33
|
-
function handleAssertUnique(artifact, artifactName) {
|
|
33
|
+
function handleAssertUnique( artifact, artifactName ) {
|
|
34
34
|
// operate only on real entities that are not abstract
|
|
35
35
|
if (artifact.abstract || (artifact.kind !== 'entity' || (artifact.query || artifact.projection) && !hasAnnotationValue(artifact, '@cds.persistence.table')))
|
|
36
36
|
return;
|
|
@@ -38,12 +38,13 @@ function processAssertUnique(csn, options, error, info) {
|
|
|
38
38
|
const constraintDict = Object.create(null);
|
|
39
39
|
// filter unique constraints from annotations
|
|
40
40
|
for (const propName in artifact) {
|
|
41
|
-
|
|
42
|
-
|
|
41
|
+
const anno = propName;
|
|
42
|
+
if (propName === '@assert.unique')
|
|
43
|
+
error(null, [ 'definitions', artifactName ], { anno }, '$(ANNO): Table constraint can\'t be anonymous');
|
|
44
|
+
|
|
45
|
+
if (propName.startsWith('@assert.unique.') && artifact[propName] !== null) {
|
|
43
46
|
// Constraint Name check
|
|
44
47
|
const constraintName = propName.split('.').splice(2);
|
|
45
|
-
if (constraintName.length === 0)
|
|
46
|
-
error(null, [ 'definitions', artifactName ], { anno }, '$(ANNO): Table constraint can\'t be anonymous');
|
|
47
48
|
if (constraintName.length > 1)
|
|
48
49
|
// Neither HANA CDS nor HANA SQL allow dots in index names
|
|
49
50
|
error(null, [ 'definitions', artifactName ], { anno }, '$(ANNO): Illegal character \'.\' in constraint name');
|
|
@@ -121,7 +122,7 @@ function processAssertUnique(csn, options, error, info) {
|
|
|
121
122
|
* @param {string} propName
|
|
122
123
|
* @returns {Array} Array of paths
|
|
123
124
|
*/
|
|
124
|
-
function checkVal(val, propName) {
|
|
125
|
+
function checkVal( val, propName ) {
|
|
125
126
|
const paths = [];
|
|
126
127
|
const loc = [ 'definitions', artifactName ];
|
|
127
128
|
if (!Array.isArray(val)) {
|
|
@@ -147,7 +148,7 @@ function processAssertUnique(csn, options, error, info) {
|
|
|
147
148
|
* @param {any} v
|
|
148
149
|
* @returns {string|string[]|any}
|
|
149
150
|
*/
|
|
150
|
-
function unref(v) {
|
|
151
|
+
function unref( v ) {
|
|
151
152
|
if (Array.isArray(v))
|
|
152
153
|
return v.map(unref);
|
|
153
154
|
return (v['='] || v);
|
|
@@ -160,7 +161,7 @@ function processAssertUnique(csn, options, error, info) {
|
|
|
160
161
|
* @param {string} val
|
|
161
162
|
* @returns {object}
|
|
162
163
|
*/
|
|
163
|
-
function toRef(val) {
|
|
164
|
+
function toRef( val ) {
|
|
164
165
|
let ref = val.split('.');
|
|
165
166
|
const [ head, ...tail ] = ref;
|
|
166
167
|
if (head === '$self' || head === '$projection')
|
|
@@ -185,7 +186,7 @@ function processAssertUnique(csn, options, error, info) {
|
|
|
185
186
|
* @param {object} path
|
|
186
187
|
* @param {string} constraintName
|
|
187
188
|
*/
|
|
188
|
-
function check(path, constraintName) {
|
|
189
|
+
function check( path, constraintName ) {
|
|
189
190
|
if (path.isChecked)
|
|
190
191
|
return;
|
|
191
192
|
path.isChecked = true;
|
|
@@ -262,12 +263,12 @@ function processAssertUnique(csn, options, error, info) {
|
|
|
262
263
|
* @param {CSN.Options} options
|
|
263
264
|
* @param {string} pathDelimiter
|
|
264
265
|
*/
|
|
265
|
-
function rewriteUniqueConstraints(csn, options, pathDelimiter) {
|
|
266
|
+
function rewriteUniqueConstraints( csn, options, pathDelimiter ) {
|
|
266
267
|
forEachDefinition(csn, rewrite);
|
|
267
268
|
/**
|
|
268
269
|
* @param {CSN.Artifact} artifact
|
|
269
270
|
*/
|
|
270
|
-
function rewrite(artifact) {
|
|
271
|
+
function rewrite( artifact ) {
|
|
271
272
|
if (artifact.$tableConstraints && artifact.$tableConstraints.unique) {
|
|
272
273
|
const uniqueConstraints = artifact.$tableConstraints.unique;
|
|
273
274
|
// it's safe to add the tc here
|
|
@@ -15,7 +15,7 @@ const {
|
|
|
15
15
|
* @param {string} pathDelimiter
|
|
16
16
|
* @returns {CSN.Model} Return the input csn, with the transformations applied
|
|
17
17
|
*/
|
|
18
|
-
function attachOnConditions(csn, pathDelimiter) {
|
|
18
|
+
function attachOnConditions( csn, pathDelimiter ) {
|
|
19
19
|
const {
|
|
20
20
|
isManagedAssociation,
|
|
21
21
|
} = getUtils(csn);
|
|
@@ -41,7 +41,7 @@ function attachOnConditions(csn, pathDelimiter) {
|
|
|
41
41
|
* @param {string} elemName
|
|
42
42
|
* @returns {void}
|
|
43
43
|
*/
|
|
44
|
-
function transformManagedAssociation(elem, elemName) {
|
|
44
|
+
function transformManagedAssociation( elem, elemName ) {
|
|
45
45
|
// No need to run over this - we already did, possibly because it was referenced in the ON-Condition
|
|
46
46
|
// of another association - see a few lines lower
|
|
47
47
|
if (alreadyHandled.has(elem))
|
|
@@ -107,7 +107,7 @@ function attachOnConditions(csn, pathDelimiter) {
|
|
|
107
107
|
* @param {string} pathDelimiter
|
|
108
108
|
* @returns {(artifact: CSN.Artifact, artifactName: string) => void} Callback for forEachDefinition
|
|
109
109
|
*/
|
|
110
|
-
function getFKAccessFinalizer(csn, pathDelimiter) {
|
|
110
|
+
function getFKAccessFinalizer( csn, pathDelimiter ) {
|
|
111
111
|
const {
|
|
112
112
|
inspectRef,
|
|
113
113
|
} = getUtils(csn);
|
|
@@ -123,7 +123,7 @@ function getFKAccessFinalizer(csn, pathDelimiter) {
|
|
|
123
123
|
* @param {CSN.Artifact} artifact Artifact to check
|
|
124
124
|
* @param {string} artifactName Name of the artifact
|
|
125
125
|
*/
|
|
126
|
-
function handleManagedAssocSteps(artifact, artifactName) {
|
|
126
|
+
function handleManagedAssocSteps( artifact, artifactName ) {
|
|
127
127
|
const transformer = {
|
|
128
128
|
ref: (refOwner, prop, ref, path) => {
|
|
129
129
|
// [<assoc base>.]<managed assoc>.<field>
|
|
@@ -177,7 +177,7 @@ function getFKAccessFinalizer(csn, pathDelimiter) {
|
|
|
177
177
|
* @param {number} startIndex
|
|
178
178
|
* @returns {object | undefined} CSN definition of the source of the managed association
|
|
179
179
|
*/
|
|
180
|
-
function findSource(links, startIndex) {
|
|
180
|
+
function findSource( links, startIndex ) {
|
|
181
181
|
for (let i = startIndex; i >= 0; i--) {
|
|
182
182
|
const link = links[i];
|
|
183
183
|
// We found the latest assoc step - now check where that points to
|
|
@@ -19,7 +19,7 @@ function getAnnoProcessor() {
|
|
|
19
19
|
/**
|
|
20
20
|
* @param {CSN.Artifact} artifact
|
|
21
21
|
*/
|
|
22
|
-
function handleCdsPersistence(artifact) {
|
|
22
|
+
function handleCdsPersistence( artifact ) {
|
|
23
23
|
const ignoreArtifact = (artifact.kind === 'entity') &&
|
|
24
24
|
(artifact.abstract ||
|
|
25
25
|
hasAnnotationValue(artifact, '@cds.persistence.skip') ||
|
|
@@ -39,7 +39,7 @@ function getAnnoProcessor() {
|
|
|
39
39
|
* @param {Function} messageFunctions.info
|
|
40
40
|
* @returns {(artifact: CSN.Artifact, artifactName: string, prop: string, path: CSN.Path) => void} Callback function for forEachDefinition
|
|
41
41
|
*/
|
|
42
|
-
function getAssocToSkippedIgnorer(csn, options, messageFunctions) {
|
|
42
|
+
function getAssocToSkippedIgnorer( csn, options, messageFunctions ) {
|
|
43
43
|
const { info } = messageFunctions;
|
|
44
44
|
const doA2J = !(options.transformation === 'hdbcds' && options.sqlMapping === 'hdbcds');
|
|
45
45
|
|
|
@@ -55,7 +55,7 @@ function getAssocToSkippedIgnorer(csn, options, messageFunctions) {
|
|
|
55
55
|
* @param {string} prop
|
|
56
56
|
* @param {CSN.Path} path
|
|
57
57
|
*/
|
|
58
|
-
function ignoreAssociationToSkippedTarget(artifact, artifactName, prop, path) {
|
|
58
|
+
function ignoreAssociationToSkippedTarget( artifact, artifactName, prop, path ) {
|
|
59
59
|
if (isPersistedOnDatabase(artifact)) {
|
|
60
60
|
// TODO: structure in CSN is artifact.query.[SELECT/SET].mixin
|
|
61
61
|
if (artifact.query) {
|
|
@@ -79,7 +79,7 @@ function getAssocToSkippedIgnorer(csn, options, messageFunctions) {
|
|
|
79
79
|
* @param {string} prop
|
|
80
80
|
* @param {CSN.Path} path
|
|
81
81
|
*/
|
|
82
|
-
function ignore(member, memberName, prop, path) {
|
|
82
|
+
function ignore( member, memberName, prop, path ) {
|
|
83
83
|
if (options.sqlDialect === 'hana' &&
|
|
84
84
|
!member._ignore && member.target &&
|
|
85
85
|
isAssocOrComposition(member.type) &&
|
|
@@ -102,7 +102,7 @@ function getAssocToSkippedIgnorer(csn, options, messageFunctions) {
|
|
|
102
102
|
* @param {Function} messageFunctions.error
|
|
103
103
|
* @returns {(artifact: CSN.Artifact, artifactName) => void} Callback function for forEachDefinition
|
|
104
104
|
*/
|
|
105
|
-
function getPersistenceTableProcessor(csn, options, messageFunctions ) {
|
|
105
|
+
function getPersistenceTableProcessor( csn, options, messageFunctions ) {
|
|
106
106
|
const { error } = messageFunctions;
|
|
107
107
|
const {
|
|
108
108
|
recurseElements,
|
|
@@ -115,7 +115,7 @@ function getPersistenceTableProcessor(csn, options, messageFunctions ) {
|
|
|
115
115
|
* @param {CSN.Artifact} artifact
|
|
116
116
|
* @param {string} artifactName
|
|
117
117
|
*/
|
|
118
|
-
function handleQueryish(artifact, artifactName) {
|
|
118
|
+
function handleQueryish( artifact, artifactName ) {
|
|
119
119
|
const stripQueryish = artifact.query && hasAnnotationValue(artifact, '@cds.persistence.table');
|
|
120
120
|
|
|
121
121
|
if (stripQueryish) {
|
|
@@ -124,8 +124,10 @@ function getPersistenceTableProcessor(csn, options, messageFunctions ) {
|
|
|
124
124
|
|
|
125
125
|
recurseElements(artifact, [ 'definitions', artifactName ], (member, path) => {
|
|
126
126
|
// All elements must have a type for this to work
|
|
127
|
-
if (!member._ignore && !member.kind && !member.type)
|
|
128
|
-
error(null, path,
|
|
127
|
+
if (!member._ignore && !member.kind && !member.type) {
|
|
128
|
+
error(null, path, { anno: '@cds.persistence.table' },
|
|
129
|
+
'Expecting element to have a type if view is annotated with $(ANNO)');
|
|
130
|
+
}
|
|
129
131
|
});
|
|
130
132
|
}
|
|
131
133
|
}
|
|
@@ -14,7 +14,7 @@ const ASSOCIATION = 'cds.Association';
|
|
|
14
14
|
* @param {CSN.Model} csn
|
|
15
15
|
* @param {CSN.Options} options are used to modify the validate / enforced flag on the constraints
|
|
16
16
|
*/
|
|
17
|
-
function createReferentialConstraints(csn, options) {
|
|
17
|
+
function createReferentialConstraints( csn, options ) {
|
|
18
18
|
let validated = true;
|
|
19
19
|
let enforced = true;
|
|
20
20
|
if (options.integrityNotValidated)
|
|
@@ -77,7 +77,7 @@ function createReferentialConstraints(csn, options) {
|
|
|
77
77
|
* @param {CSN.Artifact} parent artifact containing the composition
|
|
78
78
|
* @param {CSN.Path} path
|
|
79
79
|
*/
|
|
80
|
-
function foreignKeyConstraintForUpLinkOfComposition(composition, parent, path) {
|
|
80
|
+
function foreignKeyConstraintForUpLinkOfComposition( composition, parent, path ) {
|
|
81
81
|
const dependent = csn.definitions[path[1]];
|
|
82
82
|
if (skipConstraintGeneration(parent, dependent, composition))
|
|
83
83
|
return;
|
|
@@ -103,7 +103,7 @@ function createReferentialConstraints(csn, options) {
|
|
|
103
103
|
* @param {CSN.Path} path
|
|
104
104
|
* @param {CSN.PathSegment} upLinkFor the name of the composition which used this association in a `$self = <comp>.<up_>` comparison
|
|
105
105
|
*/
|
|
106
|
-
function foreignKeyConstraintForAssociation(association, path, upLinkFor = null) {
|
|
106
|
+
function foreignKeyConstraintForAssociation( association, path, upLinkFor = null ) {
|
|
107
107
|
const parent = csn.definitions[association.target];
|
|
108
108
|
const dependent = csn.definitions[path[1]];
|
|
109
109
|
if (skipConstraintGeneration(parent, dependent, association))
|
|
@@ -136,7 +136,7 @@ function createReferentialConstraints(csn, options) {
|
|
|
136
136
|
* @param {CSN.PathSegment} upLinkFor the name of the composition which used this association in a `$self = <comp>.<up_>` comparison
|
|
137
137
|
* it is used for a comment in the constraint, which is only printed out in test-mode
|
|
138
138
|
*/
|
|
139
|
-
function attachConstraintsToDependentKeys(dependentKeys, parentKeys, parentTable, sourceAssociation, upLinkFor = null) {
|
|
139
|
+
function attachConstraintsToDependentKeys( dependentKeys, parentKeys, parentTable, sourceAssociation, upLinkFor = null ) {
|
|
140
140
|
while (dependentKeys.length > 0) {
|
|
141
141
|
const dependentKeyValuePair = dependentKeys.pop();
|
|
142
142
|
const dependentKey = dependentKeyValuePair[1];
|
|
@@ -178,7 +178,7 @@ function createReferentialConstraints(csn, options) {
|
|
|
178
178
|
* @param {CSN.Path} path the path to the element
|
|
179
179
|
* @returns {boolean} indicating whether the association / composition is a constraint candidate
|
|
180
180
|
*/
|
|
181
|
-
function hasConstraintCompliantOnCondition(element, siblingElements, path) {
|
|
181
|
+
function hasConstraintCompliantOnCondition( element, siblingElements, path ) {
|
|
182
182
|
const onCondition = element.on;
|
|
183
183
|
const allowedTokens = [ '=', 'and', '(', ')' ];
|
|
184
184
|
// on condition must only contain logical operator 'AND'
|
|
@@ -266,7 +266,7 @@ function createReferentialConstraints(csn, options) {
|
|
|
266
266
|
* @param {CSN.Association} element the composition or association
|
|
267
267
|
* @returns {boolean}
|
|
268
268
|
*/
|
|
269
|
-
function skipConstraintGeneration(parent, dependent, element) {
|
|
269
|
+
function skipConstraintGeneration( parent, dependent, element ) {
|
|
270
270
|
// if set to 'off' don't even bother, just skip all constraints
|
|
271
271
|
if (options.assertIntegrity === false || options.assertIntegrity === 'false')
|
|
272
272
|
return true;
|
|
@@ -390,7 +390,7 @@ function createReferentialConstraints(csn, options) {
|
|
|
390
390
|
* @param {string|boolean} value
|
|
391
391
|
* @returns {boolean}
|
|
392
392
|
*/
|
|
393
|
-
function isAssertIntegrityAnnotationSetTo(value) {
|
|
393
|
+
function isAssertIntegrityAnnotationSetTo( value ) {
|
|
394
394
|
return hasAnnotationValue(element, '@assert.integrity', value, true);
|
|
395
395
|
}
|
|
396
396
|
|
|
@@ -401,7 +401,7 @@ function createReferentialConstraints(csn, options) {
|
|
|
401
401
|
* @param {string} prop
|
|
402
402
|
* @param {object} val
|
|
403
403
|
*/
|
|
404
|
-
function assignPropOnBacklinkIfPossible(prop, val) {
|
|
404
|
+
function assignPropOnBacklinkIfPossible( prop, val ) {
|
|
405
405
|
if (!element.$selfOnCondition)
|
|
406
406
|
return;
|
|
407
407
|
const target = csn.definitions[element.target];
|
|
@@ -418,7 +418,7 @@ function createReferentialConstraints(csn, options) {
|
|
|
418
418
|
* @param {CSN.Composition} composition the composition which might be treated like an association
|
|
419
419
|
* @returns {boolean} true if the composition should be treated as an association in regards to foreign key constraints
|
|
420
420
|
*/
|
|
421
|
-
function treatCompositionLikeAssociation(composition) {
|
|
421
|
+
function treatCompositionLikeAssociation( composition ) {
|
|
422
422
|
return Boolean(isToOne(composition) && composition.keys);
|
|
423
423
|
}
|
|
424
424
|
|
|
@@ -428,7 +428,7 @@ function createReferentialConstraints(csn, options) {
|
|
|
428
428
|
* @param {CSN.Association|CSN.Composition} assocOrComposition
|
|
429
429
|
* @returns {boolean}
|
|
430
430
|
*/
|
|
431
|
-
function isToOne(assocOrComposition) {
|
|
431
|
+
function isToOne( assocOrComposition ) {
|
|
432
432
|
const { min, max } = assocOrComposition.cardinality || {};
|
|
433
433
|
return !min && !max || max === 1;
|
|
434
434
|
}
|
|
@@ -440,7 +440,7 @@ function createReferentialConstraints(csn, options) {
|
|
|
440
440
|
* @param {CSN.Elements} targetElements elements of association/composition target entity
|
|
441
441
|
* @returns {Map} of target elements with their name as key
|
|
442
442
|
*/
|
|
443
|
-
function elementsOfTargetSide(on, targetElements) {
|
|
443
|
+
function elementsOfTargetSide( on, targetElements ) {
|
|
444
444
|
const elements = new Map();
|
|
445
445
|
on.filter(element => typeof element === 'object' &&
|
|
446
446
|
element.ref.length > 1 &&
|
|
@@ -459,7 +459,7 @@ function createReferentialConstraints(csn, options) {
|
|
|
459
459
|
* @param {CSN.Elements} sourceElements elements of source entity where the association/composition is defined.
|
|
460
460
|
* @returns {Map} of source elements with their name as key
|
|
461
461
|
*/
|
|
462
|
-
function elementsOfSourceSide(on, sourceElements) {
|
|
462
|
+
function elementsOfSourceSide( on, sourceElements ) {
|
|
463
463
|
const elements = new Map();
|
|
464
464
|
on.filter(element => typeof element === 'object' &&
|
|
465
465
|
element.ref.length === 1 &&
|
|
@@ -481,7 +481,7 @@ function createReferentialConstraints(csn, options) {
|
|
|
481
481
|
* @param {CSN.Artifact} artifact
|
|
482
482
|
* @param {string} artifactName
|
|
483
483
|
*/
|
|
484
|
-
function collectAndAttachReferentialConstraints(artifact, artifactName) {
|
|
484
|
+
function collectAndAttachReferentialConstraints( artifact, artifactName ) {
|
|
485
485
|
const referentialConstraints = Object.create(null);
|
|
486
486
|
for (const elementName in artifact.elements) {
|
|
487
487
|
const element = artifact.elements[elementName];
|
|
@@ -546,7 +546,7 @@ function createReferentialConstraints(csn, options) {
|
|
|
546
546
|
* @param {CSN.Path} path
|
|
547
547
|
* @param {Function} error
|
|
548
548
|
*/
|
|
549
|
-
function assertConstraintIdentifierUniqueness(artifact, artifactName, path, error) {
|
|
549
|
+
function assertConstraintIdentifierUniqueness( artifact, artifactName, path, error ) {
|
|
550
550
|
// can only happen if referential & unique constraints are present
|
|
551
551
|
if (!(artifact.$tableConstraints && artifact.$tableConstraints.referential && artifact.$tableConstraints.unique))
|
|
552
552
|
return;
|
|
@@ -23,7 +23,7 @@ const { forEach } = require('../../utils/objectUtils');
|
|
|
23
23
|
* @param {Function} messageFunctions.throwWithAnyError
|
|
24
24
|
* @param {object} iterateOptions
|
|
25
25
|
*/
|
|
26
|
-
function expandStructureReferences(csn, options, pathDelimiter, { error, info, throwWithAnyError }, iterateOptions = {}) {
|
|
26
|
+
function expandStructureReferences( csn, options, pathDelimiter, { error, info, throwWithAnyError }, iterateOptions = {} ) {
|
|
27
27
|
const csnUtils = getUtils(csn);
|
|
28
28
|
const {
|
|
29
29
|
isStructured, get$combined, getFinalBaseTypeWithProps,
|
|
@@ -62,7 +62,7 @@ function expandStructureReferences(csn, options, pathDelimiter, { error, info, t
|
|
|
62
62
|
* For such skipped things, error for usage of assoc pointing to them and and ignore publishing of assoc pointing to them.
|
|
63
63
|
*/
|
|
64
64
|
function rewriteExpandInline() {
|
|
65
|
-
let cleanup;
|
|
65
|
+
let cleanup = [];
|
|
66
66
|
let _dependents;
|
|
67
67
|
|
|
68
68
|
const entity = findAnEntity();
|
|
@@ -81,7 +81,7 @@ function expandStructureReferences(csn, options, pathDelimiter, { error, info, t
|
|
|
81
81
|
* Do not remove unexpandable many columns in OData
|
|
82
82
|
*/
|
|
83
83
|
if (rewritten.toMany.length > 0 && !options.toOdata) {
|
|
84
|
-
|
|
84
|
+
markAsToDummify(artifact, path[1]);
|
|
85
85
|
error( null, [ 'definitions', path[1] ], { name: path[1] }, 'Unexpected .expand with to-many association in entity $(NAME)');
|
|
86
86
|
}
|
|
87
87
|
else {
|
|
@@ -96,12 +96,10 @@ function expandStructureReferences(csn, options, pathDelimiter, { error, info, t
|
|
|
96
96
|
if (!options.toOdata)
|
|
97
97
|
dummyfy();
|
|
98
98
|
|
|
99
|
-
|
|
100
|
-
cleanup.forEach(fn => fn());
|
|
99
|
+
cleanup.forEach(fn => fn());
|
|
101
100
|
|
|
102
101
|
({ effectiveType, inspectRef } = csnRefs(csn));
|
|
103
102
|
|
|
104
|
-
|
|
105
103
|
const publishing = [];
|
|
106
104
|
// OData must allow navigations to @cds.persistence.skip targets
|
|
107
105
|
// as valid navigations in the API
|
|
@@ -134,7 +132,7 @@ function expandStructureReferences(csn, options, pathDelimiter, { error, info, t
|
|
|
134
132
|
* @param {Array} parts
|
|
135
133
|
* @param {CSN.Path} path
|
|
136
134
|
*/
|
|
137
|
-
function check(parent, name, parts, path) {
|
|
135
|
+
function check( parent, name, parts, path ) {
|
|
138
136
|
const inColumns = name === 'columns';
|
|
139
137
|
const kill = [];
|
|
140
138
|
for (let i = 0; i < parts.length; i++) {
|
|
@@ -207,8 +205,8 @@ function expandStructureReferences(csn, options, pathDelimiter, { error, info, t
|
|
|
207
205
|
* @param {CSN.Artifact} artifact
|
|
208
206
|
* @param {string} name
|
|
209
207
|
*/
|
|
210
|
-
function
|
|
211
|
-
if (!_dependents &&
|
|
208
|
+
function markAsToDummify( artifact, name ) {
|
|
209
|
+
if (!_dependents && cleanup.length === 0)
|
|
212
210
|
({ cleanup, _dependents } = setDependencies(csn, csnUtils));
|
|
213
211
|
|
|
214
212
|
const stack = [ [ artifact, name ] ];
|
|
@@ -240,7 +238,7 @@ function expandStructureReferences(csn, options, pathDelimiter, { error, info, t
|
|
|
240
238
|
* @param {CSN.Artifact} base The current base
|
|
241
239
|
* @returns {CSN.Artifact}
|
|
242
240
|
*/
|
|
243
|
-
function nextBase(parent, base) {
|
|
241
|
+
function nextBase( parent, base ) {
|
|
244
242
|
if (parent.ref) {
|
|
245
243
|
const finalBaseType = getFinalBaseTypeWithProps(parent._art.type);
|
|
246
244
|
const art = parent._art;
|
|
@@ -262,7 +260,7 @@ function expandStructureReferences(csn, options, pathDelimiter, { error, info, t
|
|
|
262
260
|
* @param {string[]} excluding
|
|
263
261
|
* @returns {{columns: Array, toMany: Array}} Object with rewritten columns (.expand/.inline) and with any .expand + to-many
|
|
264
262
|
*/
|
|
265
|
-
function rewrite(root, columns, excluding) {
|
|
263
|
+
function rewrite( root, columns, excluding ) {
|
|
266
264
|
const allToMany = [];
|
|
267
265
|
const newThing = [];
|
|
268
266
|
const containsExpandInline = columns.some(col => col.expand || col.inline);
|
|
@@ -299,7 +297,7 @@ function expandStructureReferences(csn, options, pathDelimiter, { error, info, t
|
|
|
299
297
|
* @param {CSN.Element} obj
|
|
300
298
|
* @returns {boolean}
|
|
301
299
|
*/
|
|
302
|
-
function isToMany(obj) {
|
|
300
|
+
function isToMany( obj ) {
|
|
303
301
|
if (!obj._art)
|
|
304
302
|
return false;
|
|
305
303
|
const eType = effectiveType(obj._art);
|
|
@@ -318,7 +316,7 @@ function expandStructureReferences(csn, options, pathDelimiter, { error, info, t
|
|
|
318
316
|
* @param {Array} alias Any start-alias
|
|
319
317
|
* @returns {{expanded: Array, toManys: Array}} Object with expanded .expand/.inline and with any .expand + to-many
|
|
320
318
|
*/
|
|
321
|
-
function expandInline(root, col, ref, alias) {
|
|
319
|
+
function expandInline( root, col, ref, alias ) {
|
|
322
320
|
const toManys = [];
|
|
323
321
|
const expanded = [];
|
|
324
322
|
const stack = [ [ root, col, ref, alias ] ];
|
|
@@ -376,7 +374,7 @@ function expandStructureReferences(csn, options, pathDelimiter, { error, info, t
|
|
|
376
374
|
* @param {object} parent Thing that has an .xpr/.args
|
|
377
375
|
* @param {string[]} ref Ref so far
|
|
378
376
|
*/
|
|
379
|
-
function rewriteExpressionArrays(parent, ref) {
|
|
377
|
+
function rewriteExpressionArrays( parent, ref ) {
|
|
380
378
|
const stack = [ [ parent, ref ] ];
|
|
381
379
|
while (stack.length > 0) {
|
|
382
380
|
const [ current, currentRef ] = stack.pop();
|
|
@@ -397,7 +395,7 @@ function expandStructureReferences(csn, options, pathDelimiter, { error, info, t
|
|
|
397
395
|
* @param {object} parent
|
|
398
396
|
* @param {Array} ref The so-far effective name (basically the will-be alias), as an array to treat like a ref
|
|
399
397
|
*/
|
|
400
|
-
function rewriteOn(parent, ref) {
|
|
398
|
+
function rewriteOn( parent, ref ) {
|
|
401
399
|
const stack = [ [ parent, ref ] ];
|
|
402
400
|
while (stack.length > 0) {
|
|
403
401
|
const [ current, currentRef ] = stack.pop();
|
|
@@ -418,7 +416,7 @@ function expandStructureReferences(csn, options, pathDelimiter, { error, info, t
|
|
|
418
416
|
* @param {Array} currentRef
|
|
419
417
|
* @param {Array} stack
|
|
420
418
|
*/
|
|
421
|
-
function rewriteOnCondition(on, currentRef, stack) {
|
|
419
|
+
function rewriteOnCondition( on, currentRef, stack ) {
|
|
422
420
|
for (let i = 0; i < on.length; i++) {
|
|
423
421
|
const part = on[i];
|
|
424
422
|
if (part.ref && part.ref[0] !== '$self' && part.ref[0] !== '$projection') {
|
|
@@ -439,7 +437,7 @@ function expandStructureReferences(csn, options, pathDelimiter, { error, info, t
|
|
|
439
437
|
* @param {Array} currentRef
|
|
440
438
|
* @param {Array} stack
|
|
441
439
|
*/
|
|
442
|
-
function rewriteSingleExpressionArray(expressionArray, currentRef, stack) {
|
|
440
|
+
function rewriteSingleExpressionArray( expressionArray, currentRef, stack ) {
|
|
443
441
|
for (let i = 0; i < expressionArray.length; i++) {
|
|
444
442
|
const part = expressionArray[i];
|
|
445
443
|
if (part.ref) {
|
|
@@ -472,7 +470,7 @@ function expandStructureReferences(csn, options, pathDelimiter, { error, info, t
|
|
|
472
470
|
* @param {string} source
|
|
473
471
|
* @returns {CSN.Artifact}
|
|
474
472
|
*/
|
|
475
|
-
function createDummyView(source) {
|
|
473
|
+
function createDummyView( source ) {
|
|
476
474
|
const elements = Object.create(null);
|
|
477
475
|
elements.one = {
|
|
478
476
|
'@Core.Computed': true,
|
|
@@ -517,7 +515,7 @@ function expandStructureReferences(csn, options, pathDelimiter, { error, info, t
|
|
|
517
515
|
* @param {boolean} [withAlias=false] Whether to "expand" the (implicit) alias aswell.
|
|
518
516
|
* @returns {Array} New array - with all structured things expanded
|
|
519
517
|
*/
|
|
520
|
-
function expand(thing, path, withAlias = false) {
|
|
518
|
+
function expand( thing, path, withAlias = false ) {
|
|
521
519
|
const newThing = [];
|
|
522
520
|
for (let i = 0; i < thing.length; i++) {
|
|
523
521
|
const col = thing[i];
|
|
@@ -553,7 +551,7 @@ function expandStructureReferences(csn, options, pathDelimiter, { error, info, t
|
|
|
553
551
|
* @param {boolean} withAlias
|
|
554
552
|
* @returns {Array}
|
|
555
553
|
*/
|
|
556
|
-
function expandRef(art, ref, alias, isKey, withAlias) {
|
|
554
|
+
function expandRef( art, ref, alias, isKey, withAlias ) {
|
|
557
555
|
const expanded = [];
|
|
558
556
|
/** @type {Array<[CSN.Element, any[], any[]]>} */
|
|
559
557
|
const stack = [ [ art, ref, [ alias || ref[ref.length - 1] ] ] ];
|
|
@@ -588,7 +586,7 @@ function expandStructureReferences(csn, options, pathDelimiter, { error, info, t
|
|
|
588
586
|
* @param {object} part A thing with a ref/as/func
|
|
589
587
|
* @returns {string}
|
|
590
588
|
*/
|
|
591
|
-
function dbName(part) {
|
|
589
|
+
function dbName( part ) {
|
|
592
590
|
if (part.as)
|
|
593
591
|
return part.as;
|
|
594
592
|
else if (part.ref)
|
|
@@ -606,7 +604,7 @@ function expandStructureReferences(csn, options, pathDelimiter, { error, info, t
|
|
|
606
604
|
* @param {string[]} [excluding=[]]
|
|
607
605
|
* @returns {Array} If there was a star, expand it and handle shadowing/excluding, else just return subs
|
|
608
606
|
*/
|
|
609
|
-
function replaceStar(base, subs, excluding = []) {
|
|
607
|
+
function replaceStar( base, subs, excluding = [] ) {
|
|
610
608
|
const stars = [];
|
|
611
609
|
const names = Object.create(null);
|
|
612
610
|
for (let i = 0; i < subs.length; i++) {
|