@sap/cds 5.4.6 → 5.5.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 +208 -2
- package/apis/ql.d.ts +17 -15
- package/app/index.js +1 -1
- package/bin/build/buildTaskEngine.js +26 -42
- package/bin/build/buildTaskFactory.js +6 -10
- package/bin/build/buildTaskHandler.js +2 -4
- package/bin/build/buildTaskProvider.js +3 -1
- package/bin/build/buildTaskProviderFactory.js +9 -15
- package/bin/build/constants.js +15 -3
- package/bin/build/index.js +5 -4
- package/bin/build/mtaUtil.js +8 -11
- package/bin/build/provider/buildTaskHandlerEdmx.js +63 -6
- package/bin/build/provider/buildTaskHandlerInternal.js +2 -34
- package/bin/build/provider/buildTaskProviderInternal.js +16 -42
- package/bin/build/provider/fiori/index.js +13 -24
- package/bin/build/provider/hana/2migration.js +17 -15
- package/bin/build/provider/hana/2tabledata.js +52 -48
- package/bin/build/provider/hana/index.js +27 -25
- package/bin/build/provider/hana/migrationtable.js +91 -67
- package/bin/build/provider/java-cf/index.js +14 -24
- package/bin/build/provider/mtx/index.js +12 -14
- package/bin/build/provider/node-cf/index.js +18 -32
- package/bin/cds.js +5 -5
- package/bin/serve.js +29 -23
- package/bin/version.js +0 -1
- package/lib/compile/etc/_localized.js +4 -9
- package/lib/compile/for/sql.js +5 -2
- package/lib/compile/parse.js +25 -17
- package/lib/compile/to/srvinfo.js +2 -1
- package/lib/connect/bindings.js +2 -1
- package/lib/connect/index.js +48 -49
- package/lib/core/classes.js +1 -1
- package/lib/core/reflect.js +10 -2
- package/lib/deploy.js +26 -23
- package/lib/env/defaults.js +13 -6
- package/lib/env/index.js +73 -78
- package/lib/env/requires.js +38 -19
- package/lib/index.js +9 -10
- package/lib/lazy.js +2 -2
- package/lib/log/index.js +33 -45
- package/lib/log/service/index.js +2 -2
- package/lib/ql/CREATE.js +14 -9
- package/lib/ql/DELETE.js +6 -5
- package/lib/ql/DROP.js +12 -9
- package/lib/ql/INSERT.js +40 -16
- package/lib/ql/Query.js +67 -40
- package/lib/ql/SELECT.js +162 -127
- package/lib/ql/UPDATE.js +74 -42
- package/lib/ql/Whereable.js +77 -87
- package/lib/ql/index.js +36 -24
- package/lib/ql/parse.js +35 -0
- package/lib/req/context.js +44 -8
- package/lib/req/locale.js +7 -7
- package/lib/serve/Service-api.js +21 -14
- package/lib/serve/Service-dispatch.js +28 -12
- package/lib/serve/Transaction.js +22 -10
- package/lib/serve/index.js +16 -11
- package/lib/utils/axios.js +23 -16
- package/lib/utils/data.js +35 -0
- package/lib/utils/tests.js +27 -18
- package/libx/_runtime/audit/generic/personal/access.js +81 -0
- package/libx/_runtime/audit/generic/personal/constants.js +4 -0
- package/libx/_runtime/audit/generic/personal/index.js +50 -0
- package/libx/_runtime/audit/generic/personal/modification.js +138 -0
- package/libx/_runtime/audit/generic/personal/utils.js +186 -0
- package/libx/_runtime/audit/utils/v2.js +10 -4
- package/libx/_runtime/cds-services/adapter/odata-v4/Dispatcher.js +5 -5
- package/libx/_runtime/cds-services/adapter/odata-v4/OData.js +6 -7
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/action.js +5 -7
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/create.js +5 -7
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/delete.js +2 -3
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/error.js +4 -0
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/metadata.js +7 -4
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/read.js +59 -8
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/request.js +11 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/update.js +6 -10
- package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/ExpressionToCQN.js +3 -46
- package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/applyToCQN.js +2 -5
- package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/createToCQN.js +2 -2
- package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/deleteToCQN.js +4 -3
- package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/expandToCQN.js +1 -2
- package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/index.js +0 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/selectHelper.js +1 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/updateToCQN.js +2 -2
- package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/utils.js +16 -18
- package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-commons/edm/EdmEntityType.js +6 -3
- package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-commons/format/RepresentationKind.js +4 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/core/OdataRequest.js +1 -0
- package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/serializer/SerializerFactory.js +15 -2
- package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/validator/OperationValidator.js +1 -0
- package/libx/_runtime/cds-services/adapter/odata-v4/to.js +1 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/data.js +8 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/handlerUtils.js +6 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/omitValues.js +12 -5
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/readAfterWrite.js +1 -7
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/request.js +7 -7
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/result.js +14 -18
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/stream.js +13 -13
- package/libx/_runtime/cds-services/adapter/rest/handlers/create.js +0 -1
- package/libx/_runtime/cds-services/adapter/rest/handlers/operation.js +2 -1
- package/libx/_runtime/cds-services/adapter/rest/handlers/read.js +2 -2
- package/libx/_runtime/cds-services/adapter/rest/rest-to-cqn/index.js +2 -4
- package/libx/_runtime/cds-services/adapter/rest/utils/result.js +4 -2
- package/libx/_runtime/cds-services/services/Service.js +40 -5
- package/libx/_runtime/cds-services/services/utils/columns.js +13 -7
- package/libx/_runtime/cds-services/services/utils/compareJson.js +88 -4
- package/libx/_runtime/cds-services/services/utils/differ.js +24 -6
- package/libx/_runtime/cds-services/services/utils/handlerUtils.js +2 -2
- package/libx/_runtime/common/composition/data.js +44 -55
- package/libx/_runtime/common/composition/delete.js +97 -71
- package/libx/_runtime/common/composition/index.js +2 -1
- package/libx/_runtime/common/composition/insert.js +34 -11
- package/libx/_runtime/common/composition/tree.js +119 -92
- package/libx/_runtime/common/composition/update.js +4 -1
- package/libx/_runtime/common/composition/utils.js +1 -3
- package/libx/_runtime/common/constants/draft.js +12 -1
- package/libx/_runtime/common/generic/auth.js +6 -22
- package/libx/_runtime/common/generic/crud.js +14 -13
- package/libx/_runtime/common/generic/input.js +23 -26
- package/libx/_runtime/common/generic/put.js +1 -1
- package/libx/_runtime/common/generic/sorting.js +16 -16
- package/libx/_runtime/common/i18n/index.js +1 -1
- package/libx/_runtime/common/i18n/messages.properties +4 -0
- package/libx/_runtime/common/utils/backlinks.js +12 -5
- package/libx/_runtime/common/utils/cqn.js +6 -1
- package/libx/_runtime/common/utils/cqn2cqn4sql.js +102 -101
- package/libx/_runtime/common/utils/csn.js +47 -4
- package/libx/_runtime/common/utils/data.js +0 -37
- package/libx/_runtime/common/utils/enrichWithKeysFromWhere.js +1 -1
- package/libx/_runtime/common/utils/entityFromCqn.js +7 -24
- package/libx/_runtime/common/utils/foreignKeyPropagations.js +39 -7
- package/libx/_runtime/common/utils/generateOnCond.js +11 -12
- package/libx/_runtime/common/utils/onlyKeysRemain.js +10 -0
- package/libx/_runtime/common/utils/path.js +35 -0
- package/libx/_runtime/common/utils/postProcessing.js +86 -0
- package/libx/_runtime/common/utils/quotingStyles.js +37 -26
- package/libx/_runtime/common/utils/resolveView.js +223 -171
- package/libx/_runtime/common/utils/rewriteAsterisk.js +46 -26
- package/libx/_runtime/common/utils/structured.js +6 -12
- package/libx/_runtime/common/utils/template.js +10 -5
- package/libx/_runtime/common/utils/templateDelimiter.js +1 -0
- package/libx/_runtime/common/utils/templateProcessor.js +22 -30
- package/libx/_runtime/common/utils/union.js +31 -0
- package/libx/_runtime/common/utils/unionCqnTemplate.js +184 -0
- package/libx/_runtime/db/Service.js +1 -1
- package/libx/_runtime/db/data-conversion/timestamp.js +2 -9
- package/libx/_runtime/db/expand/expandCQNToJoin.js +204 -297
- package/libx/_runtime/db/expand/index.js +3 -3
- package/libx/_runtime/db/expand/rawToExpanded.js +36 -7
- package/libx/_runtime/db/generic/index.js +1 -1
- package/libx/_runtime/db/generic/input.js +5 -7
- package/libx/_runtime/db/generic/integrity.js +1 -1
- package/libx/_runtime/db/generic/rewrite.js +2 -10
- package/libx/_runtime/db/generic/update.js +13 -5
- package/libx/_runtime/db/generic/virtual.js +22 -58
- package/libx/_runtime/db/query/delete.js +7 -4
- package/libx/_runtime/db/query/insert.js +6 -4
- package/libx/_runtime/db/query/read.js +13 -20
- package/libx/_runtime/db/query/run.js +4 -1
- package/libx/_runtime/db/query/update.js +5 -4
- package/libx/_runtime/db/sql-builder/ExpressionBuilder.js +35 -2
- package/libx/_runtime/db/sql-builder/FunctionBuilder.js +17 -2
- package/libx/_runtime/db/sql-builder/InsertBuilder.js +6 -5
- package/libx/_runtime/db/sql-builder/ReferenceBuilder.js +10 -0
- package/libx/_runtime/db/sql-builder/SelectBuilder.js +35 -24
- package/libx/_runtime/db/sql-builder/UpdateBuilder.js +14 -4
- package/libx/_runtime/db/sql-builder/arrayed.js +4 -0
- package/libx/_runtime/db/utils/deep.js +8 -0
- package/libx/_runtime/db/utils/generateAliases.js +2 -1
- package/libx/_runtime/fiori/generic/activate.js +19 -15
- package/libx/_runtime/fiori/generic/before.js +3 -11
- package/libx/_runtime/fiori/generic/cancel.js +1 -1
- package/libx/_runtime/fiori/generic/delete.js +3 -1
- package/libx/_runtime/fiori/generic/edit.js +12 -2
- package/libx/_runtime/fiori/generic/new.js +5 -5
- package/libx/_runtime/fiori/generic/patch.js +0 -18
- package/libx/_runtime/fiori/generic/read.js +241 -189
- package/libx/_runtime/fiori/utils/delete.js +36 -7
- package/libx/_runtime/fiori/utils/handler.js +43 -44
- package/libx/_runtime/fiori/utils/where.js +30 -15
- package/libx/_runtime/hana/customBuilder/CustomSelectBuilder.js +4 -6
- package/libx/_runtime/hana/execute.js +2 -2
- package/libx/_runtime/hana/localized.js +4 -4
- package/libx/_runtime/hana/pool.js +29 -14
- package/libx/_runtime/hana/search2cqn4sql.js +2 -1
- package/libx/_runtime/hana/searchToContains.js +18 -14
- package/libx/_runtime/index.js +0 -5
- package/libx/_runtime/messaging/AMQPWebhookMessaging.js +13 -5
- package/libx/_runtime/messaging/common-utils/naming-conventions.js +4 -1
- package/libx/_runtime/messaging/enterprise-messaging-utils/EMManagement.js +31 -19
- package/libx/_runtime/messaging/enterprise-messaging-utils/registerEndpoints.js +1 -2
- package/libx/_runtime/messaging/enterprise-messaging.js +6 -4
- package/libx/_runtime/messaging/service.js +7 -6
- package/libx/_runtime/odata/cqn2odata.js +110 -43
- package/libx/_runtime/odata/index.js +26 -48
- package/libx/_runtime/odata/odata2cqn.js +1 -6154
- package/libx/_runtime/odata/odata2cqn.pegjs +559 -0
- package/libx/_runtime/odata/readToCqn.js +94 -64
- package/libx/_runtime/remote/Service.js +74 -21
- package/libx/_runtime/remote/cqn2odata/index.js +1 -5
- package/libx/_runtime/remote/utils/client.js +24 -101
- package/libx/_runtime/remote/utils/dataConversion.js +27 -12
- package/libx/_runtime/sqlite/Service.js +3 -5
- package/libx/_runtime/sqlite/execute.js +23 -24
- package/libx/_runtime/sqlite/localized.js +12 -7
- package/libx/_runtime/types/api.js +10 -0
- package/package.json +1 -1
- package/server.js +16 -2
- package/lib/ql/grammar.pegjs +0 -208
- package/lib/ql/parser.js +0 -1
- package/lib/ql/rt/DELETE.js +0 -29
- package/lib/ql/rt/INSERT.js +0 -23
- package/lib/ql/rt/Query.js +0 -84
- package/lib/ql/rt/SELECT.js +0 -174
- package/lib/ql/rt/UPDATE.js +0 -119
- package/lib/ql/rt/_helpers.js +0 -91
- package/lib/ql/rt/index.js +0 -32
- package/libx/_runtime/audit/generic/personal.js +0 -260
- package/libx/_runtime/cds-services/statements/BaseStatement.js +0 -72
- package/libx/_runtime/cds-services/statements/Create.js +0 -57
- package/libx/_runtime/cds-services/statements/Delete.js +0 -33
- package/libx/_runtime/cds-services/statements/Drop.js +0 -42
- package/libx/_runtime/cds-services/statements/Insert.js +0 -201
- package/libx/_runtime/cds-services/statements/Select.js +0 -826
- package/libx/_runtime/cds-services/statements/Update.js +0 -181
- package/libx/_runtime/cds-services/statements/Where.js +0 -726
- package/libx/_runtime/cds-services/statements/index.js +0 -25
- package/libx/_runtime/common/generic/resolve-mock.js +0 -9
|
@@ -1,42 +1,46 @@
|
|
|
1
|
-
const
|
|
2
|
-
const _warn = (message) => { console.error ('[WARNING] [hdbtabledata] -', message) } // eslint-disable-line
|
|
3
|
-
const cds = require ('../../cds')
|
|
1
|
+
const cds = require('../../cds')
|
|
4
2
|
const CSV = require('../../csv-reader')
|
|
5
|
-
const { getElementCdsPersistenceName, getArtifactCdsPersistenceName } = require
|
|
3
|
+
const { getElementCdsPersistenceName, getArtifactCdsPersistenceName } = require('@sap/cds-compiler')
|
|
4
|
+
const { LOG_MODULE_NAMES } = require('../../constants')
|
|
6
5
|
const { fs, path, isdir } = cds.utils
|
|
7
6
|
const { readdir } = fs.promises
|
|
7
|
+
let logger = cds.log(LOG_MODULE_NAMES)
|
|
8
|
+
|
|
9
|
+
module.exports = async (model, options = {}) => {
|
|
10
|
+
if (options.logger) {
|
|
11
|
+
logger = options.logger
|
|
12
|
+
}
|
|
8
13
|
|
|
9
|
-
module.exports = async (model, options={}) => {
|
|
10
14
|
const baseDir = options.baseDir // where the hdbtabledata will be located, for usage in the file_name path
|
|
11
|
-
const dirs = Array.isArray(options.dirs) ? options.dirs : _csvDirs
|
|
12
|
-
if (dirs.length === 0)
|
|
15
|
+
const dirs = Array.isArray(options.dirs) ? options.dirs : _csvDirs(model.$sources.map(path.dirname))
|
|
16
|
+
if (dirs.length === 0) return [] // nothing to do
|
|
13
17
|
const naming = options.sqlMapping || options.names || cds.env.sql.names
|
|
14
18
|
|
|
15
19
|
const datas = (await Promise.all(dirs.map(async dir => {
|
|
16
20
|
let files = []
|
|
17
21
|
if (isdir(dir)) {
|
|
18
|
-
files = await readdir
|
|
22
|
+
files = await readdir(dir)
|
|
19
23
|
}
|
|
20
|
-
return Promise.all(files.filter
|
|
24
|
+
return Promise.all(files.filter(_csvs).map(file => _tabledata4(dir, file, cds.linked(model), baseDir, naming)))
|
|
21
25
|
})))
|
|
22
|
-
|
|
23
|
-
return _toOutput
|
|
26
|
+
.reduce((a, b) => a.concat(b), [])
|
|
27
|
+
return _toOutput(datas)
|
|
24
28
|
}
|
|
25
29
|
|
|
26
|
-
async function _tabledata4
|
|
30
|
+
async function _tabledata4(dir, csvFile, model, baseDir, naming) {
|
|
27
31
|
const baseFileName = path.parse(csvFile).name
|
|
28
|
-
const entityName = baseFileName.replace(/-/g,'.')
|
|
29
|
-
const entity = _entity4
|
|
32
|
+
const entityName = baseFileName.replace(/-/g, '.')
|
|
33
|
+
const entity = _entity4(entityName, model)
|
|
30
34
|
if (!entity) {
|
|
31
35
|
let message = `no entity '${entityName}' found for CSV file '${path.relative(process.cwd(), path.join(dir, csvFile))}'`
|
|
32
36
|
const candidate = Object.keys(model.definitions)
|
|
33
37
|
.filter(name => !name.startsWith('localized.'))
|
|
34
|
-
.find
|
|
35
|
-
if (candidate)
|
|
36
|
-
return
|
|
38
|
+
.find(name => name.toLowerCase().includes(entityName.toLowerCase()))
|
|
39
|
+
if (candidate) message += `. Did you mean '${candidate}'?`
|
|
40
|
+
return logger.warn(`[hdbtabledata] ${message}`)
|
|
37
41
|
}
|
|
38
42
|
|
|
39
|
-
const tableName = getArtifactCdsPersistenceName
|
|
43
|
+
const tableName = getArtifactCdsPersistenceName(entity.name, naming, model)
|
|
40
44
|
const tabledata = { format_version: 1, imports: [] }
|
|
41
45
|
const _import = {
|
|
42
46
|
target_table: tableName,
|
|
@@ -47,84 +51,84 @@ async function _tabledata4 (dir, csvFile, model, baseDir, naming) {
|
|
|
47
51
|
|
|
48
52
|
const file = path.join(dir, csvFile)
|
|
49
53
|
const reader = fs.createReadStream(file)
|
|
50
|
-
const { cols, delimiter } = await CSV.readHeader
|
|
51
|
-
if (cols.length === 0)
|
|
54
|
+
const { cols, delimiter } = await CSV.readHeader(reader)
|
|
55
|
+
if (cols.length === 0) return // no columns at all -> skip import
|
|
52
56
|
|
|
53
57
|
cols.forEach(csvCol => {
|
|
54
58
|
// Only translate the column name, but do not check for the existence of the element in the model.
|
|
55
59
|
// This gets tricky for foreign key elements, and the DB deployment anyways checks the column.
|
|
56
|
-
const tableCol = getElementCdsPersistenceName
|
|
57
|
-
_import.import_settings.import_columns.push
|
|
60
|
+
const tableCol = getElementCdsPersistenceName(csvCol, naming)
|
|
61
|
+
_import.import_settings.import_columns.push(tableCol)
|
|
58
62
|
_import.column_mappings[tableCol] = csvCol
|
|
59
63
|
})
|
|
60
64
|
|
|
61
65
|
_import.source_data.type_config.delimiter = delimiter
|
|
62
66
|
|
|
63
67
|
// add a locale filter for mono-lingual files that refer to generated text tables
|
|
64
|
-
if (entity.elements.locale)
|
|
65
|
-
const locale = /_texts_(.+)\.csv$/.test
|
|
68
|
+
if (entity.elements.locale) {
|
|
69
|
+
const locale = /_texts_(.+)\.csv$/.test(csvFile) ? RegExp.$1 : null
|
|
66
70
|
if (locale) {
|
|
67
|
-
const localeKey = getElementCdsPersistenceName
|
|
68
|
-
_import.import_settings.include_filter.push
|
|
71
|
+
const localeKey = getElementCdsPersistenceName(entity.elements.locale.name/*usually 'LOCALE'*/, naming)
|
|
72
|
+
_import.import_settings.include_filter.push({ [localeKey]: locale })
|
|
69
73
|
}
|
|
70
74
|
}
|
|
71
75
|
|
|
72
|
-
tabledata.imports.push
|
|
76
|
+
tabledata.imports.push(_import)
|
|
73
77
|
const suffix = '.hdbtabledata'
|
|
74
78
|
return [
|
|
75
79
|
tabledata, {
|
|
76
80
|
name: baseFileName, suffix,
|
|
77
81
|
file: baseFileName + suffix,
|
|
78
|
-
folder: (baseDir||dir), // as metadata, add the dir to which the csvs are relative to
|
|
82
|
+
folder: (baseDir || dir), // as metadata, add the dir to which the csvs are relative to
|
|
79
83
|
csvFolder: dir
|
|
80
84
|
}
|
|
81
85
|
]
|
|
82
86
|
}
|
|
83
87
|
|
|
84
|
-
function _entity4
|
|
85
|
-
const entity = csn.definitions
|
|
88
|
+
function _entity4(name, csn) {
|
|
89
|
+
const entity = csn.definitions[name]
|
|
86
90
|
if (!entity) {
|
|
87
|
-
if (/(.+)[._]texts_?/.test
|
|
88
|
-
const base = csn.definitions
|
|
91
|
+
if (/(.+)[._]texts_?/.test(name)) { // 'Books_texts', 'Books_texts_de'
|
|
92
|
+
const base = csn.definitions[RegExp.$1]
|
|
89
93
|
if (base && base.elements && base.elements.texts) {
|
|
90
|
-
return _entity4
|
|
94
|
+
return _entity4(base.elements.texts.target, csn)
|
|
91
95
|
}
|
|
92
96
|
}
|
|
93
97
|
return
|
|
94
98
|
}
|
|
95
|
-
if (entity['@cds.persistence.skip'] === true)
|
|
99
|
+
if (entity['@cds.persistence.skip'] === true) return logger.warn(`[hdbtabledata] exclude skipped entity '${name}'`)
|
|
96
100
|
const p = entity.query && entity.query.SELECT || entity.projection
|
|
97
101
|
if (p) {
|
|
98
102
|
let from = p.from
|
|
99
103
|
if (from && from.ref && from.ref.length === 1) {
|
|
100
|
-
return _entity4
|
|
104
|
+
return _entity4(from.ref[0], csn)
|
|
101
105
|
}
|
|
102
106
|
}
|
|
103
107
|
return entity
|
|
104
108
|
}
|
|
105
109
|
|
|
106
|
-
function _csvDirs
|
|
107
|
-
sources = Array.from
|
|
110
|
+
function _csvDirs(sources) {
|
|
111
|
+
sources = Array.from(new Set(sources)) // uniq
|
|
108
112
|
const folders = []
|
|
109
113
|
for (let src of sources) {
|
|
110
|
-
for (let data of ['/data','/csv']) {
|
|
111
|
-
for (let each of [
|
|
112
|
-
let folder = path.resolve
|
|
113
|
-
if (isdir
|
|
114
|
+
for (let data of ['/data', '/csv']) {
|
|
115
|
+
for (let each of [src + data, src + '/src' + data, src + '/..' + data]) {
|
|
116
|
+
let folder = path.resolve(cds.root, each)
|
|
117
|
+
if (isdir(folder)) folders.push(folder)
|
|
114
118
|
}
|
|
115
119
|
}
|
|
116
120
|
}
|
|
117
121
|
return folders
|
|
118
122
|
}
|
|
119
123
|
|
|
120
|
-
function _csvs
|
|
121
|
-
if (filename[0] === '-' || !filename.endsWith
|
|
124
|
+
function _csvs(filename, _, allFiles) {
|
|
125
|
+
if (filename[0] === '-' || !filename.endsWith('.csv')) return false
|
|
122
126
|
// ignores 'Books_texts.csv' if there is any 'Books_texts_LANG.csv'
|
|
123
|
-
if (/(.*)[._]texts\.csv$/.test
|
|
127
|
+
if (/(.*)[._]texts\.csv$/.test(filename)) {
|
|
124
128
|
const basename = RegExp.$1
|
|
125
|
-
const monoLangFiles = allFiles.filter
|
|
129
|
+
const monoLangFiles = allFiles.filter(file => new RegExp(basename + '_texts_').test(file))
|
|
126
130
|
if (monoLangFiles.length > 0) {
|
|
127
|
-
|
|
131
|
+
logger._debug && logger.debug(`[hdbtabledata] ignoring '${filename}' in favor of [${monoLangFiles}]`)
|
|
128
132
|
return false
|
|
129
133
|
}
|
|
130
134
|
}
|
|
@@ -132,8 +136,8 @@ function _csvs (filename,_,allFiles) {
|
|
|
132
136
|
}
|
|
133
137
|
|
|
134
138
|
// generator function compliant to what `cds.compile.to` backends can return
|
|
135
|
-
function* _toOutput
|
|
139
|
+
function* _toOutput(datas) {
|
|
136
140
|
for (let i = 0; i < datas.length; i++) {
|
|
137
|
-
if (datas[i])
|
|
141
|
+
if (datas[i]) yield datas[i]
|
|
138
142
|
}
|
|
139
143
|
}
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
const {fs} = require('@sap/cds-foss')
|
|
1
|
+
const { fs } = require('@sap/cds-foss')
|
|
2
2
|
const path = require('path')
|
|
3
3
|
const BuildTaskHandlerInternal = require('../buildTaskHandlerInternal')
|
|
4
4
|
const { getHanaDbModuleDescriptor } = require('../../mtaUtil')
|
|
5
|
-
const { OUTPUT_MODE_RESULT_ONLY, BUILD_OPTION_OUTPUT_MODE,
|
|
5
|
+
const { OUTPUT_MODE_RESULT_ONLY, BUILD_OPTION_OUTPUT_MODE, SKIP_HDBTABLEDATA_GENERATION, SKIP_PACKAGE_JSON_GENERATION,
|
|
6
|
+
SKIP_MANIFEST_GENERATION, CONTENT_MANIFEST, CONTENT_PACKAGE_JSON, CONTENT_HDBTABLEDATA } = require('../../constants')
|
|
6
7
|
const { BuildError, setProperty, relativePaths } = require('../../util')
|
|
7
8
|
const CSV = require('../../csv-reader')
|
|
8
9
|
const to_hdbmigration = require('./2migration')
|
|
9
10
|
const to_hdbtabledata = require('./2tabledata')
|
|
10
11
|
const { ERROR } = require('../../buildTaskHandler')
|
|
11
12
|
|
|
12
|
-
const DEBUG = process.env.DEBUG
|
|
13
13
|
const DEFAULT_COMPILE_DEST_FOLDER = path.normalize("src/gen")
|
|
14
14
|
|
|
15
15
|
const FILE_EXT_CSV = ".csv"
|
|
@@ -31,6 +31,11 @@ class HanaModuleBuilder extends BuildTaskHandlerInternal {
|
|
|
31
31
|
dest: this.task.dest,
|
|
32
32
|
hana: []
|
|
33
33
|
}
|
|
34
|
+
// set unified option values in order to easy access later on
|
|
35
|
+
this.task.options[CONTENT_MANIFEST] = !this.hasBuildOption(CONTENT_MANIFEST, false) && !this.hasBuildOption(SKIP_MANIFEST_GENERATION, true) ? true : false
|
|
36
|
+
this.task.options[CONTENT_PACKAGE_JSON] = !this.hasBuildOption(CONTENT_PACKAGE_JSON, false) && !this.hasBuildOption(SKIP_PACKAGE_JSON_GENERATION, true) ? true : false
|
|
37
|
+
this.task.options[CONTENT_HDBTABLEDATA] = !this.hasBuildOption(CONTENT_HDBTABLEDATA, false) && !this.hasBuildOption(SKIP_HDBTABLEDATA_GENERATION, true) ? true : false
|
|
38
|
+
|
|
34
39
|
this.task.options.compileDest = path.resolve(this.task.dest, this.task.options.compileDest || DEFAULT_COMPILE_DEST_FOLDER)
|
|
35
40
|
}
|
|
36
41
|
|
|
@@ -60,13 +65,13 @@ class HanaModuleBuilder extends BuildTaskHandlerInternal {
|
|
|
60
65
|
await this._writeHdiConfig(plugins)
|
|
61
66
|
await this._writeHdiNamespace()
|
|
62
67
|
|
|
63
|
-
if (
|
|
68
|
+
if (this.hasBuildOption(CONTENT_HDBTABLEDATA, true)) {
|
|
64
69
|
await this._compileToHdbtabledata(model, dest)
|
|
65
70
|
}
|
|
66
|
-
if (
|
|
71
|
+
if (this.hasBuildOption(CONTENT_PACKAGE_JSON, true)) {
|
|
67
72
|
await this._writePackageJson()
|
|
68
73
|
}
|
|
69
|
-
if (
|
|
74
|
+
if (this.hasBuildOption(CONTENT_MANIFEST, true)) {
|
|
70
75
|
await this._writeManifestYml()
|
|
71
76
|
await this._writeCfIgnore()
|
|
72
77
|
}
|
|
@@ -97,14 +102,15 @@ class HanaModuleBuilder extends BuildTaskHandlerInternal {
|
|
|
97
102
|
const dbCsvDir = path.join(src, "csv")
|
|
98
103
|
const dbDataDir = path.join(src, "data")
|
|
99
104
|
const csvDirs = [dbCsvDir, dbDataDir]
|
|
105
|
+
const regex = RegExp('\\.cds$|\\.csv$|\\.hdbtabledata$')
|
|
106
|
+
const regexData = RegExp('\\.csv$|\\.hdbtabledata$')
|
|
100
107
|
|
|
101
108
|
await super.copyNativeContent(src, dest, (entry) => {
|
|
102
109
|
if (fs.statSync(entry).isDirectory()) {
|
|
103
110
|
return true // using common filter for folders
|
|
104
111
|
}
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
((extName === FILE_EXT_CSV || extName === FILE_EXT_HDBTABLEDATA) && !entry.startsWith(dbCsvDir) && !entry.startsWith(dbCsvDir))
|
|
112
|
+
return (!regex.test(entry) && entry !== this.env.build.outputfile) ||
|
|
113
|
+
(regexData.test(entry) && !entry.startsWith(dbCsvDir) && !entry.startsWith(dbCsvDir))
|
|
108
114
|
}) || []
|
|
109
115
|
|
|
110
116
|
// handle *.csv and *.hdbtabledata located in '<dbSrc>/data' and '<dbSrc>/csv' folder
|
|
@@ -113,8 +119,7 @@ class HanaModuleBuilder extends BuildTaskHandlerInternal {
|
|
|
113
119
|
if (fs.statSync(entry).isDirectory()) {
|
|
114
120
|
return false
|
|
115
121
|
}
|
|
116
|
-
|
|
117
|
-
return (extName === FILE_EXT_CSV || extName === FILE_EXT_HDBTABLEDATA)
|
|
122
|
+
return regexData.test(entry)
|
|
118
123
|
}))
|
|
119
124
|
}, [])
|
|
120
125
|
|
|
@@ -162,8 +167,9 @@ class HanaModuleBuilder extends BuildTaskHandlerInternal {
|
|
|
162
167
|
|
|
163
168
|
const promises = []
|
|
164
169
|
const relDest = path.relative(this.task.dest, this.task.options.compileDest)
|
|
170
|
+
const options = { ...this.options(), dirs: csvDirs, baseDir: this.task.options.compileDest }
|
|
165
171
|
|
|
166
|
-
const tableDatas = await to_hdbtabledata(model,
|
|
172
|
+
const tableDatas = await to_hdbtabledata(model, options)
|
|
167
173
|
for (let [tableData, { file, csvFolder }] of tableDatas) {
|
|
168
174
|
// create .hdbtabledata side-by-side if .csv is contained in 'src/gen/**' subfolder
|
|
169
175
|
// otherwise create in 'src/gen'
|
|
@@ -261,8 +267,8 @@ class HanaModuleBuilder extends BuildTaskHandlerInternal {
|
|
|
261
267
|
if (!this.hasBuildOption(BUILD_OPTION_OUTPUT_MODE, OUTPUT_MODE_RESULT_ONLY)) {
|
|
262
268
|
promises.push(this.write(content).to(path.join(dbSrcDir, file)))
|
|
263
269
|
}
|
|
264
|
-
} else
|
|
265
|
-
this.logger.
|
|
270
|
+
} else {
|
|
271
|
+
this.logger._debug && this.logger.debug(`no change, keep existing ${file}`)
|
|
266
272
|
}
|
|
267
273
|
} else {
|
|
268
274
|
this._result.hana.push(path.join(relDestDir, file))
|
|
@@ -294,8 +300,8 @@ class HanaModuleBuilder extends BuildTaskHandlerInternal {
|
|
|
294
300
|
const packageJson = path.join(this.task.src, "package.json")
|
|
295
301
|
const exists = await fs.pathExists(packageJson)
|
|
296
302
|
|
|
297
|
-
if (
|
|
298
|
-
this.logger.
|
|
303
|
+
if (exists) {
|
|
304
|
+
this.logger._debug && this.logger.debug(`skip create [${relativePaths(this.buildOptions.root, packageJson)}], already existing`)
|
|
299
305
|
}
|
|
300
306
|
if (this.isStagingBuild() && !exists) {
|
|
301
307
|
const content = await this._readTemplateAsJson(FILE_NAME_PACKAGE_JSON)
|
|
@@ -354,9 +360,7 @@ class HanaModuleBuilder extends BuildTaskHandlerInternal {
|
|
|
354
360
|
return
|
|
355
361
|
}
|
|
356
362
|
if (await fs.pathExists(path.join(this.task.src, FILE_NAME_MANIFEST_YML)) || await fs.pathExists(path.join(this.task.src, 'manifest.yml'))) {
|
|
357
|
-
|
|
358
|
-
this.logger.log('[cds] - skip cf manifest generation, already existing')
|
|
359
|
-
}
|
|
363
|
+
this.logger.debug('skip cf manifest generation, already existing')
|
|
360
364
|
return
|
|
361
365
|
}
|
|
362
366
|
try {
|
|
@@ -373,10 +377,8 @@ applications:
|
|
|
373
377
|
services:
|
|
374
378
|
- ${descriptor.hdiServiceName}`
|
|
375
379
|
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
this.logger.log(` cf cs hana hdi-shared ${descriptor.hdiServiceName}`)
|
|
379
|
-
}
|
|
380
|
+
this.logger.debug("Cloud Foundry service binding required for HDI container. To create a service use CF command")
|
|
381
|
+
this.logger._debug && this.logger.debug(` cf cs hana hdi-shared ${descriptor.hdiServiceName}`)
|
|
380
382
|
|
|
381
383
|
await this.write(MANIFEST_YML_CONTENT).to(path.join(this.task.dest, FILE_NAME_MANIFEST_YML))
|
|
382
384
|
} catch (e) {
|
|
@@ -413,11 +415,11 @@ applications:
|
|
|
413
415
|
return fs.statSync(res).isFile() && path.extname(res) === FILE_EXT_HDBMIGRATIONTABLE
|
|
414
416
|
})
|
|
415
417
|
if (migrationTableFiles.length > 0) {
|
|
416
|
-
const
|
|
418
|
+
const parser = require('./migrationtable')
|
|
417
419
|
|
|
418
420
|
await Promise.all(migrationTableFiles.map(async file => {
|
|
419
421
|
try {
|
|
420
|
-
const tableModel = await
|
|
422
|
+
const tableModel = await parser.read(file)
|
|
421
423
|
if (tableModel && /^>>>>>/m.test(tableModel.migrations.toString())) {
|
|
422
424
|
this.pushMessage(`Current model changes require manual resolution. See migration file ${path.relative(this.buildOptions.root, file)} for further details.`, ERROR)
|
|
423
425
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const {fs} = require('@sap/cds-foss')
|
|
1
|
+
const { fs } = require('@sap/cds-foss')
|
|
2
2
|
|
|
3
3
|
class MigrationTableParser {
|
|
4
4
|
constructor() {
|
|
@@ -27,15 +27,15 @@ class MigrationTableParser {
|
|
|
27
27
|
|
|
28
28
|
_validate(lines) {
|
|
29
29
|
let isTableBegin = false, isTableEnd = false, isMigration = false
|
|
30
|
-
let
|
|
31
|
-
lines.
|
|
32
|
-
if (
|
|
33
|
-
|
|
30
|
+
let tVersion, mVersion = -1
|
|
31
|
+
for (let idx = 0; idx < lines.length; idx++) {
|
|
32
|
+
if (MigrationTableParser._isVersionMarker(lines[idx])) {
|
|
33
|
+
tVersion = MigrationTableParser._parseVersionNumber(lines[idx])
|
|
34
34
|
if (isTableBegin || isTableEnd || isMigration) {
|
|
35
35
|
throw new Error(`Invalid format, version defintion must be very first statement`)
|
|
36
36
|
}
|
|
37
|
-
} else if (/^\s*COLUMN TABLE\s/.test(
|
|
38
|
-
if (
|
|
37
|
+
} else if (/^\s*COLUMN TABLE\s/.test(lines[idx])) {
|
|
38
|
+
if (tVersion === -1) {
|
|
39
39
|
throw new Error(`Invalid format, version entry not complying to format '^== version=d+'`)
|
|
40
40
|
}
|
|
41
41
|
if (isTableBegin) {
|
|
@@ -45,55 +45,66 @@ class MigrationTableParser {
|
|
|
45
45
|
throw new Error(`Invalid format, migrations must not be mixed with COLUMN TABLE definitions`)
|
|
46
46
|
}
|
|
47
47
|
isTableBegin = true
|
|
48
|
-
} else if (
|
|
49
|
-
|
|
50
|
-
throw new Error(`Invalid format, multiple COLUMN TABLE matching closing brackets found`)
|
|
51
|
-
}
|
|
52
|
-
if (isMigration) {
|
|
53
|
-
throw new Error(`Invalid format, migrations must not be mixed with COLUMN TABLE definitions`)
|
|
54
|
-
}
|
|
55
|
-
isTableEnd = true
|
|
56
|
-
} else if (!isMigration && /^\s*== migration=\d+\s*$/.test(line)) {
|
|
57
|
-
if (!new RegExp(`^\\s*== migration=${version}\\s*$`).test(line)) {
|
|
58
|
-
throw new Error(`Invalid format, migration and table version number do not match'`)
|
|
59
|
-
}
|
|
48
|
+
} else if (MigrationTableParser._isMigrationMarker(lines[idx])) {
|
|
49
|
+
const version = MigrationTableParser._parseVersionNumber(lines[idx])
|
|
60
50
|
if (version === -1) {
|
|
61
51
|
throw new Error(`Invalid format, migration entry not complying to format '^== version=d+'`)
|
|
62
52
|
}
|
|
63
|
-
if (
|
|
64
|
-
|
|
53
|
+
if (version > mVersion) {
|
|
54
|
+
mVersion = version
|
|
65
55
|
}
|
|
66
|
-
if (!
|
|
67
|
-
|
|
56
|
+
if (!isMigration) {
|
|
57
|
+
if (!isTableBegin) {
|
|
58
|
+
throw new Error(`Invalid format, COLUMN TABLE statement missing`)
|
|
59
|
+
}
|
|
60
|
+
// back search for end table
|
|
61
|
+
for (let tIdx = idx - 1; tIdx > 0; tIdx--) {
|
|
62
|
+
if (MigrationTableParser._isDDL(lines[tIdx])
|
|
63
|
+
|| MigrationTableParser._isComment(lines[tIdx])) {
|
|
64
|
+
isTableEnd = true
|
|
65
|
+
break
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
isMigration = true
|
|
68
69
|
}
|
|
69
|
-
|
|
70
|
+
} else if (isTableBegin && !isMigration && idx + 1 === lines.length) {
|
|
71
|
+
isTableEnd = true
|
|
70
72
|
}
|
|
71
|
-
}
|
|
73
|
+
}
|
|
72
74
|
if (!isTableBegin) {
|
|
73
75
|
throw new Error(`Invalid format, COLUMN TABLE statement missing`)
|
|
74
76
|
}
|
|
75
77
|
if (!isTableEnd) {
|
|
76
|
-
throw new Error(`Invalid format, COLUMN TABLE
|
|
78
|
+
throw new Error(`Invalid format, COLUMN TABLE statement not correctly terminated`)
|
|
77
79
|
}
|
|
78
|
-
if (!isMigration &&
|
|
79
|
-
throw new Error(`Invalid format, '== migration=${
|
|
80
|
+
if (!isMigration && tVersion > 1) {
|
|
81
|
+
throw new Error(`Invalid format, '== migration=${tVersion}' entry missing`)
|
|
82
|
+
}
|
|
83
|
+
if (mVersion !== -1 && mVersion !== tVersion) {
|
|
84
|
+
throw new Error(`Invalid format, migration version ${mVersion} does not match table version ${tVersion}`)
|
|
80
85
|
}
|
|
81
86
|
}
|
|
82
87
|
|
|
83
88
|
_parseTable(lines) {
|
|
84
89
|
const format = { startLine: -1, endLine: -1 }
|
|
85
90
|
for (let idx = 0; idx < lines.length; idx++) {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
91
|
+
if (format.startLine === -1) {
|
|
92
|
+
if (MigrationTableParser._isVersionMarker(lines[idx])) {
|
|
93
|
+
format.startLine = idx
|
|
94
|
+
}
|
|
89
95
|
} else if (format.endLine === -1) {
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
96
|
+
let tIdx = -1
|
|
97
|
+
if (MigrationTableParser._isMigrationMarker(lines[idx])) {
|
|
98
|
+
tIdx = idx - 1
|
|
99
|
+
} else if (idx + 1 === lines.length) {
|
|
100
|
+
tIdx = idx
|
|
101
|
+
}
|
|
102
|
+
// back search for end of table, comments belong to table
|
|
103
|
+
for (; tIdx > format.startLine; tIdx--) {
|
|
104
|
+
if (MigrationTableParser._isDDL(lines[tIdx])
|
|
105
|
+
|| MigrationTableParser._isComment(lines[tIdx])) {
|
|
106
|
+
format.endLine = tIdx
|
|
107
|
+
break
|
|
97
108
|
}
|
|
98
109
|
}
|
|
99
110
|
} else {
|
|
@@ -101,7 +112,7 @@ class MigrationTableParser {
|
|
|
101
112
|
}
|
|
102
113
|
}
|
|
103
114
|
if (format.startLine === -1) {
|
|
104
|
-
throw new Error(`Invalid format
|
|
115
|
+
throw new Error(`Invalid format, '== version=' entry missing`)
|
|
105
116
|
}
|
|
106
117
|
return new MigrationTable(lines, format)
|
|
107
118
|
}
|
|
@@ -109,10 +120,9 @@ class MigrationTableParser {
|
|
|
109
120
|
_parseMigrations(lines, table) {
|
|
110
121
|
const migrations = []
|
|
111
122
|
let format = { startLine: -1, endLine: -1 }
|
|
112
|
-
for (let idx = table.lines.length; idx < lines.length; idx++) {
|
|
113
|
-
let line = lines[idx]
|
|
123
|
+
for (let idx = table.lines.length; idx < lines.length; idx++) {
|
|
114
124
|
let nextMigration = false
|
|
115
|
-
if (
|
|
125
|
+
if (MigrationTableParser._isMigrationMarker(lines[idx])) {
|
|
116
126
|
if (format.startLine === -1) {
|
|
117
127
|
format.startLine = idx
|
|
118
128
|
} else {
|
|
@@ -120,25 +130,42 @@ class MigrationTableParser {
|
|
|
120
130
|
}
|
|
121
131
|
}
|
|
122
132
|
if (format.startLine !== -1 && (nextMigration || (idx + 1) === lines.length)) {
|
|
123
|
-
// back search for end migration
|
|
124
|
-
for (let
|
|
125
|
-
if (
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
if (nextMigration !== -1) {
|
|
129
|
-
format = { startLine: idx, endLine: -1 }
|
|
130
|
-
}
|
|
133
|
+
// back search for end of migration, comments belong to former migration
|
|
134
|
+
for (let mIdx = nextMigration ? idx - 1 : idx; mIdx > format.startLine; mIdx--) {
|
|
135
|
+
if (MigrationTableParser._isDDL(lines[mIdx])
|
|
136
|
+
|| MigrationTableParser._isComment(lines[mIdx])) {
|
|
137
|
+
format.endLine = mIdx
|
|
131
138
|
break
|
|
132
139
|
}
|
|
133
140
|
}
|
|
141
|
+
migrations.push(new Migration(lines, format))
|
|
142
|
+
if (nextMigration) {
|
|
143
|
+
format = { startLine: idx, endLine: -1 }
|
|
144
|
+
}
|
|
134
145
|
}
|
|
135
146
|
}
|
|
136
147
|
return new Migrations(migrations)
|
|
137
148
|
}
|
|
138
149
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
return !/^\s*--|^\s
|
|
150
|
+
// any lines that do not start with a comment or conflict marker and do not represent version tags
|
|
151
|
+
static _isDDL(line) {
|
|
152
|
+
return !/^\s*--|^\s*==|^\s*$|^\s*>>>>>/.test(line)
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
static _isComment(line) {
|
|
156
|
+
return /^\s*--/.test(line)
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
static _isConflictMarker(line) {
|
|
160
|
+
return /^\s*>>>>>/.test(line)
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
static _isVersionMarker(line) {
|
|
164
|
+
return /^\s*== version=\d+\s*$/.test(line)
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
static _isMigrationMarker(line) {
|
|
168
|
+
return /^\s*== migration=\d+\s*$/.test(line)
|
|
142
169
|
}
|
|
143
170
|
|
|
144
171
|
static _parseVersionNumber(line) {
|
|
@@ -154,7 +181,6 @@ class MigrationTableParser {
|
|
|
154
181
|
}
|
|
155
182
|
}
|
|
156
183
|
|
|
157
|
-
|
|
158
184
|
/**
|
|
159
185
|
* Model representation of an entire .hdbmigrationtable file.
|
|
160
186
|
* <p>
|
|
@@ -269,10 +295,6 @@ class MigrationTable {
|
|
|
269
295
|
this._versionNumber = newVersion
|
|
270
296
|
}
|
|
271
297
|
|
|
272
|
-
get sql() {
|
|
273
|
-
return this._lines.filter(line => MigrationTableParser._isSqlStatement(line)).join('\n')
|
|
274
|
-
}
|
|
275
|
-
|
|
276
298
|
get lines() {
|
|
277
299
|
return this._lines
|
|
278
300
|
}
|
|
@@ -288,7 +310,7 @@ class MigrationTable {
|
|
|
288
310
|
|
|
289
311
|
class Migrations {
|
|
290
312
|
constructor(migrations = []) {
|
|
291
|
-
this._migrations = migrations
|
|
313
|
+
this._migrations = migrations.sort((a, b) => b.versionNumber - a.versionNumber)
|
|
292
314
|
}
|
|
293
315
|
get versionNumber() {
|
|
294
316
|
return this._migrations.length > 0 ? this._migrations[0].versionNumber : 1
|
|
@@ -327,7 +349,7 @@ class Migration {
|
|
|
327
349
|
this._lines = lines
|
|
328
350
|
}
|
|
329
351
|
this._versionNumber = MigrationTableParser._parseVersionNumber(this.lines[0])
|
|
330
|
-
this._changeset = this._lines.filter(line => MigrationTableParser.
|
|
352
|
+
this._changeset = this._lines.filter(line => !MigrationTableParser._isMigrationMarker(line))
|
|
331
353
|
}
|
|
332
354
|
|
|
333
355
|
/**
|
|
@@ -359,6 +381,14 @@ class Migration {
|
|
|
359
381
|
return this._changeset
|
|
360
382
|
}
|
|
361
383
|
|
|
384
|
+
/**
|
|
385
|
+
* Returns the DDL statements of this changeset. Any lines that do not start with a comment or conflict marker
|
|
386
|
+
* and do not represent version tags are treated as valid DDL statements.
|
|
387
|
+
*/
|
|
388
|
+
get ddl() {
|
|
389
|
+
return this.changeset.filter(line => MigrationTableParser._isDDL(line))
|
|
390
|
+
}
|
|
391
|
+
|
|
362
392
|
/**
|
|
363
393
|
* Returns the string representation of this migration.
|
|
364
394
|
*/
|
|
@@ -371,10 +401,4 @@ class Migration {
|
|
|
371
401
|
}
|
|
372
402
|
}
|
|
373
403
|
|
|
374
|
-
module.exports =
|
|
375
|
-
MigrationTableParser: new MigrationTableParser(),
|
|
376
|
-
MigrationTableModel,
|
|
377
|
-
MigrationTable,
|
|
378
|
-
Migrations,
|
|
379
|
-
Migration
|
|
380
|
-
}
|
|
404
|
+
module.exports = new MigrationTableParser()
|