@sap/xsodata
Advanced tools
Comparing version 7.5.0 to 7.5.5
@@ -11,2 +11,14 @@ # Change Log | ||
## [7.5.5] - 2022-04-21 | ||
* On calc view: Stable sort order with $skip and $top usage for subsequent requests via "order by" of key fields in SQL statement | ||
## [7.5.4] - 2022-04-21 | ||
Build infrastructure fix | ||
## [7.5.1] - [7.5.3] - 2022-04-20 | ||
Build infrastructure fixes | ||
## [7.5.0] - 2022-03-22 | ||
@@ -13,0 +25,0 @@ |
@@ -95,3 +95,10 @@ 'use strict'; | ||
this._SelectedPropertiesOrdered = null; | ||
/** | ||
* For CV: (real) key names with alias | ||
* @type {Array<String,string>} | ||
*/ | ||
this._aliasedKeyPropertiesOnCalcView = []; | ||
/** | ||
* Store names existing of navigation properties | ||
@@ -597,2 +604,46 @@ * @type {Array<String>} | ||
DbSegment.prototype.getKeyProperties0123ForSelectOnCalcViewAs0123 = function (noTable) { | ||
let ret = []; | ||
let keyNames; | ||
let keyName; | ||
let property; | ||
let selectProperty; | ||
let propertyType; | ||
let i; | ||
let j = -1; | ||
keyNames = this.entityType.keyNamesOrdered; | ||
for (i = 0; i < keyNames.length; i++) { | ||
keyName = keyNames[i]; | ||
property = this.entityType.propertiesMap[keyName]; | ||
selectProperty = null; | ||
if (property.KIND !== EntityType.entityKind.inputParameters) { | ||
j = j + 1; // for real key properties use numbering: 0,1,2, ... (skip CV input params) | ||
propertyType = property.aggregate ? null : property.DATA_TYPE_NAME; | ||
selectProperty = new sqlStatement.SelectProperty(noTable ? null : this._Alias, keyName, propertyType, j.toString()); | ||
ret.push(selectProperty); | ||
} | ||
} | ||
return ret; | ||
}; | ||
DbSegment.prototype.setAliasedKeyPropertiesOnCalcView = function(selectProperties) { | ||
this._aliasedKeyPropertiesOnCalcView = selectProperties; | ||
}; | ||
DbSegment.prototype.hasAliasedKeyPropertiesOnCalcView = function() { | ||
return this._aliasedKeyPropertiesOnCalcView.length !== 0; | ||
}; | ||
DbSegment.prototype.getAliasedKeyPropertyOnCalcView = function(propertyName) { | ||
for (let i = 0; i < this._aliasedKeyPropertiesOnCalcView.length; i++) { | ||
if (this._aliasedKeyPropertiesOnCalcView[i].property === propertyName) { | ||
return this._aliasedKeyPropertiesOnCalcView[i]; | ||
} | ||
} | ||
return null; | ||
}; | ||
/** | ||
@@ -654,4 +705,27 @@ * Returns a selectProperty for usage in the select part of sql statements | ||
DbSegment.prototype.getKeyPropertiesNotSelectedForSelect = function (noTable) { | ||
DbSegment.prototype.getKeyProperties0123ForOrderByCalcView = function (noTable) { | ||
let ret = []; | ||
let keyName; | ||
let property; | ||
let j = -1; | ||
let keyNames = this.entityType.keyNamesOrdered; | ||
for (let i = 0; i < keyNames.length; i++) { | ||
keyName = keyNames[i]; | ||
property = this.entityType.propertiesMap[keyName]; | ||
if (property.KIND !== EntityType.entityKind.inputParameters) { | ||
j = j + 1; | ||
let newSortOrder = new typedObjects.SortOrder(new typedObjects.Property(j.toString(), noTable ? null : this._Alias), 'ASC'); | ||
newSortOrder.setPropertyName(property.COLUMN_NAME); | ||
ret.push(newSortOrder); | ||
} | ||
} | ||
return ret; | ||
}; | ||
DbSegment.prototype.getKeyPropertiesNotSelectedForSelect = function (noTable = undefined, inputParameters = null) { | ||
let ret = []; | ||
let keyNames; | ||
@@ -665,2 +739,14 @@ let i; | ||
// remove input params from key list | ||
if (inputParameters !== null) { | ||
for (let inputParameterName in inputParameters) { | ||
if (inputParameters.hasOwnProperty(inputParameterName)) { | ||
let indexKeyName = keyNames.indexOf(inputParameterName); | ||
if (indexKeyName > -1) { | ||
keyNames.splice(indexKeyName, 1); | ||
} | ||
} | ||
} | ||
} | ||
for (i = 0; i < keyNames.length; i++) { | ||
@@ -667,0 +753,0 @@ keyName = keyNames[i]; |
@@ -137,5 +137,20 @@ 'use strict'; | ||
} else { | ||
value = null; | ||
if (dbSeg.hasAliasedKeyPropertiesOnCalcView()) { | ||
let foundKeyFieldAlias = null; | ||
for (let i = 0; i < dbSeg._aliasedKeyPropertiesOnCalcView.length; i++) { | ||
if (dbSeg._aliasedKeyPropertiesOnCalcView[i].property === keyProperty.COLUMN_NAME && | ||
dbSeg._aliasedKeyPropertiesOnCalcView[i].table === dbSeg._Alias) { | ||
foundKeyFieldAlias = dbSeg._aliasedKeyPropertiesOnCalcView[i].alias; | ||
break; // there must not be more than one entry! | ||
} | ||
} | ||
if (foundKeyFieldAlias !== null && row[foundKeyFieldAlias] !== undefined) { | ||
value = typeConverter.serializeDbValueToUriLiteral(row[foundKeyFieldAlias], keyProperty); | ||
} else { | ||
value = null; | ||
} | ||
} else { | ||
value = null; | ||
} | ||
} | ||
} else { | ||
@@ -171,9 +186,23 @@ value = typeConverter.serializeDbValueToUriLiteral(row[keyProperty.COLUMN_NAME], keyProperty); | ||
var i; | ||
if (!dbSeg.hasAliasedKeyPropertiesOnCalcView()) { | ||
dbSeg.getSelectedPropsWithGenKey().forEach(function toConverter(property, index) { | ||
ret[property] = converter[index](row[property]); | ||
}); | ||
} else { | ||
let selectedProperties = dbSeg.getSelectedPropsWithGenKey(); | ||
for (let i = 0; i < selectedProperties.length; i++) { | ||
if (!row[selectedProperties[i]]) { | ||
let aliasedKeyProperty = dbSeg.getAliasedKeyPropertyOnCalcView(selectedProperties[i]); | ||
if (aliasedKeyProperty !== null && aliasedKeyProperty.alias) { | ||
ret[selectedProperties[i]] = converter[i](row[aliasedKeyProperty.alias]); | ||
} else { | ||
ret[selectedProperties[i]] = converter[i](row[selectedProperties[i]]); // keeps null | ||
} | ||
} else { | ||
ret[selectedProperties[i]] = converter[i](row[selectedProperties[i]]); | ||
} | ||
} | ||
} | ||
dbSeg.getSelectedPropsWithGenKey().forEach(function toConverter(property, index) { | ||
ret[property] = converter[index](row[property]); | ||
}); | ||
for (i = 0; i < dbSeg._SelectedNavigations.length; i++) { | ||
for (let i = 0; i < dbSeg._SelectedNavigations.length; i++) { | ||
var sn = dbSeg._SelectedNavigations[i]; | ||
@@ -180,0 +209,0 @@ var navDbSeg = dbSeg.getRelevantNavigationSegments()[sn]; |
@@ -194,4 +194,16 @@ 'use strict'; | ||
if (!isCount) { | ||
if (!(dbSeg.entityType.kind === EntityType.entityKind.calculationView && dbSeg.entityType._entityType.parameters && dbSeg.entityType._entityType.parameters.viaKey === true)) { | ||
if (!(dbSeg.entityType.kind === EntityType.entityKind.calculationView && | ||
dbSeg.entityType._entityType.parameters && | ||
dbSeg.entityType._entityType.parameters.viaKey === true)) { | ||
select.addSortOrders(dbSeg.getKeyProperties0123ForOrderBy(true)); | ||
} else { | ||
let orderByProperties = dbSeg.getKeyProperties0123ForOrderByCalcView(true); | ||
for (let i= 0; i < select.select.length; i++) { | ||
for (let j= 0; j < orderByProperties.length; j++) { | ||
if (orderByProperties[j].getPropertyName() === select.select[i].property) { | ||
select.select[i].alias = orderByProperties[j].expression.property; | ||
} | ||
} | ||
} | ||
select.addSortOrders(orderByProperties); | ||
} | ||
@@ -388,12 +400,17 @@ } | ||
if (dbSeg.entityType.kind === EntityType.entityKind.calculationView && dbSeg.entityType._entityType.parameters && dbSeg.entityType._entityType.parameters.viaKey === true) { | ||
// stm.addSelect(dbSeg.getKeyProperties0123ForSelectAs0123()); | ||
// Adding properties from getKeyProperties0123ForSelectAs0123 is not needed since | ||
// if (in future) a association via input parameter is used then the input parameter values must be added via ? into the sql command | ||
// that's because calcview don't return their input parameter in the | ||
// if (in future) an association via input parameter is used then the input parameter values must be added via ? into the sql command | ||
// that's because calcview don't return their input parameter in the result set | ||
let tmp = dbSeg.getPropertiesForSelectCollectInputParameters(); | ||
// since the input parameters may not be returned from the calcview the parameters are merged after the select | ||
// from "calcview2" into the result. | ||
// from "calcview2" into the result. // Q: What does that mean: "calcview2"? | ||
stm.byPassInputs = tmp.input; | ||
stm.addSelects(tmp.selects); | ||
stm.addSelects(dbSeg.getKeyPropertiesNotSelectedForSelect()); | ||
stm.addSelects(dbSeg.getKeyPropertiesNotSelectedForSelect(undefined, dbSeg.entityType.inputParameters)); | ||
// keep aliased key properties | ||
let selectProperties = dbSeg.getKeyProperties0123ForSelectOnCalcViewAs0123(); | ||
dbSeg.setAliasedKeyPropertiesOnCalcView(selectProperties); | ||
} else { | ||
@@ -400,0 +417,0 @@ stm.addSelect(dbSeg.getKeyProperties0123ForSelectAs0123()); |
@@ -623,3 +623,2 @@ 'use strict'; | ||
this.addCalcViewHint = false; | ||
this.customData = {}; // restriction on the count of selected records | ||
@@ -665,2 +664,5 @@ } | ||
// note: $orderby properties for CV that are NOT in select list result in SQL error | ||
// but: That was never supported by this lib! | ||
sql += '\nfrom '; | ||
@@ -1003,3 +1005,2 @@ | ||
} | ||
if (add) { | ||
@@ -1006,0 +1007,0 @@ this.select.push(newSelect); |
@@ -46,4 +46,5 @@ 'use strict'; | ||
let XSODATA_LOG_SQL_PARAMETERS = process.env.XSODATA_LOG_SQL_PARAMETERS || 2; | ||
let XSODATA_LOG_SQL_PARAM_VALUE_SIZE = process.env.XSODATA_LOG_SQL_PARAM_VALUE_SIZE || 30; | ||
let XSODATA_LOG_SQL_PARAM_ARRAY_SIZE = process.env.XSODATA_LOG_SQL_PARAM_ARRAY_SIZE || 30; | ||
// XSODATA_LOG_SQL_PARAM_VALUE_SIZE: sets the length of the parameter value loggged out | ||
let XSODATA_LOG_SQL_PARAM_VALUE_SIZE = process.env.XSODATA_LOG_SQL_PARAM_VALUE_SIZE || 80; | ||
let XSODATA_LOG_SQL_PARAM_ARRAY_SIZE = process.env.XSODATA_LOG_SQL_PARAM_ARRAY_SIZE || 80; | ||
@@ -50,0 +51,0 @@ // Log long sql results |
@@ -1084,2 +1084,10 @@ 'use strict'; | ||
SortOrder.prototype.setPropertyName = function(propertyName) { | ||
this.propertyName = propertyName; | ||
}; | ||
SortOrder.prototype.getPropertyName = function() { | ||
return this.propertyName; | ||
}; | ||
SortOrder.prototype.setAlias = function (alias) { | ||
@@ -1086,0 +1094,0 @@ this.expression.setAlias(alias); |
{ | ||
"name": "@sap/xsodata", | ||
"version": "7.5.0", | ||
"version": "7.5.5", | ||
"description": "Expose data from a HANA database as OData V2 service with help of .xsodata files.", | ||
@@ -11,17 +11,13 @@ "main": "index.js", | ||
"pretest": "npm -g ls --depth=0 && npm ls --depth=0", | ||
"test": "npm run unit-tests", | ||
"lint": "jshint .", | ||
"all-tests": "node ./node_modules/mocha/bin/_mocha --timeout 20000 test/**/test*.js test_apps/test_**/**/test*.js", | ||
"all-tests-jenkins": "node ./node_modules/mocha/bin/_mocha --timeout 20000 'test/**/test*.js' 'test_apps/test_**/**/test*.js'", | ||
"all-tests-cv": "node ./node_modules/mocha/bin/_mocha --timeout 20000 'test_apps/test_cv/**/test*.js'", | ||
"scenario-tests": "node ./node_modules/mocha/bin/_mocha --timeout 20000 test_apps/test_**/**/test*.js", | ||
"unit-tests": "node ./node_modules/mocha/bin/_mocha test/**/test*.js", | ||
"cover": "istanbul cover -x test/**/* -x test_apps/**/* --report lcov --dir ./_coverage ./node_modules/mocha/bin/_mocha -- -R spec test/**/test*.js test_apps/**/test*.js", | ||
"cover-unit-tests": "istanbul cover -x test/**/* --report lcov --dir ./_coverage ./node_modules/mocha/bin/_mocha -- -R spec test/**/test*.js", | ||
"cover-scenario-tests": "istanbul cover -x test_apps/**/* --report lcov --dir ./_coverage ./node_modules/mocha/bin/_mocha -- -R spec test_apps/**/test*.js", | ||
"cover-jenkins-istanbul": "istanbul cover ./node_modules/mocha/bin/_mocha 'test/**/test*.js' 'test_apps/**/test*.js' -- --timeout 20000 && istanbul check-coverage ./_coverage/coverage.json", | ||
"cover-unit-tests": "nyc --reporter=text --reporter=html --all --include lib/ npm run unit-tests", | ||
"cover-scenario-tests": "nyc --reporter=text --reporter=html --all --include lib/ --check-coverage true --lines 80 --branches 69 --functions 87 --statements 80 npm run scenario-tests", | ||
"cover-jenkins": "nyc --reporter=text --reporter=html --all --include lib/ --check-coverage true --lines 80 --branches 69 --functions 87 --statements 80 npm run all-tests-jenkins", | ||
"report": "node ./node_modules/mocha/bin/_mocha test/**/test*.js test_apps/test_**/**/test*.js --reporter mocha-simple-html-reporter --reporter-options output=_gen/report/report_all.html", | ||
"report-unit-tests": "node ./node_modules/mocha/bin/_mocha test/**/test*.js --reporter mocha-simple-html-reporter --reporter-options output=_gen/report/report_unit.html", | ||
"report-scenario-tests": "node ./node_modules/mocha/bin/_mocha test_apps/test_**/**/test*.js --reporter mocha-simple-html-reporter --reporter-options output=_gen/report/report_scenario.html", | ||
"env": "env", | ||
"report": "node ./node_modules/mocha/bin/_mocha test/**/test*.js test_apps/test_**/**/test*.js --reporter mocha-simple-html-reporter --reporter-options output=report_all.html", | ||
"report-unit-tests": "node ./node_modules/mocha/bin/_mocha test/**/test*.js --reporter mocha-simple-html-reporter --reporter-options output=report_unit.html", | ||
"report-scenario-tests": "node ./node_modules/mocha/bin/_mocha test_apps/test_**/**/test*.js --reporter mocha-simple-html-reporter --reporter-options output=report_scenario.html", | ||
"gen": "npm run genfilter && npm run genorderby && npm run gensegment && npm run genxso && npm run genxml && npm run genDateTimeParser", | ||
@@ -72,6 +68,5 @@ "genfilter": "jison lib/grammars/filter.jison -o lib/parsers/jison_filter_parser.js", | ||
"filter-node-package": "=2.2.0", | ||
"istanbul": "0.4.5", | ||
"jison": "0.4.18", | ||
"jshint": "2.10.2", | ||
"mocha": "8.3.2", | ||
"jshint": "2.13.4", | ||
"mocha": "9.2.2", | ||
"mocha-simple-html-reporter": "1.1.0", | ||
@@ -78,0 +73,0 @@ "node-mocks-http": "=1.7.6", |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
1324674
13
32571