@sap/cds-compiler 6.7.3 → 6.9.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 +70 -0
- package/README.md +4 -0
- package/bin/cdsc.js +5 -5
- package/bin/cdshi.js +1 -0
- package/bin/cdsse.js +1 -1
- package/lib/api/main.js +17 -9
- package/lib/api/options.js +5 -2
- package/lib/api/validate.js +1 -1
- package/lib/base/builtins.js +13 -9
- package/lib/{model → base}/csnRefs.js +8 -10
- package/lib/base/error.js +2 -0
- package/lib/base/message-registry.js +68 -4
- package/lib/base/messages.js +4 -2
- package/lib/{optionProcessor.js → base/optionProcessor.js} +5 -3
- package/lib/base/{model.js → specialOptions.js} +16 -39
- package/lib/checks/arrayOfs.js +1 -1
- package/lib/checks/elements.js +1 -1
- package/lib/checks/enricher.js +2 -2
- package/lib/checks/featureFlags.js +54 -24
- package/lib/checks/foreignKeys.js +1 -1
- package/lib/checks/invalidTarget.js +1 -1
- package/lib/checks/managedInType.js +1 -1
- package/lib/checks/onConditions.js +1 -1
- package/lib/checks/queryNoDbArtifacts.js +1 -1
- package/lib/checks/validator.js +10 -14
- package/lib/compiler/assert-consistency.js +11 -9
- package/lib/compiler/base.js +5 -1
- package/lib/compiler/builtins.js +1 -1
- package/lib/compiler/checks.js +3 -3
- package/lib/compiler/define.js +6 -3
- package/lib/{base → compiler}/dictionaries.js +4 -3
- package/lib/compiler/extend.js +121 -21
- package/lib/compiler/generate.js +2 -2
- package/lib/compiler/index.js +11 -3
- package/lib/compiler/kick-start.js +1 -1
- package/lib/compiler/lsp-api.js +3 -3
- package/lib/compiler/populate.js +6 -7
- package/lib/compiler/resolve.js +53 -36
- package/lib/compiler/shared.js +68 -18
- package/lib/compiler/tweak-assocs.js +2 -2
- package/lib/compiler/utils.js +28 -27
- package/lib/compiler/xpr-rewrite.js +3 -3
- package/lib/edm/EdmPrimitiveTypeDefinitions.js +4 -1
- package/lib/edm/annotations/edmJson.js +2 -4
- package/lib/edm/annotations/genericTranslation.js +51 -7
- package/lib/edm/csn2edm.js +3 -2
- package/lib/edm/edmAnnoPreprocessor.js +1 -1
- package/lib/edm/edmInboundChecks.js +2 -1
- package/lib/edm/edmPreprocessor.js +3 -3
- package/lib/edm/edmUtils.js +2 -2
- package/lib/gen/BaseParser.js +59 -108
- package/lib/gen/CdlGrammar.checksum +1 -1
- package/lib/gen/CdlParser.js +2052 -1965
- package/lib/gen/Dictionary.json +67 -7
- package/lib/json/from-csn.js +14 -14
- package/lib/json/to-csn.js +77 -38
- package/lib/main.js +3 -3
- package/lib/model/csnUtils.js +2 -2
- package/lib/modelCompare/compare.js +1 -1
- package/lib/modelCompare/utils/filter.js +1 -0
- package/lib/parsers/AstBuildingParser.js +83 -33
- package/lib/parsers/index.js +1 -1
- package/lib/render/manageConstraints.js +1 -1
- package/lib/render/toCdl.js +49 -30
- package/lib/render/toHdbcds.js +2 -2
- package/lib/render/toSql.js +16 -7
- package/lib/render/utils/common.js +11 -3
- package/lib/render/utils/sql.js +14 -5
- package/lib/render/utils/standardDatabaseFunctions.js +108 -99
- package/lib/sql-identifier.js +9 -1
- package/lib/{model → tool-lib}/enrichCsn.js +3 -2
- package/lib/{model → tool-lib}/revealInternalProperties.js +2 -1
- package/lib/transform/addTenantFields.js +1 -1
- package/lib/transform/db/applyTransformations.js +1 -1
- package/lib/transform/db/assertUnique.js +1 -1
- package/lib/transform/db/assocsToQueries/transformExists.js +1 -1
- package/lib/transform/db/backlinks.js +2 -2
- package/lib/transform/db/expansion.js +2 -2
- package/lib/transform/db/flattening.js +3 -4
- package/lib/transform/db/killAnnotations.js +1 -0
- package/lib/transform/db/processSqlServices.js +2 -1
- package/lib/transform/db/rewriteCalculatedElements.js +2 -2
- package/lib/transform/db/temporal.js +30 -5
- package/lib/transform/db/views.js +16 -20
- package/lib/transform/draft/db.js +1 -2
- package/lib/transform/effective/associations.js +1 -1
- package/lib/transform/effective/flattening.js +6 -5
- package/lib/transform/effective/main.js +24 -4
- package/lib/transform/effective/types.js +1 -1
- package/lib/transform/{odata/fioriTreeViews.js → fioriTreeViews.js} +48 -25
- package/lib/transform/forOdata.js +25 -7
- package/lib/transform/forRelationalDB.js +48 -12
- package/lib/transform/localized.js +2 -2
- package/lib/transform/odata/createForeignKeys.js +1 -1
- package/lib/transform/odata/flattening.js +2 -2
- package/lib/transform/odata/toFinalBaseType.js +3 -2
- package/lib/transform/odata/typesExposure.js +3 -2
- package/lib/transform/transformUtils.js +2 -2
- package/lib/transform/translateAssocsToJoins.js +2 -1
- package/lib/transform/tupleExpansion.js +44 -4
- package/lib/transform/universalCsn/universalCsnEnricher.js +7 -3
- package/lib/transform/universalCsn/utils.js +1 -1
- package/lib/{base → utils}/lazyload.js +9 -0
- package/lib/{base → utils}/node-helpers.js +2 -0
- package/lib/utils/objectUtils.js +29 -6
- package/lib/{base → utils}/optionProcessorHelper.js +16 -6
- package/package.json +3 -40
- /package/lib/{model → base}/cloneCsn.js +0 -0
- /package/lib/{model/api.js → base/model-api.js} +0 -0
- /package/lib/{api → base}/trace.js +0 -0
- /package/lib/{model → base}/xprAsTree.js +0 -0
- /package/lib/{inspect → tool-lib}/index.js +0 -0
- /package/lib/{inspect → tool-lib}/inspectModelStatistics.js +0 -0
- /package/lib/{inspect → tool-lib}/inspectPropagation.js +0 -0
- /package/lib/{inspect → tool-lib}/inspectUtils.js +0 -0
- /package/lib/{base → utils}/shuffle.js +0 -0
|
@@ -1,15 +1,10 @@
|
|
|
1
|
-
//
|
|
1
|
+
// Definitions for beta and deprecated options
|
|
2
2
|
|
|
3
|
-
//
|
|
4
|
-
//
|
|
3
|
+
// Normal options are in ../base/optionProcessor.js (and some other files),
|
|
4
|
+
// unfortunately partly non-grep-able (option `fooBar` is defined via `--foo-bar`)
|
|
5
5
|
|
|
6
6
|
'use strict';
|
|
7
7
|
|
|
8
|
-
const { forEach } = require('../utils/objectUtils');
|
|
9
|
-
|
|
10
|
-
// Normal options are in ../optionProcessor.js (and some other files),
|
|
11
|
-
// unfortunately partly non-grep-able (option `fooBar` is defined via `--foo-bar`)
|
|
12
|
-
|
|
13
8
|
/**
|
|
14
9
|
* Object of all available beta flags that will be enabled/disabled by `--beta-mode`
|
|
15
10
|
* through cdsc. Only intended for INTERNAL USE.
|
|
@@ -47,12 +42,12 @@ const availableDeprecatedFlags = {
|
|
|
47
42
|
ignoreSpecifiedQueryElements: true,
|
|
48
43
|
};
|
|
49
44
|
|
|
50
|
-
// Deprecated flags that were removed in
|
|
51
|
-
const
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
45
|
+
// Deprecated flags that were removed in newer version and are complained about.
|
|
46
|
+
const oldDeprecatedFlags = {
|
|
47
|
+
includesNonShadowedFirst: true,
|
|
48
|
+
eagerPersistenceForGeneratedEntities: true,
|
|
49
|
+
noKeyPropagationWithExpansions: true,
|
|
50
|
+
};
|
|
56
51
|
|
|
57
52
|
/**
|
|
58
53
|
* Test for early-adaptor feature, stored in option `beta`(new-style) / `betaMode`(old-style)
|
|
@@ -98,48 +93,30 @@ function isDeprecatedEnabled( options, feature = null ) {
|
|
|
98
93
|
}
|
|
99
94
|
|
|
100
95
|
/**
|
|
101
|
-
* In cds-compiler
|
|
96
|
+
* In the current cds-compiler, we might have removed old deprecated flags. That can lead to silent
|
|
102
97
|
* errors such as entity/view names changing. To ensure that the user is forced
|
|
103
98
|
* to change their code, emit an error if one of such removed flags was used.
|
|
104
99
|
*
|
|
105
100
|
* @param {CSN.Options} options
|
|
106
101
|
* @param error Error message function returned by makeMessageFunction().
|
|
107
102
|
*/
|
|
108
|
-
function checkRemovedDeprecatedFlags(
|
|
103
|
+
function checkRemovedDeprecatedFlags( { deprecated, messages }, { error } ) {
|
|
109
104
|
// Assume that we emitted these errors once if a message with this ID was found.
|
|
110
|
-
if (!
|
|
105
|
+
if (!deprecated || messages?.some( m => m.messageId === 'api-invalid-deprecated' ))
|
|
111
106
|
return;
|
|
112
107
|
|
|
113
|
-
|
|
114
|
-
if (
|
|
115
|
-
error('api-invalid-deprecated', null, { name: key },
|
|
116
|
-
|
|
108
|
+
Object.keys( deprecated ).forEach( ( key ) => {
|
|
109
|
+
if (deprecated[key] && oldDeprecatedFlags[key]) { // why testing the value of the option?
|
|
110
|
+
error( 'api-invalid-deprecated', null, { name: key },
|
|
111
|
+
'Deprecated flag $(NAME) has been removed in CDS compiler v6' );
|
|
117
112
|
}
|
|
118
113
|
});
|
|
119
114
|
}
|
|
120
115
|
|
|
121
|
-
/**
|
|
122
|
-
* Like `obj.prop = value`, but not contained in JSON / CSN
|
|
123
|
-
* It's important to set enumerable explicitly to false (although 'false' is the default),
|
|
124
|
-
* as else, if the property already exists, it keeps the old setting for enumerable.
|
|
125
|
-
*
|
|
126
|
-
* @param {object} obj
|
|
127
|
-
* @param {string} prop
|
|
128
|
-
* @param {any} value
|
|
129
|
-
*/
|
|
130
|
-
function setProp( obj, prop, value ) {
|
|
131
|
-
const descriptor = {
|
|
132
|
-
value, configurable: true, writable: true, enumerable: false,
|
|
133
|
-
};
|
|
134
|
-
Object.defineProperty( obj, prop, descriptor );
|
|
135
|
-
return value;
|
|
136
|
-
}
|
|
137
|
-
|
|
138
116
|
|
|
139
117
|
module.exports = {
|
|
140
118
|
isBetaEnabled,
|
|
141
119
|
availableBetaFlags,
|
|
142
120
|
isDeprecatedEnabled,
|
|
143
121
|
checkRemovedDeprecatedFlags,
|
|
144
|
-
setProp,
|
|
145
122
|
};
|
package/lib/checks/arrayOfs.js
CHANGED
package/lib/checks/elements.js
CHANGED
|
@@ -8,7 +8,7 @@ const {
|
|
|
8
8
|
} = require('../model/csnUtils');
|
|
9
9
|
const { isBuiltinType } = require('../base/builtins');
|
|
10
10
|
const { isGeoTypeName } = require('../compiler/builtins');
|
|
11
|
-
const { setProp } = require('../
|
|
11
|
+
const { setProp } = require('../utils/objectUtils');
|
|
12
12
|
// Only to be used with validator.js - a correct `this` value needs to be provided!
|
|
13
13
|
|
|
14
14
|
/**
|
package/lib/checks/enricher.js
CHANGED
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
|
|
5
5
|
'use strict';
|
|
6
6
|
|
|
7
|
-
const { csnRefs } = require('../
|
|
8
|
-
const { setProp } = require('../
|
|
7
|
+
const { csnRefs } = require('../base/csnRefs');
|
|
8
|
+
const { setProp } = require('../utils/objectUtils');
|
|
9
9
|
const { isAnnotationExpression } = require('../base/builtins');
|
|
10
10
|
|
|
11
11
|
/**
|
|
@@ -1,39 +1,69 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const { setProp } = require('../
|
|
3
|
+
const { setProp, forEachValue } = require('../utils/objectUtils');
|
|
4
4
|
const { featureFlags } = require('../transform/featureFlags');
|
|
5
5
|
const { isSqlService, isDummyService, isDataProductProductionService } = require('../transform/db/processSqlServices');
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
|
+
* Set a feature flag on the CSN model.
|
|
8
9
|
*
|
|
9
|
-
* @param {
|
|
10
|
+
* @param {CSN.Model} csn CSN model to set flag on
|
|
11
|
+
* @param {string} flag Flag name to set
|
|
12
|
+
*/
|
|
13
|
+
function setFeatureFlag( csn, flag ) {
|
|
14
|
+
if (!csn.meta)
|
|
15
|
+
setProp(csn, 'meta', {});
|
|
16
|
+
if (!csn.meta[featureFlags])
|
|
17
|
+
csn.meta[featureFlags] = {};
|
|
18
|
+
|
|
19
|
+
csn.meta[featureFlags][flag] = true;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Get a function that detects and sets feature flags for expand/inline columns in a query.
|
|
10
24
|
*
|
|
11
|
-
* @
|
|
25
|
+
* @param {CSN.Model} csn CSN model to set flags on
|
|
26
|
+
* @returns {Function} Function to call per query
|
|
12
27
|
*/
|
|
13
|
-
function
|
|
14
|
-
return function
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
28
|
+
function getQueryFeatureFlagSetter( csn ) {
|
|
29
|
+
return function setQueryFeatureFlags(query) {
|
|
30
|
+
const queryProp = query.SELECT ? 'SELECT' : 'projection';
|
|
31
|
+
query[queryProp]?.columns?.forEach((column) => {
|
|
32
|
+
if (column.expand || column.inline)
|
|
33
|
+
setFeatureFlag(csn, '$expandInline');
|
|
34
|
+
});
|
|
35
|
+
};
|
|
36
|
+
}
|
|
19
37
|
|
|
20
|
-
|
|
38
|
+
/**
|
|
39
|
+
* Get a function that detects and sets feature flags for entity/service definitions.
|
|
40
|
+
* That are calculated elements and SQL services.
|
|
41
|
+
*
|
|
42
|
+
* @param {CSN.Model} csn CSN model to set flags on
|
|
43
|
+
* @param {CSN.Options} options Compiler options
|
|
44
|
+
* @returns {Function} Function to call per definition
|
|
45
|
+
*/
|
|
46
|
+
function getDefinitionFeatureFlagSetter( csn, options ) {
|
|
47
|
+
return function setDefinitionFeatureFlags(def) {
|
|
48
|
+
if (def.kind === 'entity' && def.elements) {
|
|
49
|
+
forEachValue(def.elements, (element) => {
|
|
50
|
+
if (element.value)
|
|
51
|
+
setFeatureFlag(csn, '$calculatedElements');
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
else if (def.kind === 'service') {
|
|
55
|
+
if (isSqlService(def))
|
|
56
|
+
setFeatureFlag(csn, '$sqlService');
|
|
57
|
+
if (isDummyService(def, options))
|
|
58
|
+
setFeatureFlag(csn, '$dummyService');
|
|
59
|
+
if (isDataProductProductionService(def))
|
|
60
|
+
setFeatureFlag(csn, '$dataProductService');
|
|
61
|
+
}
|
|
21
62
|
};
|
|
22
63
|
}
|
|
23
64
|
|
|
24
|
-
// Export
|
|
65
|
+
// Export factory functions that create bound feature flag setters for use in transformation loops
|
|
25
66
|
module.exports = {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
inline: setFeatureFlag('$expandInline'),
|
|
29
|
-
kind: function setFeatureFlagForSqlService( artifact ) {
|
|
30
|
-
if (isSqlService(artifact))
|
|
31
|
-
setFeatureFlag( '$sqlService' ).call(this);
|
|
32
|
-
|
|
33
|
-
if (isDummyService(artifact, this.options))
|
|
34
|
-
setFeatureFlag( '$dummyService' ).call(this);
|
|
35
|
-
|
|
36
|
-
if (isDataProductProductionService(artifact, this.options))
|
|
37
|
-
setFeatureFlag( '$dataProductService' ).call(this);
|
|
38
|
-
},
|
|
67
|
+
getQueryFeatureFlagSetter,
|
|
68
|
+
getDefinitionFeatureFlagSetter,
|
|
39
69
|
};
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// Only to be used with validator.js - a correct this value needs to be provided!
|
|
4
4
|
|
|
5
5
|
const { ModelError } = require('../base/error');
|
|
6
|
-
const { setProp } = require('../
|
|
6
|
+
const { setProp } = require('../utils/objectUtils');
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* Assert that targets of associations and compositions are entities.
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
const { forEachGeneric } = require('../model/csnUtils');
|
|
4
4
|
const { otherSideIsExpandableStructure, resolveArtifactType } = require('./utils');
|
|
5
|
-
const { pathId } = require('../
|
|
5
|
+
const { pathId } = require('../base/csnRefs');
|
|
6
6
|
|
|
7
7
|
// Only to be used with validator.js - a correct this value needs to be provided!
|
|
8
8
|
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
const { isPersistedOnDatabase, applyTransformationsOnNonDictionary } = require('../model/csnUtils');
|
|
4
4
|
const { isBuiltinType } = require('../base/builtins');
|
|
5
5
|
const { requireForeignKeyAccess } = require('./onConditions');
|
|
6
|
-
const { pathId } = require('../
|
|
6
|
+
const { pathId } = require('../base/csnRefs');
|
|
7
7
|
|
|
8
8
|
const generalQueryProperties = [ 'from', 'columns', 'where', 'groupBy', 'orderBy', 'having', 'limit' ];
|
|
9
9
|
|
package/lib/checks/validator.js
CHANGED
|
@@ -18,7 +18,6 @@ const validateHasPersistedElements = require('./hasPersistedElements');
|
|
|
18
18
|
const checkForHanaTypes = require('./checkForTypes');
|
|
19
19
|
const { checkAnnotationExpression } = require('./structuredAnnoExpressions');
|
|
20
20
|
const checkForParams = require('./parameters');
|
|
21
|
-
const checkAndRemoveEnums = require('./enums');
|
|
22
21
|
// forOdata
|
|
23
22
|
const { validateDefaultValues } = require('./defaultValues');
|
|
24
23
|
const { checkActionOrFunction } = require('./actionsFunctions');
|
|
@@ -54,7 +53,6 @@ const {
|
|
|
54
53
|
checkSqlAnnotationOnElement,
|
|
55
54
|
} = require('./sql-snippets');
|
|
56
55
|
const assertNoAssocUsageOutsideOfService = require('./assocOutsideService');
|
|
57
|
-
const featureFlags = require('./featureFlags');
|
|
58
56
|
const { timetrace } = require('../utils/timetrace');
|
|
59
57
|
|
|
60
58
|
const forRelationalDBMemberValidators
|
|
@@ -94,7 +92,6 @@ const forRelationalDBCsnValidators = [
|
|
|
94
92
|
navigationIntoMany,
|
|
95
93
|
expandToMany,
|
|
96
94
|
checkPathsInStoredCalcElement,
|
|
97
|
-
featureFlags,
|
|
98
95
|
];
|
|
99
96
|
/**
|
|
100
97
|
* @type {Array<(query: CSN.Query, path: CSN.Path) => void>}
|
|
@@ -168,7 +165,7 @@ function _validate( csn, that,
|
|
|
168
165
|
// TODO: Don't know if that's feasible? Do we really need to enrich annotations always?
|
|
169
166
|
// const { cleanup } = enrich(csn, { processAnnotations: that.options.tranformation === 'odata' });
|
|
170
167
|
|
|
171
|
-
applyTransformations(csn, mergeTransformers(csnValidators, that), [], { drillRef: true });
|
|
168
|
+
applyTransformations(csn, mergeTransformers(csnValidators, that), [], { drillRef: true, ...iterateOptions });
|
|
172
169
|
|
|
173
170
|
forEachDefinition(csn, (artifact, artifactName, prop, path) => {
|
|
174
171
|
artifactValidators.forEach((artifactValidator) => {
|
|
@@ -201,10 +198,8 @@ function _validate( csn, that,
|
|
|
201
198
|
function getDBCsnValidators( options ) {
|
|
202
199
|
const validations = [ ...forRelationalDBCsnValidators ];
|
|
203
200
|
|
|
204
|
-
if (options.transformation !== 'effective')
|
|
205
|
-
validations.push(checkAndRemoveEnums);
|
|
201
|
+
if (options.transformation !== 'effective')
|
|
206
202
|
validations.push(checkForParams.csnValidator);
|
|
207
|
-
}
|
|
208
203
|
|
|
209
204
|
if (options.sqlDialect === 'h2' || options.sqlDialect === 'postgres')
|
|
210
205
|
validations.push(checkForHanaTypes);
|
|
@@ -221,7 +216,13 @@ function forRelationalDB( csn, that ) {
|
|
|
221
216
|
const memberValidators = [ ...forRelationalDBMemberValidators, ...commonMemberValidators ];
|
|
222
217
|
if (that.options.transformation === 'hdbcds')
|
|
223
218
|
memberValidators.push(checkForParams.memberValidator);
|
|
224
|
-
|
|
219
|
+
// skip artifacts / elements which are not persisted on the database from being validated
|
|
220
|
+
const iterateOptions = {
|
|
221
|
+
skipArtifact: artifact => artifact.abstract ||
|
|
222
|
+
hasPersistenceSkipAnnotation(artifact) ||
|
|
223
|
+
artifact['@cds.persistence.exists'] ||
|
|
224
|
+
[ 'action', 'function', 'event' ].includes(artifact.kind),
|
|
225
|
+
};
|
|
225
226
|
return _validate(csn, that,
|
|
226
227
|
getDBCsnValidators(that.options),
|
|
227
228
|
memberValidators,
|
|
@@ -246,12 +247,7 @@ function forRelationalDB( csn, that ) {
|
|
|
246
247
|
}
|
|
247
248
|
),
|
|
248
249
|
forRelationalDBQueryValidators.concat(commonQueryValidators),
|
|
249
|
-
|
|
250
|
-
skipArtifact: artifact => artifact.abstract ||
|
|
251
|
-
hasPersistenceSkipAnnotation(artifact) ||
|
|
252
|
-
artifact['@cds.persistence.exists'] ||
|
|
253
|
-
[ 'action', 'function', 'event' ].includes(artifact.kind),
|
|
254
|
-
});
|
|
250
|
+
iterateOptions);
|
|
255
251
|
}
|
|
256
252
|
|
|
257
253
|
/**
|
|
@@ -283,7 +283,7 @@ function assertConsistency( model, stage ) {
|
|
|
283
283
|
'quantifier', 'orderBy', 'limit', 'name', '$parens', 'kind',
|
|
284
284
|
'_origin', '$contains', // TODO tmp, see TODO in getOriginRaw()
|
|
285
285
|
'_parent', '_main', '_leadingQuery', '_effectiveType', '$effectiveSeqNo', // in FROM
|
|
286
|
-
'_$next', // parsing error: tableTerm with UNION on rhs.
|
|
286
|
+
'$expand', '_$next', // parsing error: tableTerm with UNION on rhs.
|
|
287
287
|
],
|
|
288
288
|
},
|
|
289
289
|
select: { // sub query
|
|
@@ -309,7 +309,7 @@ function assertConsistency( model, stage ) {
|
|
|
309
309
|
'on', '$parens', 'cardinality',
|
|
310
310
|
'kind', 'name', '_block', '_parent', '_main', '_user',
|
|
311
311
|
'$tableAliases', '_combined', '_joinParent', '$joinArgsIndex',
|
|
312
|
-
'_leadingQuery', '_$next', '_deps',
|
|
312
|
+
'_leadingQuery', '_$next', '_deps', '$expand',
|
|
313
313
|
],
|
|
314
314
|
},
|
|
315
315
|
ref: {
|
|
@@ -329,7 +329,7 @@ function assertConsistency( model, stage ) {
|
|
|
329
329
|
'$parens',
|
|
330
330
|
'kind', 'name', '_block', '_parent', '_main', 'elements',
|
|
331
331
|
'_effectiveType', '$effectiveSeqNo', '_origin', '_joinParent', '$joinArgsIndex',
|
|
332
|
-
'$duplicates', // duplicate query in FROM clause
|
|
332
|
+
'$expand', '$duplicates', // duplicate query in FROM clause
|
|
333
333
|
],
|
|
334
334
|
},
|
|
335
335
|
none: { optional: () => true }, // parse error
|
|
@@ -352,13 +352,13 @@ function assertConsistency( model, stage ) {
|
|
|
352
352
|
requires: [ 'location', 'name' ],
|
|
353
353
|
optional: [ '$duplicates' ],
|
|
354
354
|
},
|
|
355
|
-
orderBy: { inherits: 'value', test: isArray( expression ) },
|
|
355
|
+
orderBy: { kind: [ 'extend' ], inherits: 'value', test: isArray( expression ) },
|
|
356
356
|
sort: { test: locationVal( isString ), enum: [ 'asc', 'desc' ] },
|
|
357
357
|
nulls: { test: locationVal( isString ), enum: [ 'first', 'last' ] },
|
|
358
358
|
$orderBy: { inherits: 'orderBy' },
|
|
359
|
-
groupBy: { inherits: 'value', test: isArray( expression ) },
|
|
359
|
+
groupBy: { kind: [ 'extend' ], inherits: 'value', test: isArray( expression ) },
|
|
360
360
|
$limit: { test: TODO },
|
|
361
|
-
limit: { requires: [ 'rows' ], optional: [ 'offset', 'location' ] },
|
|
361
|
+
limit: { kind: [ 'extend' ], requires: [ 'rows' ], optional: [ 'offset', 'location' ] },
|
|
362
362
|
rows: { inherits: 'value' },
|
|
363
363
|
offset: { inherits: 'value' },
|
|
364
364
|
_combined: { test: TODO },
|
|
@@ -438,6 +438,8 @@ function assertConsistency( model, stage ) {
|
|
|
438
438
|
'location', '$inferred', 'sort', 'nulls',
|
|
439
439
|
'param', 'scope', // for dynamic parameter '?'
|
|
440
440
|
'args', 'op', 'func', 'suffix',
|
|
441
|
+
// needed for groupBy extensions - TODO: outside `value`:
|
|
442
|
+
'$extended', '_block', '_outer',
|
|
441
443
|
// calculated elements on-write - TODO: outside `value`
|
|
442
444
|
'stored',
|
|
443
445
|
],
|
|
@@ -512,8 +514,8 @@ function assertConsistency( model, stage ) {
|
|
|
512
514
|
test: args,
|
|
513
515
|
},
|
|
514
516
|
on: { kind: true, inherits: 'value', test: expression },
|
|
515
|
-
where: { inherits: 'value' },
|
|
516
|
-
having: { inherits: 'value' },
|
|
517
|
+
where: { kind: [ 'extend' ], inherits: 'value' },
|
|
518
|
+
having: { kind: [ 'extend' ], inherits: 'value' },
|
|
517
519
|
op: { test: locationVal( isString ) },
|
|
518
520
|
join: { test: locationVal( isString ) },
|
|
519
521
|
quantifier: { test: locationVal( isString ) },
|
|
@@ -736,7 +738,7 @@ function assertConsistency( model, stage ) {
|
|
|
736
738
|
$expand: {
|
|
737
739
|
kind: true,
|
|
738
740
|
// See description of `setExpandStatus()` of in `lib/compiler/utils.js`.
|
|
739
|
-
test: isOneOf( [ 'origin', 'annotate', '
|
|
741
|
+
test: isOneOf( [ 'origin', 'target', 'annotate', 'extend' ] ),
|
|
740
742
|
},
|
|
741
743
|
$inCycle: { kind: true, test: isBoolean },
|
|
742
744
|
|
package/lib/compiler/base.js
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
'use strict';
|
|
4
4
|
|
|
5
5
|
const { CompilerAssertion } = require( '../base/error' );
|
|
6
|
+
const $inferred = Symbol.for( 'cds.$inferred' );
|
|
6
7
|
|
|
7
8
|
const dictKinds = {
|
|
8
9
|
definitions: 'absolute',
|
|
@@ -67,7 +68,8 @@ const kindProperties = {
|
|
|
67
68
|
|
|
68
69
|
function propExists( prop, parent ) {
|
|
69
70
|
const obj = parent.returns || parent;
|
|
70
|
-
|
|
71
|
+
const members = (obj.items || obj.targetAspect || obj)[prop];
|
|
72
|
+
return members && !members[$inferred];
|
|
71
73
|
}
|
|
72
74
|
|
|
73
75
|
/**
|
|
@@ -90,6 +92,8 @@ function getArtifactName( art ) {
|
|
|
90
92
|
const namePath = [];
|
|
91
93
|
let parent = art._outer || art;
|
|
92
94
|
while (parent._main || parent.kind === 'builtin') { // until we hit the main artifact
|
|
95
|
+
if (!parent.name)
|
|
96
|
+
return '<error>';
|
|
93
97
|
if (parent.name.$inferred !== '$internal' || parent.kind === '$inline')
|
|
94
98
|
namePath.push( parent );
|
|
95
99
|
if (parent.kind === 'select')
|
package/lib/compiler/builtins.js
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
|
|
10
10
|
const { builtinLocation } = require('../base/location');
|
|
11
11
|
const { setLink } = require('./utils');
|
|
12
|
-
const { isBetaEnabled } = require('../base/
|
|
12
|
+
const { isBetaEnabled } = require('../base/specialOptions');
|
|
13
13
|
|
|
14
14
|
// TODO: make type parameters a dict
|
|
15
15
|
const core = {
|
package/lib/compiler/checks.js
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
|
|
10
10
|
'use strict';
|
|
11
11
|
|
|
12
|
-
const { isDeprecatedEnabled } = require('../base/
|
|
12
|
+
const { isDeprecatedEnabled } = require('../base/specialOptions');
|
|
13
13
|
const { propagationRules, acceptsExprValues } = require('../base/builtins');
|
|
14
14
|
const { typeParameters } = require('./builtins');
|
|
15
15
|
const {
|
|
@@ -132,8 +132,8 @@ function check( model ) {
|
|
|
132
132
|
typeName === 'cds.Vector' ||
|
|
133
133
|
typeName === 'cds.hana.CLOB' ||
|
|
134
134
|
typeName === 'cds.LargeBinary') {
|
|
135
|
-
warning( '
|
|
136
|
-
{
|
|
135
|
+
warning( 'type-invalid-for-key', [ elem.type?.location || elem.location, elem ],
|
|
136
|
+
{ type: typeName } );
|
|
137
137
|
}
|
|
138
138
|
}
|
|
139
139
|
|
package/lib/compiler/define.js
CHANGED
|
@@ -122,10 +122,10 @@
|
|
|
122
122
|
|
|
123
123
|
const { weakLocation, builtinLocation } = require('../base/location');
|
|
124
124
|
|
|
125
|
-
const shuffleGen = require('../
|
|
125
|
+
const shuffleGen = require('../utils/shuffle');
|
|
126
126
|
const {
|
|
127
127
|
dictAdd, dictAddArray, dictForEach, pushToDict,
|
|
128
|
-
} = require('
|
|
128
|
+
} = require('./dictionaries');
|
|
129
129
|
const { kindProperties } = require('./base');
|
|
130
130
|
const {
|
|
131
131
|
setLink,
|
|
@@ -724,6 +724,9 @@ function define( model ) {
|
|
|
724
724
|
// ORDER BY and LIMIT to be evaluated in leading query
|
|
725
725
|
}
|
|
726
726
|
else { // with parse error (`select from <EOF>`, `select from E { *, ( select }`)
|
|
727
|
+
// TODO: call initQuery() anyway to avoid Error[expr-no-subquery] also for
|
|
728
|
+
// UNIONs (test3/Queries/DollarSelf/CorruptedSource.err.cds), see also
|
|
729
|
+
// resolveExprNode()
|
|
727
730
|
return undefined;
|
|
728
731
|
}
|
|
729
732
|
return query._leadingQuery || query;
|
|
@@ -1004,7 +1007,7 @@ function define( model ) {
|
|
|
1004
1007
|
}
|
|
1005
1008
|
else if ((col.expand || col.value) &&
|
|
1006
1009
|
!path && // no parse error (path without last item)
|
|
1007
|
-
(insideExpand || query._parent
|
|
1010
|
+
(insideExpand || query._parent?.kind !== 'select')) { // not sub-selects
|
|
1008
1011
|
error( 'query-req-name',
|
|
1009
1012
|
// TODO: message function: `query` should work directly
|
|
1010
1013
|
[ (col.value || col).location, (query.name ? query : query._parent ) ],
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
//
|
|
3
3
|
// Warning: this is Core-compiler only stuff
|
|
4
4
|
|
|
5
|
+
// TODO: probably move to some future lib/xsn/
|
|
6
|
+
|
|
5
7
|
'use strict';
|
|
6
8
|
|
|
7
9
|
// New-style duplicate representation - use the style below for artifacts and
|
|
@@ -84,9 +86,8 @@ function dictAddArray( dict, name, entry, messageCallback ) {
|
|
|
84
86
|
function dictFirst( dict ) {
|
|
85
87
|
if (!dict)
|
|
86
88
|
return dict;
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
return undefined;
|
|
89
|
+
const names = Object.keys( dict );
|
|
90
|
+
return names.length ? dict[names[0]] : null;
|
|
90
91
|
}
|
|
91
92
|
|
|
92
93
|
// Push `entry` to the array value with key `name` in the dictionary `dict`.
|