Comparing version 3.0.1 to 3.1.0
@@ -9,2 +9,3 @@ // MySQL Client | ||
const Transaction = require('./transaction'); | ||
const QueryBuilder = require('./query/mysql-querybuilder'); | ||
const QueryCompiler = require('./query/mysql-querycompiler'); | ||
@@ -27,2 +28,6 @@ const SchemaCompiler = require('./schema/mysql-compiler'); | ||
queryBuilder() { | ||
return new QueryBuilder(this); | ||
} | ||
queryCompiler(builder, formatter) { | ||
@@ -29,0 +34,0 @@ return new QueryCompiler(this, builder, formatter); |
@@ -30,2 +30,9 @@ // MySQL Query Compiler | ||
} | ||
// Compiles an `delete` allowing comments | ||
del() { | ||
const sql = super.del(); | ||
if (sql === '') return sql; | ||
const comments = this.comments(); | ||
return (comments === '' ? '' : comments + ' ') + sql; | ||
} | ||
@@ -37,2 +44,4 @@ // Compiles an `insert` query, allowing for multiple | ||
if (sql === '') return sql; | ||
const comments = this.comments(); | ||
sql = (comments === '' ? '' : comments + ' ') + sql; | ||
@@ -54,2 +63,9 @@ const { ignore, merge, insert } = this.single; | ||
upsert() { | ||
const upsertValues = this.single.upsert || []; | ||
const sql = this.with() + `replace into ${this.tableName} `; | ||
const body = this._insertBody(upsertValues); | ||
return body === '' ? '' : sql + body; | ||
} | ||
// Compiles merge for onConflict, allowing for different merge strategies | ||
@@ -92,2 +108,3 @@ _merge(updates, insert) { | ||
update() { | ||
const comments = this.comments(); | ||
const withSQL = this.with(); | ||
@@ -100,2 +117,3 @@ const join = this.join(); | ||
return ( | ||
(comments === '' ? '' : comments + ' ') + | ||
withSQL + | ||
@@ -102,0 +120,0 @@ `update ${this.tableName}` + |
@@ -163,2 +163,10 @@ /* eslint max-len:0*/ | ||
} | ||
const bigIncrementsCols = this._getBigIncrementsColumnNames(); | ||
if (bigIncrementsCols.length) { | ||
bigIncrementsCols.forEach((c) => { | ||
if (!columns.includes(c)) { | ||
columns.unshift(c); | ||
} | ||
}); | ||
} | ||
} | ||
@@ -296,2 +304,3 @@ | ||
let incrementsCols = []; | ||
let bigIncrementsCols = []; | ||
if (this.grouped.columns) { | ||
@@ -306,2 +315,10 @@ incrementsCols = this._getIncrementsColumnNames(); | ||
} | ||
bigIncrementsCols = this._getBigIncrementsColumnNames(); | ||
if (bigIncrementsCols) { | ||
bigIncrementsCols.forEach((c) => { | ||
if (!primaryCols.includes(c)) { | ||
primaryCols.unshift(c); | ||
} | ||
}); | ||
} | ||
} | ||
@@ -322,2 +339,9 @@ if (this.method !== 'create' && this.method !== 'createIfNot') { | ||
} | ||
if (bigIncrementsCols.length) { | ||
this.pushQuery( | ||
`alter table ${this.tableName()} modify column ${this.formatter.columnize( | ||
bigIncrementsCols | ||
)} bigint unsigned not null auto_increment` | ||
); | ||
} | ||
} | ||
@@ -324,0 +348,0 @@ |
@@ -5,2 +5,4 @@ const Trigger = require('./trigger'); | ||
function createAutoIncrementTriggerAndSequence(columnCompiler) { | ||
const trigger = new Trigger(columnCompiler.client.version); | ||
// TODO Add warning that sequence etc is created | ||
@@ -10,3 +12,3 @@ columnCompiler.pushAdditional(function () { | ||
const schemaName = this.tableCompiler.schemaNameRaw; | ||
const createTriggerSQL = Trigger.createAutoIncrementTrigger( | ||
const createTriggerSQL = trigger.createAutoIncrementTrigger( | ||
this.client.logger, | ||
@@ -13,0 +15,0 @@ tableName, |
@@ -1,6 +0,10 @@ | ||
const utils = require('../../utils'); | ||
const { NameHelper } = require('../../utils'); | ||
const trigger = { | ||
renameColumnTrigger: function (logger, tableName, columnName, to) { | ||
const triggerName = utils.generateCombinedName( | ||
class Trigger { | ||
constructor(oracleVersion) { | ||
this.nameHelper = new NameHelper(oracleVersion); | ||
} | ||
renameColumnTrigger(logger, tableName, columnName, to) { | ||
const triggerName = this.nameHelper.generateCombinedName( | ||
logger, | ||
@@ -10,3 +14,7 @@ 'autoinc_trg', | ||
); | ||
const sequenceName = utils.generateCombinedName(logger, 'seq', tableName); | ||
const sequenceName = this.nameHelper.generateCombinedName( | ||
logger, | ||
'seq', | ||
tableName | ||
); | ||
return ( | ||
@@ -45,5 +53,5 @@ `DECLARE ` + | ||
); | ||
}, | ||
} | ||
createAutoIncrementTrigger: function (logger, tableName, schemaName) { | ||
createAutoIncrementTrigger(logger, tableName, schemaName) { | ||
const tableQuoted = `"${tableName}"`; | ||
@@ -53,3 +61,3 @@ const tableUnquoted = tableName; | ||
const constraintOwner = schemaName ? `'${schemaName}'` : 'cols.owner'; | ||
const triggerName = utils.generateCombinedName( | ||
const triggerName = this.nameHelper.generateCombinedName( | ||
logger, | ||
@@ -59,3 +67,3 @@ 'autoinc_trg', | ||
); | ||
const sequenceNameUnquoted = utils.generateCombinedName( | ||
const sequenceNameUnquoted = this.nameHelper.generateCombinedName( | ||
logger, | ||
@@ -93,6 +101,6 @@ 'seq', | ||
); | ||
}, | ||
} | ||
renameTableAndAutoIncrementTrigger: function (logger, tableName, to) { | ||
const triggerName = utils.generateCombinedName( | ||
renameTableAndAutoIncrementTrigger(logger, tableName, to) { | ||
const triggerName = this.nameHelper.generateCombinedName( | ||
logger, | ||
@@ -102,5 +110,17 @@ 'autoinc_trg', | ||
); | ||
const sequenceName = utils.generateCombinedName(logger, 'seq', tableName); | ||
const toTriggerName = utils.generateCombinedName(logger, 'autoinc_trg', to); | ||
const toSequenceName = utils.generateCombinedName(logger, 'seq', to); | ||
const sequenceName = this.nameHelper.generateCombinedName( | ||
logger, | ||
'seq', | ||
tableName | ||
); | ||
const toTriggerName = this.nameHelper.generateCombinedName( | ||
logger, | ||
'autoinc_trg', | ||
to | ||
); | ||
const toSequenceName = this.nameHelper.generateCombinedName( | ||
logger, | ||
'seq', | ||
to | ||
); | ||
return ( | ||
@@ -138,5 +158,5 @@ `DECLARE ` + | ||
); | ||
}, | ||
}; | ||
} | ||
} | ||
module.exports = trigger; | ||
module.exports = Trigger; |
@@ -14,3 +14,4 @@ // Oracle Schema Compiler | ||
renameTable(tableName, to) { | ||
const renameTable = Trigger.renameTableAndAutoIncrementTrigger( | ||
const trigger = new Trigger(this.client.version); | ||
const renameTable = trigger.renameTableAndAutoIncrementTrigger( | ||
this.client.logger, | ||
@@ -64,3 +65,4 @@ tableName, | ||
// removing the sequence that was possibly generated by increments() column | ||
const sequenceName = utils.generateCombinedName( | ||
const nameHelper = new utils.NameHelper(this.client.version); | ||
const sequenceName = nameHelper.generateCombinedName( | ||
this.client.logger, | ||
@@ -67,0 +69,0 @@ 'seq', |
@@ -42,4 +42,5 @@ /* eslint max-len:0 */ | ||
const tableName = this.tableName().slice(1, -1); | ||
const trigger = new Trigger(this.client.version); | ||
return this.pushQuery( | ||
Trigger.renameColumnTrigger(this.client.logger, tableName, from, to) | ||
trigger.renameColumnTrigger(this.client.logger, tableName, from, to) | ||
); | ||
@@ -90,4 +91,10 @@ } | ||
_indexCommand(type, tableName, columns) { | ||
const nameHelper = new utils.NameHelper(this.client.version); | ||
return this.formatter.wrap( | ||
utils.generateCombinedName(this.client.logger, type, tableName, columns) | ||
nameHelper.generateCombinedName( | ||
this.client.logger, | ||
type, | ||
tableName, | ||
columns | ||
) | ||
); | ||
@@ -94,0 +101,0 @@ } |
@@ -1,23 +0,42 @@ | ||
function generateCombinedName(logger, postfix, name, subNames) { | ||
const crypto = require('crypto'); | ||
const limit = 30; | ||
if (!Array.isArray(subNames)) subNames = subNames ? [subNames] : []; | ||
const table = name.replace(/\.|-/g, '_'); | ||
const subNamesPart = subNames.join('_'); | ||
let result = `${table}_${ | ||
subNamesPart.length ? subNamesPart + '_' : '' | ||
}${postfix}`.toLowerCase(); | ||
if (result.length > limit) { | ||
logger.warn( | ||
`Automatically generated name "${result}" exceeds ${limit} character ` + | ||
`limit for Oracle. Using base64 encoded sha1 of that name instead.` | ||
); | ||
// generates the sha1 of the name and encode it with base64 | ||
result = crypto | ||
.createHash('sha1') | ||
.update(result) | ||
.digest('base64') | ||
.replace('=', ''); | ||
class NameHelper { | ||
constructor(oracleVersion) { | ||
this.oracleVersion = oracleVersion; | ||
// In oracle versions prior to 12.2, the maximum length for a database | ||
// object name was 30 characters. 12.2 extended this to 128. | ||
const versionParts = oracleVersion | ||
.split('.') | ||
.map((versionPart) => parseInt(versionPart)); | ||
if ( | ||
versionParts[0] > 12 || | ||
(versionParts[0] === 12 && versionParts[1] >= 2) | ||
) { | ||
this.limit = 128; | ||
} else { | ||
this.limit = 30; | ||
} | ||
} | ||
return result; | ||
generateCombinedName(logger, postfix, name, subNames) { | ||
const crypto = require('crypto'); | ||
if (!Array.isArray(subNames)) subNames = subNames ? [subNames] : []; | ||
const table = name.replace(/\.|-/g, '_'); | ||
const subNamesPart = subNames.join('_'); | ||
let result = `${table}_${ | ||
subNamesPart.length ? subNamesPart + '_' : '' | ||
}${postfix}`.toLowerCase(); | ||
if (result.length > this.limit) { | ||
logger.warn( | ||
`Automatically generated name "${result}" exceeds ${this.limit} character ` + | ||
`limit for Oracle Database ${this.oracleVersion}. Using base64 encoded sha1 of that name instead.` | ||
); | ||
// generates the sha1 of the name and encode it with base64 | ||
result = crypto | ||
.createHash('sha1') | ||
.update(result) | ||
.digest('base64') | ||
.replace('=', ''); | ||
} | ||
return result; | ||
} | ||
} | ||
@@ -83,3 +102,3 @@ | ||
module.exports = { | ||
generateCombinedName, | ||
NameHelper, | ||
isConnectionError, | ||
@@ -86,0 +105,0 @@ wrapSqlWithCatch, |
@@ -28,2 +28,9 @@ // Oracledb Client | ||
super(config); | ||
if (this.version) { | ||
// Normalize version format; null bad format | ||
// to trigger fallback to auto-detect. | ||
this.version = parseVersion(this.version); | ||
} | ||
if (this.driver) { | ||
@@ -124,11 +131,10 @@ process.env.UV_THREADPOOL_SIZE = process.env.UV_THREADPOOL_SIZE || 1; | ||
acquireRawConnection() { | ||
const client = this; | ||
const asyncConnection = new Promise(function (resolver, rejecter) { | ||
return new Promise((resolver, rejecter) => { | ||
// If external authentication don't have to worry about username/password and | ||
// if not need to set the username and password | ||
const oracleDbConfig = client.connectionSettings.externalAuth | ||
? { externalAuth: client.connectionSettings.externalAuth } | ||
const oracleDbConfig = this.connectionSettings.externalAuth | ||
? { externalAuth: this.connectionSettings.externalAuth } | ||
: { | ||
user: client.connectionSettings.user, | ||
password: client.connectionSettings.password, | ||
user: this.connectionSettings.user, | ||
password: this.connectionSettings.password, | ||
}; | ||
@@ -138,21 +144,20 @@ | ||
oracleDbConfig.connectString = resolveConnectString( | ||
client.connectionSettings | ||
this.connectionSettings | ||
); | ||
if (client.connectionSettings.prefetchRowCount) { | ||
oracleDbConfig.prefetchRows = | ||
client.connectionSettings.prefetchRowCount; | ||
if (this.connectionSettings.prefetchRowCount) { | ||
oracleDbConfig.prefetchRows = this.connectionSettings.prefetchRowCount; | ||
} | ||
if (client.connectionSettings.stmtCacheSize !== undefined) { | ||
oracleDbConfig.stmtCacheSize = client.connectionSettings.stmtCacheSize; | ||
if (this.connectionSettings.stmtCacheSize !== undefined) { | ||
oracleDbConfig.stmtCacheSize = this.connectionSettings.stmtCacheSize; | ||
} | ||
client.driver.fetchAsString = client.fetchAsString; | ||
this.driver.fetchAsString = this.fetchAsString; | ||
client.driver.getConnection(oracleDbConfig, function (err, connection) { | ||
this.driver.getConnection(oracleDbConfig, (err, connection) => { | ||
if (err) { | ||
return rejecter(err); | ||
} | ||
monkeyPatchConnection(connection, client); | ||
monkeyPatchConnection(connection, this); | ||
@@ -162,3 +167,2 @@ resolver(connection); | ||
}); | ||
return asyncConnection; | ||
} | ||
@@ -172,2 +176,35 @@ | ||
// Handle oracle version resolution on acquiring connection from pool instead of connection creation. | ||
// Must do this here since only the client used to create a connection would be updated with version | ||
// information on creation. Poses a problem when knex instance is cloned since instances share the | ||
// connection pool while having their own client instances. | ||
async acquireConnection() { | ||
const connection = await super.acquireConnection(); | ||
this.checkVersion(connection); | ||
return connection; | ||
} | ||
// In Oracle, we need to check the version to dynamically determine | ||
// certain limits. If user did not specify a version, get it from the connection. | ||
checkVersion(connection) { | ||
// Already determined version before? | ||
if (this.version) { | ||
return this.version; | ||
} | ||
const detectedVersion = parseVersion(connection.oracleServerVersionString); | ||
if (!detectedVersion) { | ||
// When original version is set to null, user-provided version was invalid and we fell-back to auto-detect. | ||
// Otherwise, we couldn't auto-detect at all. Set error message accordingly. | ||
throw new Error( | ||
this.version === null | ||
? 'Invalid Oracledb version number format passed to knex. Unable to successfully auto-detect as fallback. Please specify a valid oracledb version.' | ||
: 'Unable to detect Oracledb version number automatically. Please specify the version in knex configuration.' | ||
); | ||
} | ||
this.version = detectedVersion; | ||
return detectedVersion; | ||
} | ||
// Runs the query on the specified connection, providing the bindings | ||
@@ -308,2 +345,3 @@ // and any other necessary prep work. | ||
processPassedConnection(connection) { | ||
this.checkVersion(connection); | ||
monkeyPatchConnection(connection, this); | ||
@@ -315,2 +353,18 @@ } | ||
function parseVersion(versionString) { | ||
try { | ||
// We only care about first two version components at most | ||
const versionParts = versionString.split('.').slice(0, 2); | ||
// Strip off any character suffixes in version number (ex. 12c => 12, 12.2c => 12.2) | ||
versionParts.forEach((versionPart, idx) => { | ||
versionParts[idx] = versionPart.replace(/\D$/, ''); | ||
}); | ||
const version = versionParts.join('.'); | ||
return version.match(/^\d+\.?\d*$/) ? version : null; | ||
} catch (err) { | ||
// Non-string versionString passed in. | ||
return null; | ||
} | ||
} | ||
function resolveConnectString(connectionSettings) { | ||
@@ -317,0 +371,0 @@ if (connectionSettings.connectString) { |
@@ -197,3 +197,6 @@ // PostgreSQL | ||
const queryStream = connection.query( | ||
new PGQueryStream(sql, obj.bindings, options) | ||
new PGQueryStream(sql, obj.bindings, options), | ||
(err) => { | ||
rejecter(err); | ||
} | ||
); | ||
@@ -200,0 +203,0 @@ |
@@ -222,2 +222,6 @@ // Transaction | ||
.then((transactor) => { | ||
this.transactor = transactor; | ||
if (this.outerTx) { | ||
transactor.parentTransaction = this.outerTx.transactor; | ||
} | ||
transactor.executionPromise = executionPromise; | ||
@@ -224,0 +228,0 @@ |
@@ -1733,3 +1733,3 @@ // Builder | ||
Builder.prototype.andWhereJsonObject = Builder.prototype.whereJsonObject; | ||
Builder.prototype.andWhereNotJsonObject = Builder.prototype.whereJsonObject; | ||
Builder.prototype.andWhereNotJsonObject = Builder.prototype.whereNotJsonObject; | ||
Builder.prototype.andWhereJsonPath = Builder.prototype.whereJsonPath; | ||
@@ -1736,0 +1736,0 @@ Builder.prototype.andWhereLike = Builder.prototype.whereLike; |
@@ -421,2 +421,8 @@ /* eslint max-len:0 */ | ||
} | ||
_getBigIncrementsColumnNames() { | ||
return this.grouped.columns | ||
.filter((c) => c.builder._type === 'bigincrements') | ||
.map((c) => c.builder._args[0]); | ||
} | ||
} | ||
@@ -423,0 +429,0 @@ |
{ | ||
"name": "knex", | ||
"version": "3.0.1", | ||
"version": "3.1.0", | ||
"description": "A batteries-included SQL query & schema builder for PostgresSQL, MySQL, CockroachDB, MSSQL and SQLite3", | ||
@@ -20,5 +20,6 @@ "main": "knex", | ||
"coveralls": "nyc report --reporter=lcov", | ||
"lint": "eslint --cache **/*.js", | ||
"lint:fix": "eslint --cache --fix '**/*.js'", | ||
"lint:types": "tsd && dtslint types", | ||
"lint": "eslint --cache .", | ||
"lint:fix": "eslint --cache --fix .", | ||
"lint:types": "tsd", | ||
"lint:types:legacy": "dtslint types", | ||
"lint:everything": "npm run lint && npm run lint:types", | ||
@@ -74,3 +75,3 @@ "lint:fix:everything": "npm run lint:fix && npm run lint:types", | ||
"lodash": "^4.17.21", | ||
"pg-connection-string": "2.6.1", | ||
"pg-connection-string": "2.6.2", | ||
"rechoir": "^0.8.0", | ||
@@ -111,3 +112,3 @@ "resolve-from": "^5.0.0", | ||
"@types/node": "^20.4.0", | ||
"better-sqlite3": "^7.6.2", | ||
"better-sqlite3": "^9.1.1", | ||
"chai": "^4.3.6", | ||
@@ -120,5 +121,5 @@ "chai-as-promised": "^7.1.1", | ||
"dtslint": "4.2.1", | ||
"eslint": "^8.32.0", | ||
"eslint": "^8.54.0", | ||
"eslint-config-prettier": "^8.6.0", | ||
"eslint-plugin-import": "^2.26.0", | ||
"eslint-plugin-import": "^2.29.0", | ||
"eslint-plugin-mocha-no-only": "^1.1.1", | ||
@@ -139,3 +140,3 @@ "eslint-plugin-prettier": "^4.2.1", | ||
"prettier": "2.8.7", | ||
"rimraf": "^3.0.2", | ||
"rimraf": "^5.0.5", | ||
"sinon": "^15.0.1", | ||
@@ -147,3 +148,3 @@ "sinon-chai": "^3.7.0", | ||
"tape": "^5.6.0", | ||
"tedious": "^14.4.0", | ||
"tedious": "^16.6.1", | ||
"toxiproxy-node-client": "^2.0.6", | ||
@@ -150,0 +151,0 @@ "ts-node": "^10.9.1", |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
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
873885
191
23417
+ Addedpg-connection-string@2.6.2(transitive)
- Removedpg-connection-string@2.6.1(transitive)
Updatedpg-connection-string@2.6.2