Skip to content

Commit

Permalink
Merge branch 'hide-sensitive-data' of github.com:JakobJoonas/knex int…
Browse files Browse the repository at this point in the history
…o hide-sensitive-data
  • Loading branch information
JakobJoonas committed Sep 6, 2022
2 parents 8f0177a + d91bbdb commit 83d18cd
Show file tree
Hide file tree
Showing 23 changed files with 465 additions and 77 deletions.
16 changes: 16 additions & 0 deletions CHANGELOG.md
@@ -1,5 +1,21 @@
# Master (Unreleased)

# 2.3.0 - 31 August, 2022

### New features:

- PostgreSQL: Explicit jsonb support for custom pg clients #5201
- SQLite: Support returning with sqlite3 and better-sqlite3 #5285
- MSSQL: Implement mapBinding mssql dialect option #5292

### Typings:

- Update types for TS 4.8 #5279
- Fix typo #5267
- Fix WhereJsonObject withCompositeTableType #5306
- Fix AnalyticFunction type #5304
- Infer specific column value type in aggregations #5297

# 2.2.0 - 19 July, 2022

### New features:
Expand Down
2 changes: 1 addition & 1 deletion lib/client.js
Expand Up @@ -396,7 +396,7 @@ class Client extends EventEmitter {
if (i > 0) str += ', ';
let value = values[i];
// json columns can have object in values.
if (isPlainObject(value)) {
if (isPlainObject(value) || Array.isArray(value)) {
value = JSON.stringify(value);
}
str += this.parameter(
Expand Down
34 changes: 20 additions & 14 deletions lib/dialects/mssql/index.js
Expand Up @@ -333,14 +333,24 @@ class Client_MSSQL extends Client {
_typeForBinding(binding) {
const Driver = this._driver();

if (
this.connectionSettings.options &&
this.connectionSettings.options.mapBinding
) {
const result = this.connectionSettings.options.mapBinding(binding);
if (result) {
return [result.value, result.type];
}
}

switch (typeof binding) {
case 'string':
return Driver.TYPES.NVarChar;
return [binding, Driver.TYPES.NVarChar];
case 'boolean':
return Driver.TYPES.Bit;
return [binding, Driver.TYPES.Bit];
case 'number': {
if (binding % 1 !== 0) {
return Driver.TYPES.Float;
return [binding, Driver.TYPES.Float];
}

if (binding < SQL_INT4.MIN || binding > SQL_INT4.MAX) {
Expand All @@ -350,25 +360,21 @@ class Client_MSSQL extends Client {
);
}

return Driver.TYPES.BigInt;
return [binding, Driver.TYPES.BigInt];
}

return Driver.TYPES.Int;
return [binding, Driver.TYPES.Int];
}
default: {
// if (binding === null || typeof binding === 'undefined') {
// return tedious.TYPES.Null;
// }

if (binding instanceof Date) {
return Driver.TYPES.DateTime;
return [binding, Driver.TYPES.DateTime];
}

if (binding instanceof Buffer) {
return Driver.TYPES.VarBinary;
return [binding, Driver.TYPES.VarBinary];
}

return Driver.TYPES.NVarChar;
return [binding, Driver.TYPES.NVarChar];
}
}
}
Expand Down Expand Up @@ -401,8 +407,8 @@ class Client_MSSQL extends Client {
}

// sets a request input parameter. Detects bigints and decimals and sets type appropriately.
_setReqInput(req, i, binding) {
const tediousType = this._typeForBinding(binding);
_setReqInput(req, i, inputBinding) {
const [binding, tediousType] = this._typeForBinding(inputBinding);
const bindingName = 'p'.concat(i);
let options;

Expand Down
22 changes: 14 additions & 8 deletions lib/dialects/mssql/schema/mssql-tablecompiler.js
Expand Up @@ -280,20 +280,24 @@ class TableCompiler_MSSQL extends TableCompiler {
* Create a unique index.
*
* @param {string | string[]} columns
* @param {string | {indexName: undefined | string, deferrable?: 'not deferrable'|'deferred'|'immediate', useConstraint?: true|false }} indexName
* @param {string | {indexName: undefined | string, deferrable?: 'not deferrable'|'deferred'|'immediate', useConstraint?: true|false, predicate?: QueryBuilder }} indexName
*/
unique(columns, indexName) {
/** @type {string | undefined} */
let deferrable;
let useConstraint = false;
let predicate;
if (isObject(indexName)) {
({ indexName, deferrable, useConstraint } = indexName);
({ indexName, deferrable, useConstraint, predicate } = indexName);
}
if (deferrable && deferrable !== 'not deferrable') {
this.client.logger.warn(
`mssql: unique index [${indexName}] will not be deferrable ${deferrable} because mssql does not support deferred constraints.`
);
}
if (useConstraint && predicate) {
throw new Error('mssql cannot create constraint with predicate');
}
indexName = indexName
? this.formatter.wrap(indexName)
: this._indexCommand('unique', this.tableNameRaw, columns);
Expand All @@ -302,10 +306,6 @@ class TableCompiler_MSSQL extends TableCompiler {
columns = [columns];
}

const whereAllTheColumnsAreNotNull = columns
.map((column) => this.formatter.columnize(column) + ' IS NOT NULL')
.join(' AND ');

if (useConstraint) {
// mssql supports unique indexes and unique constraints.
// unique indexes cannot be used with foreign key relationships hence unique constraints are used instead.
Expand All @@ -315,12 +315,18 @@ class TableCompiler_MSSQL extends TableCompiler {
)})`
);
} else {
// make unique constraint that allows null https://stackoverflow.com/a/767702/360060
// default to making unique index that allows null https://stackoverflow.com/a/767702/360060
// to be more or less compatible with other DBs (if any of the columns is NULL then "duplicates" are allowed)
const predicateQuery = predicate
? ' ' + this.client.queryCompiler(predicate).where()
: ' WHERE ' +
columns
.map((column) => this.formatter.columnize(column) + ' IS NOT NULL')
.join(' AND ');
this.pushQuery(
`CREATE UNIQUE INDEX ${indexName} ON ${this.tableName()} (${this.formatter.columnize(
columns
)}) WHERE ${whereAllTheColumnsAreNotNull}`
)})${predicateQuery}`
);
}
}
Expand Down
1 change: 1 addition & 0 deletions lib/dialects/postgres/schema/pg-columncompiler.js
Expand Up @@ -145,6 +145,7 @@ function jsonColumn(client, jsonb) {
if (
!client.version ||
client.config.client === 'cockroachdb' ||
client.config.jsonbSupport === true ||
parseFloat(client.version) >= 9.2
) {
return jsonb ? 'jsonb' : 'json';
Expand Down
40 changes: 32 additions & 8 deletions lib/dialects/postgres/schema/pg-tablecompiler.js
Expand Up @@ -189,20 +189,44 @@ class TableCompiler_PG extends TableCompiler {

unique(columns, indexName) {
let deferrable;
let useConstraint = true;
let predicate;
if (isObject(indexName)) {
({ indexName, deferrable } = indexName);
({ indexName, deferrable, useConstraint, predicate } = indexName);
if (useConstraint === undefined) {
useConstraint = !!deferrable || !predicate;
}
}
if (!useConstraint && deferrable && deferrable !== 'not deferrable') {
throw new Error('postgres cannot create deferrable index');
}
if (useConstraint && predicate) {
throw new Error('postgres cannot create constraint with predicate');
}
deferrable = deferrable ? ` deferrable initially ${deferrable}` : '';
indexName = indexName
? this.formatter.wrap(indexName)
: this._indexCommand('unique', this.tableNameRaw, columns);
this.pushQuery(
`alter table ${this.tableName()} add constraint ${indexName}` +
' unique (' +
this.formatter.columnize(columns) +
')' +
deferrable
);

if (useConstraint) {
this.pushQuery(
`alter table ${this.tableName()} add constraint ${indexName}` +
' unique (' +
this.formatter.columnize(columns) +
')' +
deferrable
);
} else {
const predicateQuery = predicate
? ' ' + this.client.queryCompiler(predicate).where()
: '';

this.pushQuery(
`create unique index ${indexName} on ${this.tableName()} (${this.formatter.columnize(
columns
)})${predicateQuery}`
);
}
}

index(columns, indexName, options) {
Expand Down
16 changes: 10 additions & 6 deletions lib/dialects/sqlite3/index.js
Expand Up @@ -126,6 +126,8 @@ class Client_SQLite3 extends Client {
switch (method) {
case 'insert':
case 'update':
callMethod = obj.returning ? 'all' : 'run';
break;
case 'counter':
case 'del':
callMethod = 'run';
Expand Down Expand Up @@ -190,16 +192,18 @@ class Client_SQLite3 extends Client {
if (response) {
return response;
}

// ToDo Implement after https://github.com/microsoft/vscode-node-sqlite3/issues/15 is resolved
this.logger.warn(
'node-sqlite3 does not currently support RETURNING clause'
);
}
return [ctx.lastID];
}
case 'update': {
if (returning) {
if (response) {
return response;
}
}
return ctx.changes;
}
case 'del':
case 'update':
case 'counter':
return ctx.changes;
default: {
Expand Down
17 changes: 17 additions & 0 deletions lib/dialects/sqlite3/query/sqlite-querycompiler.js
Expand Up @@ -149,6 +149,23 @@ class QueryCompiler_SQLite3 extends QueryCompiler {
};
}

// Compiles an `update` query, allowing for a return value.
update() {
const withSQL = this.with();
const updateData = this._prepUpdate(this.single.update);
const wheres = this.where();
const { returning } = this.single;
return {
sql:
withSQL +
`update ${this.single.only ? 'only ' : ''}${this.tableName} ` +
`set ${updateData.join(', ')}` +
(wheres ? ` ${wheres}` : '') +
this._returning(returning),
returning,
};
}

_ignore(columns) {
if (columns === true) {
return ' on conflict do nothing';
Expand Down
12 changes: 9 additions & 3 deletions lib/dialects/sqlite3/schema/sqlite-tablecompiler.js
Expand Up @@ -51,7 +51,7 @@ class TableCompiler_SQLite3 extends TableCompiler {
const type = col.getColumnType();

const defaultTo = col.modified['defaultTo']
? formatDefault(col.modified['defaultTo'][0], type, this.client)
? formatDefault(col.modified['defaultTo'][0], col.type, this.client)
: null;

const notNull =
Expand Down Expand Up @@ -132,8 +132,9 @@ class TableCompiler_SQLite3 extends TableCompiler {
// Compile a unique key command.
unique(columns, indexName) {
let deferrable;
let predicate;
if (isObject(indexName)) {
({ indexName, deferrable } = indexName);
({ indexName, deferrable, predicate } = indexName);
}
if (deferrable && deferrable !== 'not deferrable') {
this.client.logger.warn(
Expand All @@ -144,8 +145,13 @@ class TableCompiler_SQLite3 extends TableCompiler {
? this.formatter.wrap(indexName)
: this._indexCommand('unique', this.tableNameRaw, columns);
columns = this.formatter.columnize(columns);

const predicateQuery = predicate
? ' ' + this.client.queryCompiler(predicate).where()
: '';

this.pushQuery(
`create unique index ${indexName} on ${this.tableName()} (${columns})`
`create unique index ${indexName} on ${this.tableName()} (${columns})${predicateQuery}`
);
}

Expand Down
3 changes: 1 addition & 2 deletions lib/formatter/wrappingFormatter.js
Expand Up @@ -225,8 +225,7 @@ function rawOrFn(value, method, builder, client, bindingHolder) {
compileCallback(value, method, client, bindingHolder),
undefined,
builder,
client,
bindingHolder
client
);
}
return unwrapRaw(value, undefined, builder, client, bindingHolder) || '';
Expand Down
24 changes: 12 additions & 12 deletions package.json
@@ -1,6 +1,6 @@
{
"name": "knex",
"version": "2.2.0",
"version": "2.3.0",
"description": "A batteries-included SQL query & schema builder for PostgresSQL, MySQL, CockroachDB, MSSQL and SQLite3",
"main": "knex",
"types": "types/index.d.ts",
Expand Down Expand Up @@ -105,8 +105,8 @@
},
"devDependencies": {
"@tsconfig/recommended": "^1.0.1",
"@types/node": "^18.0.4",
"better-sqlite3": "^7.5.1",
"@types/node": "^18.7.14",
"better-sqlite3": "^7.6.2",
"chai": "^4.3.6",
"chai-as-promised": "^7.1.1",
"chai-subset-in-order": "^3.1.0",
Expand All @@ -123,26 +123,26 @@
"JSONStream": "^1.3.5",
"lint-staged": "^13.0.0",
"mocha": "^10.0.0",
"mock-fs": "^5.1.2",
"mock-fs": "^5.1.4",
"mysql": "^2.18.1",
"mysql2": "^2.3.3",
"nyc": "^15.1.0",
"oracledb": "^5.3.0",
"pg": "^8.7.3",
"pg-query-stream": "^4.2.1",
"oracledb": "^5.4.0",
"pg": "^8.8.0",
"pg-query-stream": "^4.2.4",
"prettier": "2.6.2",
"rimraf": "^3.0.2",
"sinon": "^14.0.0",
"sinon-chai": "^3.7.0",
"source-map-support": "^0.5.21",
"sqlite3": "^5.0.4",
"sqlite3": "^5.0.11",
"tap-spec": "^5.0.0",
"tape": "^5.5.3",
"tape": "^5.6.0",
"tedious": "^14.4.0",
"toxiproxy-node-client": "^2.0.6",
"ts-node": "^10.7.0",
"tsd": "^0.22.0",
"typescript": "4.7.4"
"ts-node": "^10.9.1",
"tsd": "^0.23.0",
"typescript": "4.8.2"
},
"buildDependencies": [
"rimraf"
Expand Down

0 comments on commit 83d18cd

Please sign in to comment.