@sap/cds-compiler 2.11.2 → 2.13.6
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 +175 -2
- package/bin/.eslintrc.json +1 -2
- package/bin/cds_update_identifiers.js +10 -8
- package/bin/cdsc.js +23 -17
- package/bin/cdsse.js +2 -2
- package/bin/cdsv2m.js +3 -2
- package/doc/CHANGELOG_ARCHIVE.md +1 -1
- package/doc/CHANGELOG_BETA.md +25 -6
- package/doc/CHANGELOG_DEPRECATED.md +22 -6
- package/doc/NameResolution.md +21 -16
- package/lib/api/main.js +32 -79
- package/lib/api/options.js +3 -2
- package/lib/api/validate.js +2 -1
- package/lib/backends.js +16 -26
- package/lib/base/dictionaries.js +0 -8
- package/lib/base/error.js +26 -0
- package/lib/base/keywords.js +10 -19
- package/lib/base/location.js +9 -4
- package/lib/base/message-registry.js +75 -9
- package/lib/base/messages.js +31 -35
- package/lib/base/model.js +2 -62
- package/lib/base/optionProcessorHelper.js +246 -183
- package/lib/checks/.eslintrc.json +2 -0
- package/lib/checks/actionsFunctions.js +2 -1
- package/lib/checks/annotationsOData.js +1 -1
- package/lib/checks/cdsPersistence.js +2 -1
- package/lib/checks/emptyOrOnlyVirtual.js +2 -2
- package/lib/checks/enricher.js +17 -1
- package/lib/checks/foreignKeys.js +4 -4
- package/lib/checks/invalidTarget.js +3 -1
- package/lib/checks/managedInType.js +4 -4
- package/lib/checks/managedWithoutKeys.js +3 -1
- package/lib/checks/queryNoDbArtifacts.js +1 -3
- package/lib/checks/selectItems.js +4 -4
- package/lib/checks/sql-snippets.js +94 -0
- package/lib/checks/types.js +1 -1
- package/lib/checks/unknownMagic.js +1 -1
- package/lib/checks/validator.js +12 -7
- package/lib/compiler/assert-consistency.js +12 -8
- package/lib/compiler/base.js +0 -1
- package/lib/compiler/builtins.js +42 -21
- package/lib/compiler/checks.js +46 -12
- package/lib/compiler/cycle-detector.js +1 -1
- package/lib/compiler/define.js +1103 -0
- package/lib/compiler/extend.js +983 -0
- package/lib/compiler/finalize-parse-cdl.js +231 -0
- package/lib/compiler/index.js +46 -39
- package/lib/compiler/kick-start.js +190 -0
- package/lib/compiler/moduleLayers.js +4 -4
- package/lib/compiler/populate.js +1226 -0
- package/lib/compiler/propagator.js +113 -47
- package/lib/compiler/resolve.js +1433 -0
- package/lib/compiler/shared.js +100 -65
- package/lib/compiler/tweak-assocs.js +529 -0
- package/lib/compiler/utils.js +215 -33
- package/lib/edm/.eslintrc.json +5 -0
- package/lib/edm/annotations/genericTranslation.js +38 -25
- package/lib/edm/annotations/preprocessAnnotations.js +3 -3
- package/lib/edm/csn2edm.js +10 -9
- package/lib/edm/edm.js +19 -20
- package/lib/edm/edmPreprocessor.js +166 -95
- package/lib/edm/edmUtils.js +127 -34
- package/lib/gen/Dictionary.json +92 -43
- package/lib/gen/language.checksum +1 -1
- package/lib/gen/language.interp +11 -1
- package/lib/gen/language.tokens +86 -82
- package/lib/gen/languageLexer.interp +18 -1
- package/lib/gen/languageLexer.js +925 -847
- package/lib/gen/languageLexer.tokens +78 -74
- package/lib/gen/languageParser.js +5434 -4298
- package/lib/json/from-csn.js +59 -17
- package/lib/json/to-csn.js +189 -71
- package/lib/language/antlrParser.js +3 -3
- package/lib/language/docCommentParser.js +3 -3
- package/lib/language/errorStrategy.js +26 -8
- package/lib/language/genericAntlrParser.js +144 -53
- package/lib/language/language.g4 +424 -200
- package/lib/language/multiLineStringParser.js +536 -0
- package/lib/main.d.ts +550 -61
- package/lib/main.js +38 -11
- package/lib/model/api.js +3 -1
- package/lib/model/csnRefs.js +322 -198
- package/lib/model/csnUtils.js +226 -370
- package/lib/model/enrichCsn.js +124 -69
- package/lib/model/revealInternalProperties.js +29 -7
- package/lib/model/sortViews.js +10 -2
- package/lib/modelCompare/compare.js +17 -12
- package/lib/optionProcessor.js +8 -3
- package/lib/render/.eslintrc.json +1 -2
- package/lib/render/DuplicateChecker.js +1 -1
- package/lib/render/manageConstraints.js +36 -33
- package/lib/render/toCdl.js +174 -275
- package/lib/render/toHdbcds.js +203 -122
- package/lib/render/toRename.js +7 -10
- package/lib/render/toSql.js +161 -82
- package/lib/render/utils/common.js +22 -8
- package/lib/render/utils/sql.js +10 -7
- package/lib/render/utils/stringEscapes.js +111 -0
- package/lib/sql-identifier.js +1 -1
- package/lib/transform/.eslintrc.json +5 -0
- package/lib/transform/braceExpression.js +4 -2
- package/lib/transform/db/.eslintrc.json +2 -0
- package/lib/transform/db/applyTransformations.js +212 -0
- package/lib/transform/db/assertUnique.js +1 -1
- package/lib/transform/db/associations.js +187 -0
- package/lib/transform/db/cdsPersistence.js +150 -0
- package/lib/transform/db/constraints.js +61 -56
- package/lib/transform/db/expansion.js +50 -29
- package/lib/transform/db/flattening.js +556 -106
- package/lib/transform/db/groupByOrderBy.js +3 -1
- package/lib/transform/db/temporal.js +236 -0
- package/lib/transform/db/transformExists.js +103 -28
- package/lib/transform/db/views.js +92 -44
- package/lib/transform/draft/.eslintrc.json +38 -0
- package/lib/transform/{db/draft.js → draft/db.js} +9 -7
- package/lib/transform/draft/odata.js +227 -0
- package/lib/transform/forHanaNew.js +98 -783
- package/lib/transform/forOdataNew.js +22 -175
- package/lib/transform/localized.js +36 -32
- package/lib/transform/odata/generateForeignKeyElements.js +3 -3
- package/lib/transform/odata/referenceFlattener.js +95 -89
- package/lib/transform/odata/structureFlattener.js +1 -1
- package/lib/transform/odata/toFinalBaseType.js +86 -12
- package/lib/transform/odata/typesExposure.js +5 -5
- package/lib/transform/odata/utils.js +2 -2
- package/lib/transform/transformUtilsNew.js +47 -33
- package/lib/transform/translateAssocsToJoins.js +13 -30
- package/lib/transform/universalCsn/.eslintrc.json +36 -0
- package/lib/transform/universalCsn/coreComputed.js +170 -0
- package/lib/transform/universalCsn/universalCsnEnricher.js +715 -0
- package/lib/transform/universalCsn/utils.js +63 -0
- package/lib/utils/file.js +8 -3
- package/lib/utils/objectUtils.js +30 -0
- package/lib/utils/timetrace.js +8 -2
- package/package.json +1 -1
- package/share/messages/README.md +26 -0
- package/lib/compiler/definer.js +0 -2349
- package/lib/compiler/resolver.js +0 -2922
- package/lib/transform/db/helpers.js +0 -58
- package/lib/transform/universalCsnEnricher.js +0 -67
package/lib/api/main.js
CHANGED
|
@@ -35,6 +35,7 @@ const propertyToCheck = {
|
|
|
35
35
|
|
|
36
36
|
const { cloneCsn } = require('../model/csnUtils');
|
|
37
37
|
const { toHdbcdsSource } = require('../render/toHdbcds');
|
|
38
|
+
const { ModelError } = require('../base/error');
|
|
38
39
|
|
|
39
40
|
const relevantGeneralOptions = [ /* for future generic options */ ];
|
|
40
41
|
const relevantOdataOptions = [ 'sqlMapping', 'odataFormat' ];
|
|
@@ -115,7 +116,7 @@ function checkPreTransformedCsn(csn, options, relevantOptionNames, warnAboutMism
|
|
|
115
116
|
* @returns {boolean} Return true if it is pre-transformed
|
|
116
117
|
*/
|
|
117
118
|
function isPreTransformed(csn, transformation) {
|
|
118
|
-
return csn.meta && csn.meta.transformation === transformation;
|
|
119
|
+
return csn && csn.meta && csn.meta.transformation === transformation;
|
|
119
120
|
}
|
|
120
121
|
|
|
121
122
|
/**
|
|
@@ -159,12 +160,13 @@ function cdl(csn, externalOptions = {}) {
|
|
|
159
160
|
* Transform a CSN like to.sql
|
|
160
161
|
*
|
|
161
162
|
* @param {CSN.Model} csn Plain input CSN
|
|
162
|
-
* @param {
|
|
163
|
+
* @param {SqlOptions} [options={}] Options
|
|
163
164
|
* @returns {CSN.Model} CSN transformed like to.sql
|
|
164
165
|
* @private
|
|
165
166
|
*/
|
|
166
167
|
function forSql(csn, options = {}) {
|
|
167
168
|
const internalOptions = prepareOptions.to.sql(options);
|
|
169
|
+
internalOptions.transformation = 'sql';
|
|
168
170
|
internalOptions.toSql.csn = true;
|
|
169
171
|
return backends.toSqlWithCsn(csn, internalOptions).csn;
|
|
170
172
|
}
|
|
@@ -172,7 +174,7 @@ function forSql(csn, options = {}) {
|
|
|
172
174
|
* Transform a CSN like to.hdi
|
|
173
175
|
*
|
|
174
176
|
* @param {CSN.Model} csn Plain input CSN
|
|
175
|
-
* @param {
|
|
177
|
+
* @param {HdiOptions} [options={}] Options
|
|
176
178
|
* @returns {CSN.Model} CSN transformed like to.hdi
|
|
177
179
|
* @private
|
|
178
180
|
*/
|
|
@@ -185,7 +187,7 @@ function forHdi(csn, options = {}) {
|
|
|
185
187
|
* Transform a CSN like to.hdbcds
|
|
186
188
|
*
|
|
187
189
|
* @param {CSN.Model} csn Plain input CSN
|
|
188
|
-
* @param {
|
|
190
|
+
* @param {HdbcdsOptions} [options={}] Options
|
|
189
191
|
* @returns {CSN.Model} CSN transformed like to.hdbcds
|
|
190
192
|
* @private
|
|
191
193
|
*/
|
|
@@ -202,11 +204,12 @@ function forHdbcds(csn, options = {}) {
|
|
|
202
204
|
* Process the given CSN into SQL.
|
|
203
205
|
*
|
|
204
206
|
* @param {CSN.Model} csn A clean input CSN
|
|
205
|
-
* @param {
|
|
207
|
+
* @param {SqlOptions} [options={}] Options
|
|
206
208
|
* @returns {SQL[]} Array of SQL statements, tables first, views second
|
|
207
209
|
*/
|
|
208
210
|
function sql(csn, options = {}) {
|
|
209
211
|
const internalOptions = prepareOptions.to.sql(options);
|
|
212
|
+
internalOptions.transformation = 'sql';
|
|
210
213
|
|
|
211
214
|
// we need the CSN for view sorting
|
|
212
215
|
internalOptions.toSql.csn = true;
|
|
@@ -222,7 +225,7 @@ function sql(csn, options = {}) {
|
|
|
222
225
|
* Process the given CSN into HDI artifacts.
|
|
223
226
|
*
|
|
224
227
|
* @param {CSN.Model} csn A clean input CSN
|
|
225
|
-
* @param {
|
|
228
|
+
* @param {HdiOptions} [options={}] Options
|
|
226
229
|
* @returns {HDIArtifacts} { <filename>:<content>, ...}
|
|
227
230
|
*/
|
|
228
231
|
function hdi(csn, options = {}) {
|
|
@@ -245,19 +248,19 @@ function hdi(csn, options = {}) {
|
|
|
245
248
|
const flat = flattenResultStructure(intermediateResult);
|
|
246
249
|
|
|
247
250
|
const nameMapping = Object.create(null);
|
|
248
|
-
const
|
|
249
|
-
const
|
|
251
|
+
const sqlArtifactsWithCSNNamesToSort = Object.create(null);
|
|
252
|
+
const sqlArtifactsNotToSort = Object.create(null);
|
|
250
253
|
|
|
251
254
|
Object.keys(flat).forEach((key) => {
|
|
252
255
|
const artifactNameLikeInCsn = key.replace(/\.[^/.]+$/, '');
|
|
253
256
|
nameMapping[artifactNameLikeInCsn] = key;
|
|
254
257
|
if (key.endsWith('.hdbtable') || key.endsWith('.hdbview'))
|
|
255
|
-
|
|
258
|
+
sqlArtifactsWithCSNNamesToSort[artifactNameLikeInCsn] = flat[key];
|
|
256
259
|
else
|
|
257
|
-
|
|
260
|
+
sqlArtifactsNotToSort[key] = flat[key];
|
|
258
261
|
});
|
|
259
262
|
|
|
260
|
-
const sorted = sortViews({ sql:
|
|
263
|
+
const sorted = sortViews({ sql: sqlArtifactsWithCSNNamesToSort, csn: sqlCSN })
|
|
261
264
|
.filter(obj => obj.sql)
|
|
262
265
|
.reduce((previous, current) => {
|
|
263
266
|
const hdiArtifactName = remapName(nameMapping[current.name], sqlCSN, k => !k.endsWith('.hdbindex'));
|
|
@@ -265,9 +268,9 @@ function hdi(csn, options = {}) {
|
|
|
265
268
|
return previous;
|
|
266
269
|
}, Object.create(null));
|
|
267
270
|
|
|
268
|
-
// now add the not-sorted stuff, like
|
|
269
|
-
Object.keys(
|
|
270
|
-
sorted[remapName(key, sqlCSN, k => !k.endsWith('.hdbindex'))] =
|
|
271
|
+
// now add the not-sorted stuff, like indices
|
|
272
|
+
Object.keys(sqlArtifactsNotToSort).forEach((key) => {
|
|
273
|
+
sorted[remapName(key, sqlCSN, k => !k.endsWith('.hdbindex'))] = sqlArtifactsNotToSort[key];
|
|
271
274
|
});
|
|
272
275
|
|
|
273
276
|
return sorted;
|
|
@@ -323,7 +326,7 @@ function remapName(key, csn, filter = () => true) {
|
|
|
323
326
|
* Note: Only supports changes in entities (not views etc.) compiled/rendered as HANA-CSN/SQL.
|
|
324
327
|
*
|
|
325
328
|
* @param {CSN.Model} csn A clean input CSN representing the desired "after-image"
|
|
326
|
-
* @param {
|
|
329
|
+
* @param {HdiOptions} options Options
|
|
327
330
|
* @param {CSN.Model} beforeImage A HANA-transformed CSN representing the "before-image", or null in case no such image
|
|
328
331
|
* is known, i.e. for the very first migration step
|
|
329
332
|
* @returns {object} - afterImage: The desired after-image in HANA-CSN format
|
|
@@ -344,8 +347,8 @@ function hdiMigration(csn, options, beforeImage) {
|
|
|
344
347
|
* This is for backward compatibility with @sap/cds@4.5.(2…3).
|
|
345
348
|
*
|
|
346
349
|
* @todo Remove in cds-compiler@2.x
|
|
347
|
-
* @param {
|
|
348
|
-
* @param {CSN.Model
|
|
350
|
+
* @param {HdiOptions|CSN.Model} inputOptions Options or CSN image
|
|
351
|
+
* @param {HdiOptions|CSN.Model} inputBeforeImage CSN image or options
|
|
349
352
|
* @returns {Array} Array where the real options come first
|
|
350
353
|
*/
|
|
351
354
|
function backwardCompatible(inputOptions, inputBeforeImage) {
|
|
@@ -436,7 +439,7 @@ hdi.migration = hdiMigration;
|
|
|
436
439
|
* Process the given CSN into HDBCDS artifacts.
|
|
437
440
|
*
|
|
438
441
|
* @param {any} csn A clean input CSN
|
|
439
|
-
* @param {
|
|
442
|
+
* @param {HdbcdsOptions} [options={}] Options
|
|
440
443
|
* @returns {HDBCDS} { <filename>:<content>, ...}
|
|
441
444
|
*/
|
|
442
445
|
function hdbcds(csn, options = {}) {
|
|
@@ -641,12 +644,18 @@ function publishCsnProcessor( processor, _name ) {
|
|
|
641
644
|
return processor( csn, options, ...args );
|
|
642
645
|
}
|
|
643
646
|
catch (err) {
|
|
644
|
-
if (err instanceof CompilationError || options.noRecompile)
|
|
645
|
-
|
|
647
|
+
if (err instanceof CompilationError || options.noRecompile || isPreTransformed(csn, 'odata')) // we cannot recompile a pre-transformed CSN
|
|
648
|
+
throw err;
|
|
649
|
+
|
|
650
|
+
if (options.testMode && !(err instanceof TypeError) &&
|
|
651
|
+
!(err instanceof ModelError))
|
|
646
652
|
throw err;
|
|
647
653
|
|
|
648
654
|
const { info } = makeMessageFunction( csn, options, 'compile' );
|
|
649
|
-
info( 'api-recompiled-csn', emptyLocation('csn.json'), {}, 'CSN input had to be recompiled' );
|
|
655
|
+
const msg = info( 'api-recompiled-csn', emptyLocation('csn.json'), {}, 'CSN input had to be recompiled' );
|
|
656
|
+
if (options.internalMsg)
|
|
657
|
+
msg.error = err; // Attach original error
|
|
658
|
+
|
|
650
659
|
// next line to be replaced by CSN parser call which reads the CSN object
|
|
651
660
|
const xsn = recompileX(csn, options);
|
|
652
661
|
const recompiledCsn = compactModel(xsn);
|
|
@@ -680,12 +689,6 @@ function publishCsnProcessor( processor, _name ) {
|
|
|
680
689
|
* @typedef {'plain' | 'quoted' | 'hdbcds' } NamingMode
|
|
681
690
|
*/
|
|
682
691
|
|
|
683
|
-
/**
|
|
684
|
-
* Available SQL change modes
|
|
685
|
-
*
|
|
686
|
-
* @typedef {'alter' | 'drop' } SqlChangeMode
|
|
687
|
-
*/
|
|
688
|
-
|
|
689
692
|
/**
|
|
690
693
|
* Available oData versions
|
|
691
694
|
*
|
|
@@ -698,56 +701,6 @@ function publishCsnProcessor( processor, _name ) {
|
|
|
698
701
|
* @typedef { 'structured' | 'flat' } oDataFormat
|
|
699
702
|
*/
|
|
700
703
|
|
|
701
|
-
/**
|
|
702
|
-
* Generally available options
|
|
703
|
-
*
|
|
704
|
-
* @typedef {object} Options
|
|
705
|
-
* @property {object} [beta] Enable experimental features - not for productive use!
|
|
706
|
-
* @property {boolean} [dependentAutoexposed=false] For dependent autoexposed entities (managed compositions, texts entity), follow name of base entity
|
|
707
|
-
* @property {boolean} [longAutoexposed=false] Deprecated: Produce long names (with underscores) for autoexposed entities
|
|
708
|
-
* @property {Map<string, number>} [severities={}] Map of message-id and severity that allows setting the severity for the given message
|
|
709
|
-
* @property {Array} [messages] Allows collecting all messages in the options instead of printing them to stderr.
|
|
710
|
-
*/
|
|
711
|
-
|
|
712
|
-
/**
|
|
713
|
-
* Options available for to.hdi
|
|
714
|
-
*
|
|
715
|
-
* @typedef {object} hdiOptions
|
|
716
|
-
* @property {NamingMode} [sqlMapping='plain'] Naming mode to use
|
|
717
|
-
* @property {SqlChangeMode} [sqlChangeMode='alter'] SQL change mode to use (for changed columns)
|
|
718
|
-
* @property {boolean} [allowCsnDowngrade=false] Allow downgrades of CSN major version (for modelCompare)
|
|
719
|
-
* @property {object} [beta] Enable experimental features - not for productive use!
|
|
720
|
-
* @property {boolean} [longAutoexposed=false] Deprecated: Produce long names (with underscores) for autoexposed entities
|
|
721
|
-
* @property {Map<string, number>} [severities={}] Map of message-id and severity that allows setting the severity for the given message
|
|
722
|
-
* @property {Array} [messages] Allows collecting all messages in the options instead of printing them to stderr.
|
|
723
|
-
*/
|
|
724
|
-
|
|
725
|
-
/**
|
|
726
|
-
* Options available for to.hdbcds
|
|
727
|
-
*
|
|
728
|
-
* @typedef {object} hdbcdsOptions
|
|
729
|
-
* @property {NamingMode} [sqlMapping='plain'] Naming mode to use
|
|
730
|
-
* @property {object} [beta] Enable experimental features - not for productive use!
|
|
731
|
-
* @property {boolean} [longAutoexposed=false] Deprecated: Produce long names (with underscores) for autoexposed entities
|
|
732
|
-
* @property {Map<string, number>} [severities={}] Map of message-id and severity that allows setting the severity for the given message
|
|
733
|
-
* @property {Array} [messages] Allows collecting all messages in the options instead of printing them to stderr.
|
|
734
|
-
*/
|
|
735
|
-
|
|
736
|
-
/**
|
|
737
|
-
* Options available for to.sql
|
|
738
|
-
*
|
|
739
|
-
* @typedef {object} sqlOptions
|
|
740
|
-
* @property {NamingMode} [sqlMapping='plain'] Naming mode to use
|
|
741
|
-
* @property {SQLDialect} [sqlDialect='sqlite'] SQL dialect to use
|
|
742
|
-
* @property {object} [variableReplacements] Object containing values for magic variables like "$user"
|
|
743
|
-
* @property {string} [variableReplacements.$user.locale] Value for the "$user.locale" variable
|
|
744
|
-
* @property {string} [variableReplacements.$user.id] Value for the "$userid" variable
|
|
745
|
-
* @property {object} [beta] Enable experimental features - not for productive use!
|
|
746
|
-
* @property {boolean} [longAutoexposed=false] Deprecated: Produce long names (with underscores) for autoexposed entities
|
|
747
|
-
* @property {Map<string, number>} [severities={}] Map of message-id and severity that allows setting the severity for the given message
|
|
748
|
-
* @property {Array} [messages] Allows collecting all messages in the options instead of printing them to stderr.
|
|
749
|
-
*/
|
|
750
|
-
|
|
751
704
|
/**
|
|
752
705
|
* A fresh (just compiled, not transformed) CSN
|
|
753
706
|
*
|
|
@@ -767,13 +720,13 @@ function publishCsnProcessor( processor, _name ) {
|
|
|
767
720
|
*/
|
|
768
721
|
|
|
769
722
|
/**
|
|
770
|
-
* A map of { <file.hdbcds>:<content> }.
|
|
723
|
+
* A map of { <file.hdbcds|hdbconstraint>:<content> }.
|
|
771
724
|
*
|
|
772
725
|
* @typedef {object} HDBCDS
|
|
773
726
|
*/
|
|
774
727
|
|
|
775
728
|
/**
|
|
776
|
-
* A map of { <file.hdbtable
|
|
729
|
+
* A map of { <file.hdbtable|hdbview|hdbconstraint...>:<content> }.
|
|
777
730
|
*
|
|
778
731
|
* @typedef {object} HDIArtifacts
|
|
779
732
|
*/
|
package/lib/api/options.js
CHANGED
|
@@ -49,6 +49,7 @@ const privateOptions = [
|
|
|
49
49
|
'traceParserAmb',
|
|
50
50
|
'testMode',
|
|
51
51
|
'testSortCsn',
|
|
52
|
+
'constraintsInCreateTable',
|
|
52
53
|
'integrityNotEnforced',
|
|
53
54
|
'integrityNotValidated',
|
|
54
55
|
'assertIntegrity',
|
|
@@ -83,9 +84,9 @@ function translateOptions(input = {}, defaults = {}, hardRequire = {},
|
|
|
83
84
|
for (const name of overallOptions) {
|
|
84
85
|
// Ensure that arrays are not passed as a reference!
|
|
85
86
|
// This caused issues with the way messages are handled in processMessages
|
|
86
|
-
if (Array.isArray(input[name]) && inputOptionNames.
|
|
87
|
+
if (Array.isArray(input[name]) && inputOptionNames.includes(name))
|
|
87
88
|
options[name] = [ ...input[name] ];
|
|
88
|
-
else if (inputOptionNames.
|
|
89
|
+
else if (inputOptionNames.includes(name))
|
|
89
90
|
options[name] = input[name];
|
|
90
91
|
}
|
|
91
92
|
|
package/lib/api/validate.js
CHANGED
|
@@ -25,13 +25,14 @@ const booleanValidator = {
|
|
|
25
25
|
/**
|
|
26
26
|
* Generate a Validator that validates that the
|
|
27
27
|
* input is a string and one of the available options.
|
|
28
|
+
* The validation of the option values is case-insensitive.
|
|
28
29
|
*
|
|
29
30
|
* @param {any} availableValues Available values
|
|
30
31
|
* @returns {Validator} Return a validator for a string in an expected range
|
|
31
32
|
*/
|
|
32
33
|
function generateStringValidator(availableValues) {
|
|
33
34
|
return {
|
|
34
|
-
validate: val => typeof val === 'string' && availableValues.
|
|
35
|
+
validate: val => typeof val === 'string' && availableValues.some( av => av.toLowerCase() === val.toLowerCase() ),
|
|
35
36
|
expected: (val) => {
|
|
36
37
|
return typeof val !== 'string' ? 'type string' : availableValues.join(', ');
|
|
37
38
|
},
|
package/lib/backends.js
CHANGED
|
@@ -279,7 +279,7 @@ function transformSQLOptions(model, options) {
|
|
|
279
279
|
|
|
280
280
|
if(options.toSql.dialect !== 'hana') {
|
|
281
281
|
// CDXCORE-465, 'quoted' and 'hdbcds' are to be used in combination with dialect 'hana' only
|
|
282
|
-
if(
|
|
282
|
+
if (options.toSql.names === 'quoted' || options.toSql.names === 'hdbcds') {
|
|
283
283
|
error(null, null, `Option "{ toSql.dialect: '${options.toSql.dialect}' }" can't be combined with "{ toSql.names: '${options.toSql.names}' }"`);
|
|
284
284
|
}
|
|
285
285
|
// No non-HANA SQL for HDI
|
|
@@ -296,17 +296,17 @@ function transformSQLOptions(model, options) {
|
|
|
296
296
|
// If among the options user, user.id or user.locale are specified via the CLI or
|
|
297
297
|
// via the API, then ensure that at the end there is a user option, which is an object and has(have)
|
|
298
298
|
// "id" and/or "locale" prop(s)
|
|
299
|
-
function transformUserOption(
|
|
299
|
+
function transformUserOption(userOptions) {
|
|
300
300
|
// move the user option value under user.id if specified as a string
|
|
301
|
-
if (
|
|
302
|
-
|
|
301
|
+
if (userOptions.user && typeof userOptions.user === 'string' || userOptions.user instanceof String) {
|
|
302
|
+
userOptions.user = { id: userOptions.user };
|
|
303
303
|
}
|
|
304
304
|
// move the locale option(if provided) under user.locale
|
|
305
|
-
if (
|
|
306
|
-
|
|
307
|
-
? Object.assign(
|
|
308
|
-
:
|
|
309
|
-
delete
|
|
305
|
+
if (userOptions.locale) {
|
|
306
|
+
userOptions.user = userOptions.user
|
|
307
|
+
? Object.assign(userOptions.user, { locale: userOptions.locale })
|
|
308
|
+
: { locale: userOptions.locale };
|
|
309
|
+
delete userOptions.locale;
|
|
310
310
|
}
|
|
311
311
|
}
|
|
312
312
|
}
|
|
@@ -389,18 +389,16 @@ function toRenameWithCsn(csn, options) {
|
|
|
389
389
|
let forHanaCsn = transformForHanaWithCsn(csn, mergeOptions(options, { forHana : options.toRename } ), 'to.rename');
|
|
390
390
|
// forHanaCsn looses empty contexts and services, add them again so that toRename can calculate the namespaces
|
|
391
391
|
forEachDefinition(csn, (artifact, artifactName) => {
|
|
392
|
-
if(
|
|
392
|
+
if((artifact.kind === 'context' || artifact.kind === 'service') && forHanaCsn.definitions[artifactName] === undefined) {
|
|
393
393
|
forHanaCsn.definitions[artifactName] = artifact;
|
|
394
394
|
}
|
|
395
395
|
});
|
|
396
396
|
|
|
397
397
|
// Assemble result
|
|
398
|
-
|
|
398
|
+
return {
|
|
399
399
|
rename : toRenameDdl(forHanaCsn, options),
|
|
400
400
|
options
|
|
401
401
|
};
|
|
402
|
-
|
|
403
|
-
return result;
|
|
404
402
|
}
|
|
405
403
|
|
|
406
404
|
function alterConstraintsWithCsn(csn, options) {
|
|
@@ -418,6 +416,10 @@ function alterConstraintsWithCsn(csn, options) {
|
|
|
418
416
|
names: names || 'plain'
|
|
419
417
|
}
|
|
420
418
|
|
|
419
|
+
// Also set new-style options
|
|
420
|
+
options.sqlDialect = 'hana';
|
|
421
|
+
options.sqlMapping = names || 'plain';
|
|
422
|
+
|
|
421
423
|
// Of course we want the database constraints
|
|
422
424
|
options.assertIntegrityType = 'DB';
|
|
423
425
|
|
|
@@ -434,19 +436,7 @@ function alterConstraintsWithCsn(csn, options) {
|
|
|
434
436
|
else
|
|
435
437
|
intermediateResult = manageConstraints(forSqlCsn, mergedOptions);
|
|
436
438
|
|
|
437
|
-
|
|
438
|
-
return intermediateResult;
|
|
439
|
-
|
|
440
|
-
// if in testmode, return a string containing all the artifacts
|
|
441
|
-
let resultString = '';
|
|
442
|
-
const extension = src && src === 'hdi' ? 'hdbconstraint' : 'sql';
|
|
443
|
-
for(const id in intermediateResult){
|
|
444
|
-
const initialComment = `--$ --- ${id}.${extension} ---\n\n`;
|
|
445
|
-
resultString += initialComment;
|
|
446
|
-
resultString += intermediateResult[id];
|
|
447
|
-
resultString += '\n\n'
|
|
448
|
-
}
|
|
449
|
-
return resultString;
|
|
439
|
+
return intermediateResult;
|
|
450
440
|
}
|
|
451
441
|
|
|
452
442
|
// ----------- toCsn -----------
|
package/lib/base/dictionaries.js
CHANGED
|
@@ -89,17 +89,9 @@ function pushToDict( dict, name, entry ) {
|
|
|
89
89
|
dict[name] = [entry];
|
|
90
90
|
}
|
|
91
91
|
|
|
92
|
-
function forEachInDict( dict, callback ) {
|
|
93
|
-
let r = Object.create(null);
|
|
94
|
-
for (let name of Object.keys(dict))
|
|
95
|
-
r[name] = callback( dict[name], name, dict );
|
|
96
|
-
return r;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
92
|
module.exports = {
|
|
100
93
|
dictAdd, dictForEach,
|
|
101
94
|
dictAddArray,
|
|
102
95
|
pushToDict,
|
|
103
|
-
forEachInDict,
|
|
104
96
|
}
|
|
105
97
|
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Use this class to indicate that an internal error was noticed.
|
|
5
|
+
* In testMode, these errors do _not_ trigger a recompilation.
|
|
6
|
+
*/
|
|
7
|
+
class CompilerAssertion extends Error {
|
|
8
|
+
constructor(message) {
|
|
9
|
+
super(message);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Use this class to indicate that something with the input CSN is wrong,
|
|
15
|
+
* which will be caught by the core compiler through recompiling the sources.
|
|
16
|
+
*/
|
|
17
|
+
class ModelError extends Error {
|
|
18
|
+
constructor(message) {
|
|
19
|
+
super(message);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
module.exports = {
|
|
24
|
+
CompilerAssertion,
|
|
25
|
+
ModelError,
|
|
26
|
+
};
|
package/lib/base/keywords.js
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { functionsWithoutParens } = require("../compiler/builtins");
|
|
4
|
+
|
|
1
5
|
module.exports = {
|
|
2
6
|
// CDL reserved keywords, used for automatic quoting in 'toCdl' renderer
|
|
3
7
|
// Keep in sync with reserved keywords in language.g4
|
|
@@ -11,7 +15,7 @@ module.exports = {
|
|
|
11
15
|
'DISTINCT',
|
|
12
16
|
'EXISTS',
|
|
13
17
|
'EXTRACT',
|
|
14
|
-
'FALSE',
|
|
18
|
+
'FALSE', // boolean
|
|
15
19
|
'FROM',
|
|
16
20
|
'IN',
|
|
17
21
|
'KEY',
|
|
@@ -22,28 +26,15 @@ module.exports = {
|
|
|
22
26
|
'ON',
|
|
23
27
|
'SELECT',
|
|
24
28
|
'SOME',
|
|
29
|
+
'WHEN',
|
|
25
30
|
'TRIM',
|
|
26
|
-
'TRUE',
|
|
31
|
+
'TRUE', // boolean
|
|
27
32
|
'WHERE',
|
|
28
33
|
'WITH',
|
|
29
34
|
],
|
|
30
35
|
// CDL functions, used for automatic quoting in 'toCdl' renderer,
|
|
31
36
|
// only relevant for element references of path length 1.
|
|
32
|
-
cdl_functions:
|
|
33
|
-
'CURRENT_CONNECTION',
|
|
34
|
-
'CURRENT_DATE',
|
|
35
|
-
'CURRENT_SCHEMA',
|
|
36
|
-
'CURRENT_TIME',
|
|
37
|
-
'CURRENT_TIMESTAMP',
|
|
38
|
-
'CURRENT_TRANSACTION_ISOLATION_LEVEL',
|
|
39
|
-
'CURRENT_USER',
|
|
40
|
-
'CURRENT_UTCDATE',
|
|
41
|
-
'CURRENT_UTCTIME',
|
|
42
|
-
'CURRENT_UTCTIMESTAMP',
|
|
43
|
-
'SESSION_USER',
|
|
44
|
-
'SYSTEM_USER',
|
|
45
|
-
'SYSUUID',
|
|
46
|
-
],
|
|
37
|
+
cdl_functions: functionsWithoutParens,
|
|
47
38
|
// SQLite keywords, used to warn in 'toSql' renderer with dialect 'sqlite'
|
|
48
39
|
// Taken from http://www.sqlite.org/draft/lang_keywords.html
|
|
49
40
|
// Better use keywords in tool/mkkeywordhash.c of a sqlite distribution.
|
|
@@ -194,7 +185,7 @@ module.exports = {
|
|
|
194
185
|
'OTHERS',
|
|
195
186
|
'TIES',
|
|
196
187
|
],
|
|
197
|
-
// HANA keywords, used for smart quoting in to-hdi.plain
|
|
188
|
+
// SAP HANA keywords, used for smart quoting in to-hdi.plain
|
|
198
189
|
// Taken from https://help.sap.com/viewer/7c78579ce9b14a669c1f3295b0d8ca16/Cloud/en-US/28bcd6af3eb6437892719f7c27a8a285.html
|
|
199
190
|
// Better use keywords in ptime/query/parser/syntax/qp_keyword.cc minus those
|
|
200
191
|
// in rule unreserved_keyword_column (=…_common - "CONSTRAINT") in
|
|
@@ -674,7 +665,7 @@ module.exports = {
|
|
|
674
665
|
'XMLTABLE',
|
|
675
666
|
'YEAR'
|
|
676
667
|
],
|
|
677
|
-
// HANA CDS keywords, used for smart quoting in to-hdbcds.plain
|
|
668
|
+
// SAP HANA CDS keywords, used for smart quoting in to-hdbcds.plain
|
|
678
669
|
hdbcds: [
|
|
679
670
|
'ALL', 'ALTER', 'AS',
|
|
680
671
|
'BEFORE', 'BEGIN', 'BOTH',
|
package/lib/base/location.js
CHANGED
|
@@ -12,6 +12,9 @@ const { copyPropIfExist } = require('../utils/objectUtils');
|
|
|
12
12
|
* @param {XSN.WithLocation} start
|
|
13
13
|
* @param {XSN.WithLocation} end
|
|
14
14
|
* @returns {CSN.Location}
|
|
15
|
+
*
|
|
16
|
+
* TODO: make this function a CDL parser-only function (i.e. there should be
|
|
17
|
+
* no need to use it outside), it is XSN-only anyway already now
|
|
15
18
|
*/
|
|
16
19
|
function combinedLocation( start, end ) {
|
|
17
20
|
if (!start || !start.location)
|
|
@@ -33,6 +36,8 @@ function combinedLocation( start, end ) {
|
|
|
33
36
|
*
|
|
34
37
|
* @param {string} filename
|
|
35
38
|
* @returns {CSN.Location}
|
|
39
|
+
*
|
|
40
|
+
* TODO: make this function redundant (XSN sparse locations project)
|
|
36
41
|
*/
|
|
37
42
|
function emptyLocation(filename) {
|
|
38
43
|
return {
|
|
@@ -50,6 +55,8 @@ function emptyLocation(filename) {
|
|
|
50
55
|
*
|
|
51
56
|
* @param {string} filename
|
|
52
57
|
* @returns {CSN.Location}
|
|
58
|
+
*
|
|
59
|
+
* TODO: make this function redundant (XSN sparse locations project)
|
|
53
60
|
*/
|
|
54
61
|
function emptyWeakLocation(filename) {
|
|
55
62
|
return {
|
|
@@ -63,6 +70,8 @@ function emptyWeakLocation(filename) {
|
|
|
63
70
|
* Returns a dummy location for built-in definitions.
|
|
64
71
|
*
|
|
65
72
|
* @returns {CSN.Location}
|
|
73
|
+
*
|
|
74
|
+
* TODO: make this function redundant (XSN sparse locations project)
|
|
66
75
|
*/
|
|
67
76
|
function builtinLocation() {
|
|
68
77
|
return emptyLocation('<built-in>');
|
|
@@ -140,10 +149,6 @@ function dictLocation( dict, extraLocation ) {
|
|
|
140
149
|
endCol: max.endCol,
|
|
141
150
|
};
|
|
142
151
|
}
|
|
143
|
-
dictLocation.end = (dict) => {
|
|
144
|
-
const loc = dictLocation( dict );
|
|
145
|
-
return loc && { file: loc.file, line: loc.endLine, col: loc.endCol };
|
|
146
|
-
};
|
|
147
152
|
|
|
148
153
|
function _objLocations( obj ) {
|
|
149
154
|
return Array.isArray(obj) ? obj.map( o => o.location ) : [ obj.location ];
|