Socket
Socket
Sign inDemoInstall

@sap/cds-ql

Package Overview
Dependencies
Maintainers
3
Versions
15
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@sap/cds-ql - npm Package Compare versions

Comparing version 1.0.0 to 1.5.1

42

CHANGELOG.md

@@ -9,2 +9,44 @@ # Changelog

## Version 1.5.1 - 2019-02-12
### Added
- Support for sql functions lower, upper, trim, length in $filter and $orderby
- Support `.and` for where conditions
### Fixed
- Use `.entities` from reflected models
## Version 1.5.0 - 2019-02-06
### Changed
- Minimum node version 8.9.0
## Version 1.4.0 - 2019-01-22
### Changed
- Use latest version of @sap/cds-sql
## Version 1.3.0 - 2019-01-11
### Changed
- Use latest version of uuid and @sap/cds-sql
## Version 1.2.0 - 2018-12-21
### Added
- Allow Arrays in `UPDATE.set()`
## Version 1.1.0 - 2018-12-12
### Added
- Support for `full join` in SELECT
- Support for inline
## Version 1.0.0 - 2018-11-27

@@ -11,0 +53,0 @@

24

lib/connect/Service.js

@@ -88,3 +88,3 @@ const Pool = require('./Pool')

if (model) {
return cds.load(...(Array.isArray(model) ? model : [model])).then(csn => {
return cds.load(model).then(csn => {
this.model = cds.linked(cds.unfold.for.odata(csn))

@@ -113,19 +113,5 @@ })

entities (namespace) {
if (this._entities[namespace]) {
return this._entities[namespace]
}
// delegate to linked model
get entities () { return this.model.entities }
this._entities[namespace] = {}
// TODO: We've to create derived definitions, as cds-compiler would otherwise deep-clone our associated datasources
const entities = this.model.entities(namespace)
for (const key of Object.keys(entities)) {
this._entities[namespace][key] = { __proto__: entities[key], _datasource: this }
}
return this._entities[namespace]
}
/**

@@ -293,3 +279,5 @@ * Acquires a db client from the session.

// require only when needed
require('@sap/instance-manager').create(this.options.credentials || this.options, (err, instanceManager) => {
let options = this.options.credentials || this.options
options = Object.assign(options, { cache_max_items: 1, cache_item_expire_seconds: 1 })
require('@sap/instance-manager').create(options, (err, instanceManager) => {
if (err) {

@@ -296,0 +284,0 @@ reject(err)

@@ -45,3 +45,5 @@ const { addToQueue } = require('./queue')

if (value) {
const entity = value.source || value.name || value
// OLD CSN -> value.source
const entity =
(value.query && value.query.target && value.query.target.name) || value.source || value.name || value

@@ -48,0 +50,0 @@ if (typeof entity === 'string') {

@@ -139,2 +139,11 @@ const BaseStatement = require('./BaseStatement')

as (selectCqn) {
if (!selectCqn || !selectCqn.SELECT) {
throw new IllegalFunctionArgumentError('as')
}
this.INSERT.as = selectCqn
return this
}
_invalidArgs (argName, args) {

@@ -141,0 +150,0 @@ if (!Array.isArray(args) || args.length === 0) {

@@ -88,2 +88,5 @@ const cds = require('../cds')

this.SELECT.columns = []
if (columns.includes('.{')) {
columns = `{${columns.replace(/{/g, '').replace(/}/g, '')}}`
}
const res = cds.parse.cql(`SELECT from ${entity} ${columns.replace(/'/g, '')}`)

@@ -214,2 +217,13 @@ this._parseArray(res.SELECT.columns, entity)

/**
* Add full join.
*
* @param tableName - Table name to be used for join.
* @returns {Select} this object instance for chaining.
* @throws UnexpectedFunctionCallError - If where or having was already called.
*/
fullJoin (tableName, as) {
return this._join(tableName, as, 'full')
}
/**
* .on can only be used after .join has been called.

@@ -411,2 +425,11 @@ * @param {string|Object} arg1 Can be object if argument is passed as an object or can be a string when an identifier is directly passed.

}
if (cqn.join) {
return cqn.args
.map(arg => {
return this._getEntityNameFromCQN(arg)
})
.filter(name => {
return !name.endsWith('_drafts')
})[0]
}
}

@@ -536,6 +559,12 @@

_addColumnToOrderBy (column, order = 'asc') {
let res
if (this._isFunction(column)) {
res = this._parseFunction(column)
} else {
res = column.includes('.') ? this._parseElementWithDot(column, this.SELECT.from.ref[0]) : { ref: [column] }
}
if (this.SELECT.hasOwnProperty('orderBy')) {
this.SELECT.orderBy.push({ ref: [column] })
this.SELECT.orderBy.push(res)
} else {
this.SELECT.orderBy = [{ ref: [column] }]
this.SELECT.orderBy = [res]
}

@@ -553,6 +582,11 @@

_addColumnToGroupBy (column) {
const res =
typeof column === 'string' && column.includes('.')
? this._parseElementWithDot(column, this.SELECT.from.ref[0])
: { ref: [column] }
if (this.SELECT.hasOwnProperty('groupBy')) {
this.SELECT.groupBy.push({ ref: [column] })
this.SELECT.groupBy.push(res)
} else {
this.SELECT.groupBy = [{ ref: [column] }]
this.SELECT.groupBy = [res]
}

@@ -571,3 +605,3 @@ }

} else if (typeof columns[i] === 'string' && columns[i].includes('.')) {
this._parseElementWithDot(columns[i], entityName)
this.SELECT.columns.push(this._parseElementWithDot(columns[i], entityName))
} else {

@@ -634,4 +668,4 @@ this.SELECT.columns.push(this._parseElement(columns[i]))

if ((key.startsWith('expand(') || key.startsWith('inline(')) && Array.isArray(object[key])) {
return this._parseExpandInline(key, object[key])
if (key.startsWith('expand(') && Array.isArray(object[key])) {
return this._parseExpand(key, object[key])
}

@@ -652,18 +686,9 @@

_parseExpandInline (expr, elements) {
let ref, type
if (expr.startsWith('expand(')) {
type = 'expand'
ref = {
ref: [expr.replace(/(^expand\(|\)$)/g, '')]
}
} else {
type = 'inline'
ref = {
ref: [expr.replace(/(^inline\(|\)$)/g, '')]
}
_parseExpand (expr, elements) {
const ref = {
ref: [expr.replace(/(^expand\(|\)$)/g, '')]
}
ref[type] = []
ref['expand'] = []
for (const element of elements) {
ref[type].push(this._parseElement(element))
ref['expand'].push(this._parseElement(element))
}

@@ -675,13 +700,10 @@ return ref

if (column.includes('.{')) {
// <-- inline, no isAssociation check
this.SELECT.columns.push(this._buildInline(this._matchInline(column)))
} else {
// inline or column name with dot
const parts = column.split(/\./)
if (this._isAssociation(entityName, parts[0])) {
this.SELECT.columns.push(this._parseElement({ [`inline(${parts[0]})`]: [parts[1]] }))
} else {
this.SELECT.columns.push(this._parseStringElement(column))
}
return { ref: this._matchInline(column) }
}
const parts = column.split(/\./)
if (this[MODEL] && this._isAssociation(entityName, parts[0])) {
return { ref: parts }
}
return this._parseStringElement(column)
}

@@ -688,0 +710,0 @@

@@ -71,3 +71,5 @@ const Where = require('./Where')

valueObject[key] === undefined ||
(valueObject[key] instanceof Object && Object.keys(valueObject[key]).length === 0)
(valueObject[key] instanceof Object &&
!Array.isArray(valueObject[key]) &&
Object.keys(valueObject[key]).length === 0)
) {

@@ -74,0 +76,0 @@ return true

@@ -52,11 +52,12 @@ const BaseStatement = require('./BaseStatement')

where (arg1, arg2, arg3, arg4) {
if (this._getCQN().having) {
const cqn = this._getCQN() // please always code defensive --> this._getCQN() could be expensive
if (cqn.having) {
throw new UnexpectedFunctionCallError('where')
}
if (this._getCQN().where) {
if (cqn.where) {
return this._andWhere(...arguments)
}
this._getCQN().where = []
cqn.where = []
return this._where(...arguments)

@@ -114,12 +115,13 @@ }

_setAndOrBracket (operator, clause, ...args) {
const cqn = this._getCQN()
// set brackets if .or, .where or .having are chained
const lastSame = this._getCQN()[clause] && this._getCQN()[clause].lastIndexOf(operator)
const lastSame = cqn[clause] && cqn[clause].lastIndexOf(operator)
const lastDif =
operator === 'or'
? this._getCQN()[clause] && this._getCQN()[clause].lastIndexOf('and')
: this._getCQN()[clause] && this._getCQN()[clause].lastIndexOf('or')
? cqn[clause] && cqn[clause].lastIndexOf('and')
: cqn[clause] && cqn[clause].lastIndexOf('or')
// no brackets in case of fluid usage
if (args.length > 4 || this._hasExpressionIndicator(args[0])) {
this._getCQN()[clause].push(operator)
cqn[clause].push(operator)
return clause === 'where' ? this._where(...args) : this._having(...args)

@@ -129,8 +131,8 @@ }

this._setFirstAndOrBracket(clause)
this._getCQN()[clause].push(operator)
cqn[clause].push(operator)
if (lastSame > lastDif && this._getCQN()[clause][this._getCQN()[clause].length - 2] === ')') {
this._getCQN()[clause].splice(this._getCQN()[clause].length - 2, 1)
} else if (lastDif > lastSame && this._getCQN()[clause][this._getCQN()[clause].length - 2] === ')') {
this._getCQN()[clause].push('(')
if (lastSame > lastDif && cqn[clause][cqn[clause].length - 2] === ')') {
cqn[clause].splice(cqn[clause].length - 2, 1)
} else if (lastDif > lastSame && cqn[clause][cqn[clause].length - 2] === ')') {
cqn[clause].push('(')
}

@@ -140,5 +142,5 @@

const needLastBracket =
this._getCQN()[clause].filter(i => i === '(').length > this._getCQN()[clause].filter(i => i === ')').length
cqn[clause].filter(i => i === '(').length > cqn[clause].filter(i => i === ')').length
if (needLastBracket) {
this._getCQN()[clause].push(')')
cqn[clause].push(')')
}

@@ -149,5 +151,6 @@ return this

_logicOperation (operator, arg1, arg2, arg3, arg4) {
const isJoin = this._getCQN().from.hasOwnProperty('join')
const isWhere = this._getCQN().where && this._getCQN().where.length > 0
const isHaving = this._getCQN().having && this._getCQN().having.length > 0
const cqn = this._getCQN()
const isJoin = cqn.from && cqn.from.hasOwnProperty('join')
const isWhere = cqn.where && cqn.where.length > 0
const isHaving = cqn.having && cqn.having.length > 0

@@ -164,5 +167,9 @@ if (operator === 'or' && (isHaving || isWhere)) {

if (!isJoin && operator === 'and') {
return this.where(arg1, arg2, arg3, arg4)
}
if (isJoin) {
this._getCQN().from.on.push(operator)
this._getCQN().from.on.push(...this._parseArguments(arg1, arg2, arg3, arg4))
cqn.from.on.push(operator)
cqn.from.on.push(...this._parseArguments(arg1, arg2, arg3, arg4))

@@ -296,6 +303,12 @@ return this

const parts = aggregation.match(/[^,()]+/g)
if (parts.length !== 2) {
if (parts.length < 1) {
throw new IllegalFunctionArgumentError('columns')
}
if (parts.length === 1) {
// functions without args
return { ref: [parts[0].toLowerCase(), { args: [] }] }
}
const args = parts.slice(1, parts.length)
// special cases like count(*), count(1) or sum(10.1)

@@ -306,3 +319,3 @@ if (parts[1] === '*' || this._isNumber(parts[1])) {

return { ref: [parts[0].toLowerCase(), { args: [this._buildRef(parts[1])] }] }
return { ref: [parts[0].toLowerCase(), { args: args.map(arg => this._buildRef(arg.trim())) }] }
}

@@ -366,3 +379,3 @@

if (arg1 instanceof Object && !this._isCqn(arg1)) {
if (typeof arg1 === 'object' && !this._isCqn(arg1)) {
return this._parseObjectArgument(arg1)

@@ -509,6 +522,6 @@ }

_matchInline (name) {
let matches = name.split(/\.\{/)
const lastIndex = matches.length - 1
matches[lastIndex] = matches[lastIndex].match(/(\w+)\}+/)[1]
return matches
return name
.replace(/{/g, '')
.replace(/}/g, '')
.split(/\./)
}

@@ -520,32 +533,29 @@

_buildWithTableName (element) {
const tableNames = this._getTableNames()
const matched = this._matchTableColumn(element)
if (matched && tableNames.indexOf(matched[0]) !== -1) {
return { ref: [matched[0], matched[1]] }
_parseInlineAssociation (element, tableNames) {
if (element.includes('.{')) {
return { ref: this._matchInline(element) }
}
if (matched && this[MODEL]) {
const parts = element.split(/\./)
if (parts && this[MODEL]) {
for (const table of tableNames) {
if (this._isAssociation(table, matched[0])) {
// <-- inline or column name with dot
return this._buildInline(matched)
// inline or column name with dot
if (this._isAssociation(table, parts[0])) {
return { ref: parts }
}
}
}
}
if (element.includes('.{')) {
// <-- inline, no isAssociation check
return this._buildInline(this._matchInline(element))
_buildWithTableName (element) {
const tableNames = this._getTableNames()
const matched = this._matchTableColumn(element)
if (matched && tableNames.indexOf(matched[0]) !== -1) {
return { ref: [matched[0], matched[1]] }
}
}
_buildInline (array) {
let ref = { ref: [array[0]] }
if (array.length > 1) {
array.splice(0, 1)
ref['inline'] = [this._buildInline(array)]
if (element.includes('.')) {
return this._parseInlineAssociation(element, tableNames)
}
return ref
}

@@ -704,3 +714,4 @@

_isAssociation (entityName, associationName) {
const entity = this[MODEL].definitions[entityName]
const name = typeof entityName === 'object' ? entityName.name : entityName
const entity = this[MODEL].definitions[name]
if (entity) {

@@ -707,0 +718,0 @@ return entity.elements[associationName] && entity.elements[associationName].type === 'cds.Association'

{
"name": "@sap/cds-ql",
"version": "1.0.0",
"version": "1.5.1",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"@sap/cds-hana": {
"version": "1.0.3"
"version": "1.5.1",
"requires": {
"@sap/cds-sql": "1.5.1"
}
},
"@sap/cds-sql": {
"version": "1.0.3"
"version": "1.5.1"
},
"@sap/cds-sqlite": {
"version": "1.0.3"
"version": "1.5.1",
"requires": {
"@sap/cds-sql": "1.5.1"
}
},

@@ -18,5 +26,5 @@ "generic-pool": {

"uuid": {
"version": "3.2.1"
"version": "3.3.2"
}
}
}

@@ -1,1 +0,1 @@

{"bundleDependencies":false,"dependencies":{"@sap/cds-hana":"1.0.3","@sap/cds-sql":"1.0.3","@sap/cds-sqlite":"1.0.3","generic-pool":"3.4.2","uuid":"3.2.1"},"deprecated":false,"description":"This package deals with creating a pool of connection clients, connecting to a driver (read: db) and using these connection clients from the pool to insert, delete, select and update values or rows from a specific table. Performing these insert, delete, select and update operations also includes executing embedded queries and plain statements.","devDependencies":{"@sap/instance-manager":"^1.3.4","@sap/xsenv":"^1.2.9","husky":"^1.2.0","jest":"^23.6.0","jest-junit":"^5.2.0","jsdoc-to-markdown":"^4.0.1","lint-staged":"^8.1.0","prettier-standard":"^8.0.1","sqlite3":"4.0.4","standard":"^12.0.1","standard-reporter":"^1.0.5"},"engines":{"node":">= 8.0.0"},"husky":{"hooks":{"pre-commit":"lint-staged"}},"jest":{"testEnvironment":"node"},"jest-junit":{"suiteName":"jest tests","output":"reports/sonar/test-reporter.xml","classNameTemplate":"{classname}-{title}","titleTemplate":"{classname}-{title}","ancestorSeparator":" › ","usePathForSuiteName":"true"},"lint-staged":{"{lib,test}/**/*.js":["prettier-standard","standard --fix","git add"]},"main":"lib/index.js","name":"@sap/cds-ql","scripts":{"build":"npm run test && npm run jsdoc2md","clean":"rm -rf reports && rm -f npm-debug.log && rm -rf node_modules/@sap/*/node_modules/@sap/cds-*","jsdoc2md":"jsdoc2md --param-list-format list lib/**/*.js > docs/api.md","lint":"([ -d reports ] || mkdir reports) && standard --env jest && standard | standard-reporter --checkstyle > reports/eslint.jslint.xml","prepareRelease":"node node_modules/filter-node-package package.json","snapshots":"[ -e .pipeline/snapshots.sh ] && sh .pipeline/snapshots.sh","test":"node -v && npm run clean && npm run lint && npm run test-unit && npm run test-integration","test-integration":"jest --config=jest-integration.json && [ -e reports/sonar/test-reporter.xml ] && mv reports/sonar/test-reporter.xml reports/sonar/test-integration.xml","test-unit":"jest --config=jest-unit.json && [ -e reports/sonar/test-reporter.xml ] && mv reports/sonar/test-reporter.xml reports/sonar/test-unit.xml"},"standard":{"env":["jest"],"globals":["jest"]},"version":"1.0.0","license":"SEE LICENSE IN developer-license-3.1.txt"}
{"bundleDependencies":false,"dependencies":{"@sap/cds-hana":"1.5.1","@sap/cds-sql":"1.5.1","@sap/cds-sqlite":"1.5.1","generic-pool":"3.4.2","uuid":"3.3.2"},"deprecated":false,"description":"This package deals with creating a pool of connection clients, connecting to a driver (read: db) and using these connection clients from the pool to insert, delete, select and update values or rows from a specific table. Performing these insert, delete, select and update operations also includes executing embedded queries and plain statements.","engines":{"node":">= 8.9.0"},"husky":{"hooks":{"pre-commit":"lint-staged"}},"lint-staged":{"{lib,test}/**/*.js":["prettier-standard","standard --fix","git add"]},"main":"lib/index.js","name":"@sap/cds-ql","version":"1.5.1","license":"SEE LICENSE IN developer-license-3.1.txt"}

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc