Socket
Socket
Sign inDemoInstall

@sap/cds-sqlite

Package Overview
Dependencies
Maintainers
3
Versions
18
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@sap/cds-sqlite - npm Package Compare versions

Comparing version 0.9.0 to 1.5.0

lib/client/util.js

51

CHANGELOG.md

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

## Version 1.5.0 - 2019-02-06
### Changed
- Minimum node version 8.9.0
- Improve expand performance
## Version 1.4.0 - 2019-01-22
### Added
- `.execute` supports placeholders in CQN
## Version 1.3.0 - 2019-01-11
### Changed
- Use latest version of @sap/cds-sql
## Version 1.2.0 - 2018-12-21
### Added
- Set default values in case of CREATE, UPSERT and adding a child in deep documents
## Version 1.1.0 - 2018-12-12
### Added
- Support Deep Document CQNs
## Version 1.0.3 - 2018-11-27
### Added
- credentials.database can be used instead of parameters host and url
### Changed
- Throw db error instead of wrapping it in Sql Error
- Throw an error if database is not defined instead of fallback to memory
### Fixed
- Bulk Insert with $user / $now
- Post processing of Binary, Boolean, DateTime and Integer64
## Version 0.10.0 - 2018-10-17
- Refactoring and changes due to updated dependencies
## Version 0.9.0 - 2018-10-04

@@ -11,0 +62,0 @@

2

lib/cds.js

@@ -5,3 +5,3 @@ const _notInjected = () => {

const _validateInjection = (cds) => {
const _validateInjection = cds => {
if (!cds || typeof cds !== 'object') {

@@ -8,0 +8,0 @@ throw new Error('Injected value is not of type `cds`')

@@ -1,26 +0,23 @@

const {Database} = require('sqlite3')
const { Database } = require('sqlite3')
const SqliteStatement = require('../statement/SqliteStatement')
const {
BaseClient,
errors: {
IllegalFunctionArgumentError,
InconsistentClientError,
SqlError
errors: { IllegalFunctionArgumentError, InconsistentClientError },
builder: { sqlFactory },
expand: { createJoinCQNFromExpanded, hasExpand, rawToExpanded },
composition: {
hasCompositionDelete,
createCascadeDeleteCQNs,
hasDeepInsert,
createDeepInsertCQNs,
hasDeepUpdate,
selectDeepUpdateData,
createDeepUpdateCQNs
},
builder: {sqlFactory},
expand: {
createJoinCQNFromExpanded,
hasExpand,
rawToExpanded
},
contains: {
replaceContainsWithLike,
hasContains
},
postProcessing: {
getPostProcessMapper,
postProcess
}
contains: { replaceContainsWithLike, hasContains },
postProcessing: { getPostProcessMapper, postProcess }
} = require('@sap/cds-sql')
const { convertToBoolean, convertInt64ToString, convertToISOTime, convertToISONoMillis } = require('./util')
class Client extends BaseClient {

@@ -30,36 +27,14 @@ /**

*
* Username/password are currently not supported,
* but at least the host must be provided.
*
* @param {Object} connect - Connection details.
* @param {string} connect.host - Filename to the database or :memory; for in memory
* @param {string} [connect.user] - Username for authentication
* @param {string} [connect.password] - Password for authentication
* @param {Object} credentials - Connection details.
* @param {string} credentials.database - Filename to the database or :memory; for in memory
*/
constructor (connect) {
const convertToBase64Buffer = (element) => {
return Buffer.from(element, 'base64')
}
const convertToISOTime = (value) => {
if (value === null) {
return value
}
if (!value) {
value = 0
}
return new Date(value).toISOString()
}
constructor (credentials) {
super([
['cds.Boolean', Boolean],
['cds.Integer64', String],
['cds.Binary', convertToBase64Buffer],
['cds.LargeBinary', convertToBase64Buffer],
['cds.DateTime', convertToISOTime],
['cds.Boolean', convertToBoolean],
['cds.Integer64', convertInt64ToString],
['cds.DateTime', convertToISONoMillis],
['cds.Timestamp', convertToISOTime]
])
this._connect = connect
this._credentials = Object.assign({}, credentials)
this._user = 'anonymous' // default user

@@ -74,11 +49,12 @@ this._transCount = 0

*
* @returns {Promise} Promise, that resolves with SqliteClient if _connect is successful or rejects with error if not.
* @returns {Promise} Promise, that resolves with SqliteClient if _credentials is successful or rejects with error if not.
*/
connect () {
return new Promise((resolve, reject) => {
if (!this._connect) {
return reject(new IllegalFunctionArgumentError('connect'))
// .options() will ensure that credentials.database is set
if (!this._credentials) {
return reject(new IllegalFunctionArgumentError('options.credentials'))
}
this._dbc = new Database(this._connect.host, (err) => {
this._dbc = new Database(this._credentials.database, err => {
if (err) {

@@ -102,3 +78,3 @@ return reject(err)

return new Promise((resolve, reject) => {
this._dbc.close((err) => {
this._dbc.close(err => {
if (err) {

@@ -141,3 +117,3 @@ return reject(err)

* @param {string|object} query - SQL string or CQN object generated by the DML statements.
* @param {Array} [values] - Values to be set in the SQL statement if query is provided as string.
* @param {Array} [values] - Values to be set in the SQL statement if query is provided as string or as CQN object with placeholders.
* @returns {Promise} Promise, that resolves with result object (array) if successful or rejects with error if not.

@@ -172,10 +148,15 @@ *

const {sql, values = []} = sqlFactory(newQuery, {
typeConversion: this._typeConversionMap,
user: this._user,
now: {sql: 'strftime(\'%Y-%m-%dT%H:%M:%SZ\',\'now\')'} // '2012-12-03T07:16:23Z'
}, this._csn)
if (hasCompositionDelete(this._csn && this._csn.definitions, newQuery)) {
return this._processCascadeDelete(newQuery)
}
return this._executeSQL(sql, values, getPostProcessMapper(this._toService, this._csn, newQuery))
if (hasDeepInsert(this._csn && this._csn.definitions, newQuery)) {
return this._processDeepInsert(newQuery)
}
if (hasDeepUpdate(this._csn && this._csn.definitions, newQuery)) {
return this._processDeepUpdate(newQuery)
}
return this._execute(newQuery, values)
// The clients of this client are expecting a promise return in any case.

@@ -187,2 +168,16 @@ } catch (err) {

_execute (cqn, inValues = []) {
const { sql, values = [] } = sqlFactory(
cqn,
{
typeConversion: this._typeConversionMap,
user: this._user,
now: { sql: "strftime('%Y-%m-%dT%H:%M:%SZ','now')" } // '2012-12-03T07:16:23Z'
},
this._csn
)
const outValues = inValues.length > 0 ? inValues : values
return this._executeSQL(sql, outValues, getPostProcessMapper(this._toService, this._csn, cqn))
}
/**

@@ -211,3 +206,3 @@ * Checks which of the sqlite3 is most fitting for the sql values combination.

// Regex is faster than toLower + trim + startsWith
return (new RegExp(`^\\s*${type}`, 'i')).test(sql)
return new RegExp(`^\\s*${type}`, 'i').test(sql)
}

@@ -220,3 +215,4 @@

if (err) {
return reject(new SqlError(err, sql, values))
err.failedQuery = sql
return reject(err)
}

@@ -233,3 +229,4 @@

if (err) {
return reject(new SqlError(err, sql, values))
err.failedQuery = sql
return reject(err)
}

@@ -242,56 +239,10 @@

/**
* One can not use more than 999 values per insert.
* There is no build in bulk support of sqlite3.
* This requires to split into multiple SQLs in case the total sum of values is greater than 999.
*/
_bulkInsert (sql, values) {
const valuesPerRow = values[0].length
const placeholders = this._getBulkPlaceholders(valuesPerRow)
const promises = []
// In case 999 will be reached this vars will be reset
let bulkSql = sql
let flattenedValues = []
for (const insert of values) {
// Execute as adding this row would add more values than supported
if ((flattenedValues.length + valuesPerRow) > 999) {
promises.push(this._runSingle(bulkSql, flattenedValues))
bulkSql = sql
flattenedValues = []
}
// Array is empty on first run and after reset
if (flattenedValues.length !== 0) {
bulkSql += placeholders
}
flattenedValues.push(...insert)
}
// Ensure last bulk is executed
promises.push(this._runSingle(bulkSql, flattenedValues))
// Wait for all inserts to be done
return Promise.all(promises)
.then(() => {
// return affected rows
return values.length
})
return this.prepareStatement(sql)
.then(stmt => stmt.execute(values))
.then(() => values.length)
}
_getBulkPlaceholders (valuesPerRow) {
const placeholders = []
for (let i = 0; i < valuesPerRow; i++) {
placeholders.push('?')
}
return `,(${placeholders.join(',')})`
}
_processExpand (cqn) {
const sqls = []
const queries = []
const expandQueries = createJoinCQNFromExpanded(cqn, this._csn)

@@ -302,12 +253,33 @@

const {sql, values} = sqlFactory(cqn)
sqls.push(this._executeSelect(sql, values, false))
const { sql, values } = sqlFactory(cqn)
queries.push(this._executeSelect(sql, values, false))
}
return Promise.all(sqls)
.then((results) => {
return rawToExpanded(expandQueries, results)
})
return rawToExpanded(expandQueries, queries)
}
_processCascadeDelete (cqn) {
return this.processNestedCQNs(
createCascadeDeleteCQNs(this._csn && this._csn.definitions, cqn),
this._execute.bind(this)
)
}
_processDeepInsert (cqn) {
return this.processNestedCQNs(
[createDeepInsertCQNs(this._csn && this._csn.definitions, cqn)],
this._execute.bind(this)
)
}
_processDeepUpdate (cqn) {
/* istanbul ignore next */
return selectDeepUpdateData(this._csn && this._csn.definitions, cqn, this._execute.bind(this)).then(selectData => {
return this.processNestedCQNs(
createDeepUpdateCQNs(this._csn && this._csn.definitions, cqn, selectData),
this._execute.bind(this)
)
})
}
/**

@@ -322,5 +294,6 @@ * Prepare SQL statement.

this._dbc.serialize(() => {
const stmt = this._dbc.prepare(sql, (err) => {
const stmt = this._dbc.prepare(sql, err => {
if (err) {
return reject(new SqlError(err, sql))
err.failedQuery = sql
return reject(err)
}

@@ -350,4 +323,3 @@

*/
setLocale () {
}
setLocale () {}

@@ -354,0 +326,0 @@ /**

@@ -1,28 +0,56 @@

const {IllegalFunctionArgumentError} = require('@sap/cds-sql').errors
const { errors: { IllegalFunctionArgumentError } } = require('@sap/cds-sql')
const _validateDatabase = database => {
if (!database) {
throw new IllegalFunctionArgumentError('options.credentials.database')
}
}
const _validatePool = options => {
if (options.pool.min > options.pool.max) {
throw new IllegalFunctionArgumentError('options.pool.min')
}
if (options.credentials.database === ':memory:') {
if (options.pool.max !== 1) {
throw new IllegalFunctionArgumentError('options.pool.max')
}
if (options.pool.evictionRunIntervalMillis !== 0) {
throw new IllegalFunctionArgumentError('options.pool.evictionRunIntervalMillis')
}
if (options.pool.idleTimeoutMillisForPools !== 0) {
throw new IllegalFunctionArgumentError('options.pool.idleTimeoutMillisForPools')
}
}
}
/**
* Validates the connect and pool options and adds defaults if not given.
* @param {Object} [options] - The db connection options.
* @param {Object} [options.url] - Connect url with driver.
* @param {Object} [options.database] - Alias for url.
* @param {Object} [options.driver] - Package ID of driver facade.
* @param {string} [options.host] - Filename to the database or :memory: for in memory
* @param {string} [options.user] - Username for authentication
* @param {string} [options.password] - Password for authentication
* @param {Object} [options.credentials] - The db connection options.
* @param {Object} [options.credentials.database] - Alias for url.
* @param {Object} [options.pool] - The min and max pool options.
* @param {number} [options.pool.min] - The minimum number of db connection clients.
* @param {number} [options.pool.max] - The maximum number of db connection clients.
* @throws {Error} If pool is set up with more than one client in ':memory' case
* @param {number} [options.pool.evictionRunIntervalMillis] - How often to run eviction checks.
* @param {number} [options.pool.idleTimeoutMillisForPools] - The time interval in ms until an idle pool is evicted.
* @throws {IllegalFunctionArgumentError}
*/
const options = (options) => {
options.host = options.host || options.database || options.url || ':memory:'
const options = options => {
options.credentials = options.credentials || {}
options.credentials.database = options.credentials.database || options.database || options.host || options.url
options.pool.min = options.pool.min || 1
options.pool.max = options.pool.max || ((options.host === ':memory:') ? 1 : 10)
options.pool.max = options.pool.max || (options.credentials.database === ':memory:' ? 1 : 10)
options.pool.evictionRunIntervalMillis =
options.pool.evictionRunIntervalMillis || (options.credentials.database === ':memory:' ? 0 : 10000)
options.pool.idleTimeoutMillisForPools =
options.pool.idleTimeoutMillisForPools || (options.credentials.database === ':memory:' ? 0 : 60000)
if (options.host === ':memory:' && options.pool.max !== 1) {
throw new IllegalFunctionArgumentError('pool')
}
_validateDatabase(options.credentials.database)
_validatePool(options)
}
module.exports = options
const dependencies = {
get Client () {
const Client = require('./client').Client
Object.defineProperty(dependencies, 'Client', {value: Client})
Object.defineProperty(dependencies, 'Client', { value: Client })
return Client

@@ -9,3 +9,3 @@ },

const options = require('./client').options
Object.defineProperty(dependencies, 'options', {value: options})
Object.defineProperty(dependencies, 'options', { value: options })
return options

@@ -15,3 +15,3 @@ },

const SqliteStatement = require('./statement/SqliteStatement')
Object.defineProperty(dependencies, 'SqliteStatement', {value: SqliteStatement})
Object.defineProperty(dependencies, 'SqliteStatement', { value: SqliteStatement })
return SqliteStatement

@@ -18,0 +18,0 @@ },

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

const {IllegalFunctionArgumentError} = require('@sap/cds-sql').errors
const { IllegalFunctionArgumentError } = require('@sap/cds-sql').errors

@@ -68,12 +68,14 @@ class SqliteStatement {

values.forEach((val) => {
listPromise.push(new Promise((resolve, reject) => {
this._stmt.all(val, (err) => {
if (err) {
return reject(err)
}
values.forEach(val => {
listPromise.push(
new Promise((resolve, reject) => {
this._stmt.all(val, err => {
if (err) {
return reject(err)
}
resolve()
resolve()
})
})
}))
)
})

@@ -88,3 +90,3 @@

})
.catch((err) => {
.catch(err => {
this._stmt.finalize() // statement must be finalized also in case of error

@@ -91,0 +93,0 @@ reject(err)

{
"name": "@sap/cds-sqlite",
"version": "0.9.0",
"version": "1.5.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"@sap/cds-sql": {
"version": "0.11.0"
"version": "1.5.0"
}
}
}

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

{"bundleDependencies":false,"dependencies":{"@sap/cds-sql":"0.11.0"},"deprecated":false,"description":"Driver package for access to sqlite database, including setting up the client, configuring all the necessary options to initiate the connection and handling database specifics so that they can be processed on our end.","devDependencies":{"@sap/cds":"git://github.wdf.sap.corp/cdx/cds","jest":"^23.4.0","jest-junit":"^3.6.0","jsdoc-to-markdown":"^4.0.1","request":"2.83.0","sqlite3":"4.0.1","standard":"^11.0.0","standard-reporter":"^1.0.5"},"engines":{"node":">= 6.11.0"},"jest":{"testEnvironment":"node"},"jest-junit":{"suiteName":"jest tests","output":"reports/sonar/test-reporter.xml","classNameTemplate":"{classname}-{title}","titleTemplate":"{classname}-{title}","ancestorSeparator":" › ","usePathForSuiteName":"true"},"main":"lib/index.js","name":"@sap/cds-sqlite","scripts":{"build":"npm run test && npm run jsdoc2md","clean":"rm -rf reports && rm -f npm-debug.log","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","test":"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":"0.9.0","license":"SEE LICENSE IN developer-license-3.1.txt"}
{"bundleDependencies":false,"dependencies":{"@sap/cds-sql":"1.5.0"},"deprecated":false,"description":"Driver package for access to sqlite database, including setting up the client, configuring all the necessary options to initiate the connection and handling database specifics so that they can be processed on our end.","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-sqlite","version":"1.5.0","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