knex
Advanced tools
Comparing version 1.0.1 to 1.0.2
@@ -59,3 +59,3 @@ // better-sqlite3 Client | ||
if (typeof binding === 'boolean') { | ||
return String(binding); | ||
return Number(binding); | ||
} | ||
@@ -62,0 +62,0 @@ |
@@ -31,2 +31,7 @@ const QueryCompiler_PG = require('../postgres/query/pg-querycompiler'); | ||
_groupOrder(item, type) { | ||
// CockroachDB don't support PostgreSQL order nulls first/last syntax, we take the generic one. | ||
return this._basicGroupOrder(item, type); | ||
} | ||
whereJsonPath(statement) { | ||
@@ -33,0 +38,0 @@ let castValue = ''; |
@@ -48,10 +48,9 @@ // MySQL Schema Compiler | ||
const formattedTable = this.client.parameter( | ||
this.formatter.wrap(prefixedTableName(this.schema, tableName)), | ||
prefixedTableName(this.schema, tableName), | ||
this.builder, | ||
this.bindingsHolder | ||
); | ||
const sql = | ||
`select object_id from sys.tables ` + | ||
`where object_id = object_id(${formattedTable})`; | ||
`SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES ` + | ||
`WHERE TABLE_NAME = ${formattedTable}`; | ||
this.pushQuery({ sql, output: (resp) => resp.length > 0 }); | ||
@@ -58,0 +57,0 @@ } |
@@ -83,2 +83,3 @@ // MySQL Query Compiler | ||
update() { | ||
const withSQL = this.with(); | ||
const join = this.join(); | ||
@@ -90,2 +91,3 @@ const updates = this._prepUpdate(this.single.update); | ||
return ( | ||
withSQL + | ||
`update ${this.tableName}` + | ||
@@ -92,0 +94,0 @@ (join ? ` ${join}` : '') + |
@@ -76,3 +76,3 @@ /* eslint max-len:0*/ | ||
sql: | ||
`show fields from ${table} where field = ` + | ||
`show full fields from ${table} where field = ` + | ||
this.client.parameter(from, this.tableBuilder, this.bindingsHolder), | ||
@@ -105,3 +105,6 @@ output(resp) { | ||
} | ||
// Add back the auto increment if the column had it, fix issue #2767 | ||
if (column.Collation !== void 0 && column.Collation !== null) { | ||
sql += ` COLLATE '${column.Collation}'`; | ||
} | ||
// Add back the auto increment if the column it, fix issue #2767 | ||
if (column.Extra == 'auto_increment') { | ||
@@ -108,0 +111,0 @@ sql += ` AUTO_INCREMENT`; |
@@ -11,5 +11,3 @@ const clone = require('lodash/clone'); | ||
columnize: columnize_, | ||
direction: direction_, | ||
} = require('../../../formatter/wrappingFormatter'); | ||
const Raw = require('../../../raw'); | ||
@@ -322,16 +320,3 @@ class Oracledb_Compiler extends Oracle_Compiler { | ||
_groupOrder(item, type) { | ||
const column = super._formatGroupsItemValue(item.value); | ||
const direction = | ||
type === 'order' && item.type !== 'orderByRaw' | ||
? ` ${direction_( | ||
item.direction, | ||
this.builder, | ||
this.client, | ||
this.bindingsHolder | ||
)}` | ||
: ''; | ||
if (item.nulls && !(item.value instanceof Raw)) { | ||
return `${column}${direction ? direction : ''} nulls ${item.nulls}`; | ||
} | ||
return column + direction; | ||
return super._groupOrderNulls(item, type); | ||
} | ||
@@ -338,0 +323,0 @@ |
@@ -8,2 +8,32 @@ const QueryBuilder = require('../../../query/querybuilder.js'); | ||
} | ||
withMaterialized(alias, statementOrColumnList, nothingOrStatement) { | ||
this._validateWithArgs( | ||
alias, | ||
statementOrColumnList, | ||
nothingOrStatement, | ||
'with' | ||
); | ||
return this.withWrapped( | ||
alias, | ||
statementOrColumnList, | ||
nothingOrStatement, | ||
true | ||
); | ||
} | ||
withNotMaterialized(alias, statementOrColumnList, nothingOrStatement) { | ||
this._validateWithArgs( | ||
alias, | ||
statementOrColumnList, | ||
nothingOrStatement, | ||
'with' | ||
); | ||
return this.withWrapped( | ||
alias, | ||
statementOrColumnList, | ||
nothingOrStatement, | ||
false | ||
); | ||
} | ||
}; |
@@ -148,9 +148,7 @@ // PostgreSQL Query Builder & Compiler | ||
} | ||
return ` on conflict (${this.formatter.columnize(columns)}) do nothing`; | ||
return ` on conflict ${this._onConflictClause(columns)} do nothing`; | ||
} | ||
_merge(updates, columns, insert) { | ||
let sql = ` on conflict (${this.formatter.columnize( | ||
columns | ||
)}) do update set `; | ||
let sql = ` on conflict ${this._onConflictClause(columns)} do update set `; | ||
if (updates && Array.isArray(updates)) { | ||
@@ -223,2 +221,6 @@ sql += updates | ||
_groupOrder(item, type) { | ||
return super._groupOrderNulls(item, type); | ||
} | ||
forUpdate() { | ||
@@ -225,0 +227,0 @@ return this._lockingClause('for update'); |
@@ -94,3 +94,2 @@ /* eslint max-len: 0 */ | ||
const isEnum = col.type === 'enu'; | ||
this.pushQuery({ | ||
@@ -100,13 +99,21 @@ sql: `alter table ${quotedTableName} alter column ${colName} drop default`, | ||
}); | ||
this.pushQuery({ | ||
sql: `alter table ${quotedTableName} alter column ${colName} drop not null`, | ||
bindings: [], | ||
}); | ||
this.pushQuery({ | ||
sql: `alter table ${quotedTableName} alter column ${colName} type ${type} using (${colName}${ | ||
isEnum ? '::text::' : '::' | ||
}${type})`, | ||
bindings: [], | ||
}); | ||
const alterNullable = col.columnBuilder.alterNullable; | ||
if (alterNullable) { | ||
this.pushQuery({ | ||
sql: `alter table ${quotedTableName} alter column ${colName} drop not null`, | ||
bindings: [], | ||
}); | ||
} | ||
const alterType = col.columnBuilder.alterType; | ||
if (alterType) { | ||
this.pushQuery({ | ||
sql: `alter table ${quotedTableName} alter column ${colName} type ${type} using (${colName}${ | ||
isEnum ? '::text::' : '::' | ||
}${type})`, | ||
bindings: [], | ||
}); | ||
} | ||
const defaultTo = col.modified['defaultTo']; | ||
@@ -121,8 +128,10 @@ if (defaultTo) { | ||
const nullable = col.modified['nullable']; | ||
if (nullable && nullable[0] === false) { | ||
this.pushQuery({ | ||
sql: `alter table ${quotedTableName} alter column ${colName} set not null`, | ||
bindings: [], | ||
}); | ||
if (alterNullable) { | ||
const nullable = col.modified['nullable']; | ||
if (nullable && nullable[0] === false) { | ||
this.pushQuery({ | ||
sql: `alter table ${quotedTableName} alter column ${colName} set not null`, | ||
bindings: [], | ||
}); | ||
} | ||
} | ||
@@ -129,0 +138,0 @@ } |
@@ -18,2 +18,3 @@ // SQLite3 | ||
const Formatter = require('../../formatter'); | ||
const QueryBuilder = require('./query/sqlite-querybuilder'); | ||
@@ -48,2 +49,6 @@ class Client_SQLite3 extends Client { | ||
queryBuilder() { | ||
return new QueryBuilder(this); | ||
} | ||
viewCompiler(builder, formatter) { | ||
@@ -50,0 +55,0 @@ return new ViewCompiler(this, builder, formatter); |
@@ -156,9 +156,7 @@ // SQLite3 Query Builder & Compiler | ||
} | ||
return ` on conflict (${this.formatter.columnize(columns)}) do nothing`; | ||
return ` on conflict ${this._onConflictClause(columns)} do nothing`; | ||
} | ||
_merge(updates, columns, insert) { | ||
let sql = ` on conflict (${this.formatter.columnize( | ||
columns | ||
)}) do update set `; | ||
let sql = ` on conflict ${this._onConflictClause(columns)} do update set `; | ||
if (updates && Array.isArray(updates)) { | ||
@@ -165,0 +163,0 @@ sql += updates |
@@ -17,21 +17,36 @@ // FunctionHelper | ||
uuidToBin(uuid) { | ||
uuidToBin(uuid, ordered = true) { | ||
const buf = Buffer.from(uuid.replace(/-/g, ''), 'hex'); | ||
return Buffer.concat([ | ||
buf.slice(6, 8), | ||
buf.slice(4, 6), | ||
buf.slice(0, 4), | ||
buf.slice(8, 16), | ||
]); | ||
return ordered | ||
? Buffer.concat([ | ||
buf.slice(6, 8), | ||
buf.slice(4, 6), | ||
buf.slice(0, 4), | ||
buf.slice(8, 16), | ||
]) | ||
: Buffer.concat([ | ||
buf.slice(0, 4), | ||
buf.slice(4, 6), | ||
buf.slice(6, 8), | ||
buf.slice(8, 16), | ||
]); | ||
} | ||
binToUuid(bin) { | ||
const buf = new Buffer(bin, 'hex'); | ||
return [ | ||
buf.toString('hex', 4, 8), | ||
buf.toString('hex', 2, 4), | ||
buf.toString('hex', 0, 2), | ||
buf.toString('hex', 8, 10), | ||
buf.toString('hex', 10, 16), | ||
].join('-'); | ||
binToUuid(bin, ordered = true) { | ||
const buf = Buffer.from(bin, 'hex'); | ||
return ordered | ||
? [ | ||
buf.toString('hex', 4, 8), | ||
buf.toString('hex', 2, 4), | ||
buf.toString('hex', 0, 2), | ||
buf.toString('hex', 8, 10), | ||
buf.toString('hex', 10, 16), | ||
].join('-') | ||
: [ | ||
buf.toString('hex', 0, 4), | ||
buf.toString('hex', 4, 6), | ||
buf.toString('hex', 6, 8), | ||
buf.toString('hex', 8, 10), | ||
buf.toString('hex', 10, 16), | ||
].join('-'); | ||
} | ||
@@ -38,0 +53,0 @@ } |
@@ -565,4 +565,5 @@ // Migrator | ||
if (!isEmpty(diff)) { | ||
const names = diff.map((d) => d.name); | ||
throw new Error( | ||
`The migration directory is corrupt, the following files are missing: ${diff.join( | ||
`The migration directory is corrupt, the following files are missing: ${names.join( | ||
', ' | ||
@@ -569,0 +570,0 @@ )}` |
@@ -121,10 +121,63 @@ // Builder | ||
// ------ | ||
isValidStatementArg(statement) { | ||
return ( | ||
typeof statement === 'function' || | ||
statement instanceof Builder || | ||
(statement && statement.isRawInstance) | ||
); | ||
} | ||
_validateWithArgs(alias, statementOrColumnList, nothingOrStatement, method) { | ||
const [query, columnList] = | ||
typeof nothingOrStatement === 'undefined' | ||
? [statementOrColumnList, undefined] | ||
: [nothingOrStatement, statementOrColumnList]; | ||
if (typeof alias !== 'string') { | ||
throw new Error(`${method}() first argument must be a string`); | ||
} | ||
if (this.isValidStatementArg(query) && typeof columnList === 'undefined') { | ||
// Validated as two-arg variant (alias, statement). | ||
return; | ||
} | ||
// Attempt to interpret as three-arg variant (alias, columnList, statement). | ||
const isNonEmptyNameList = | ||
Array.isArray(columnList) && | ||
columnList.length > 0 && | ||
columnList.every((it) => typeof it === 'string'); | ||
if (!isNonEmptyNameList) { | ||
throw new Error( | ||
`${method}() second argument must be a statement or non-empty column name list.` | ||
); | ||
} | ||
if (this.isValidStatementArg(query)) { | ||
return; | ||
} | ||
throw new Error( | ||
`${method}() third argument must be a function / QueryBuilder or a raw when its second argument is a column name list` | ||
); | ||
} | ||
with(alias, statementOrColumnList, nothingOrStatement) { | ||
validateWithArgs(alias, statementOrColumnList, nothingOrStatement, 'with'); | ||
this._validateWithArgs( | ||
alias, | ||
statementOrColumnList, | ||
nothingOrStatement, | ||
'with' | ||
); | ||
return this.withWrapped(alias, statementOrColumnList, nothingOrStatement); | ||
} | ||
withMaterialized(alias, statementOrColumnList, nothingOrStatement) { | ||
throw new Error('With materialized is not supported by this dialect'); | ||
} | ||
withNotMaterialized(alias, statementOrColumnList, nothingOrStatement) { | ||
throw new Error('With materialized is not supported by this dialect'); | ||
} | ||
// Helper for compiling any advanced `with` queries. | ||
withWrapped(alias, statementOrColumnList, nothingOrStatement) { | ||
withWrapped(alias, statementOrColumnList, nothingOrStatement, materialized) { | ||
const [query, columnList] = | ||
@@ -134,3 +187,3 @@ typeof nothingOrStatement === 'undefined' | ||
: [nothingOrStatement, statementOrColumnList]; | ||
this._statements.push({ | ||
const statement = { | ||
grouping: 'with', | ||
@@ -141,3 +194,7 @@ type: 'withWrapped', | ||
value: query, | ||
}); | ||
}; | ||
if (materialized !== undefined) { | ||
statement.materialized = materialized; | ||
} | ||
this._statements.push(statement); | ||
return this; | ||
@@ -150,3 +207,3 @@ } | ||
withRecursive(alias, statementOrColumnList, nothingOrStatement) { | ||
validateWithArgs( | ||
this._validateWithArgs( | ||
alias, | ||
@@ -1663,45 +1720,2 @@ statementOrColumnList, | ||
const isValidStatementArg = (statement) => | ||
typeof statement === 'function' || | ||
statement instanceof Builder || | ||
(statement && statement.isRawInstance); | ||
const validateWithArgs = function ( | ||
alias, | ||
statementOrColumnList, | ||
nothingOrStatement, | ||
method | ||
) { | ||
const [query, columnList] = | ||
typeof nothingOrStatement === 'undefined' | ||
? [statementOrColumnList, undefined] | ||
: [nothingOrStatement, statementOrColumnList]; | ||
if (typeof alias !== 'string') { | ||
throw new Error(`${method}() first argument must be a string`); | ||
} | ||
if (isValidStatementArg(query) && typeof columnList === 'undefined') { | ||
// Validated as two-arg variant (alias, statement). | ||
return; | ||
} | ||
// Attempt to interpret as three-arg variant (alias, columnList, statement). | ||
const isNonEmptyNameList = | ||
Array.isArray(columnList) && | ||
columnList.length > 0 && | ||
columnList.every((it) => typeof it === 'string'); | ||
if (!isNonEmptyNameList) { | ||
throw new Error( | ||
`${method}() second argument must be a statement or non-empty column name list.` | ||
); | ||
} | ||
if (isValidStatementArg(query)) { | ||
return; | ||
} | ||
throw new Error( | ||
`${method}() third argument must be a function / QueryBuilder or a raw when its second argument is a column name list` | ||
); | ||
}; | ||
Builder.prototype.select = Builder.prototype.columns; | ||
@@ -1708,0 +1722,0 @@ Builder.prototype.column = Builder.prototype.columns; |
@@ -152,2 +152,8 @@ // Query Compiler | ||
_onConflictClause(columns) { | ||
return columns instanceof Raw | ||
? this.formatter.wrap(columns) | ||
: `(${this.formatter.columnize(columns)})`; | ||
} | ||
_buildInsertValues(insertData) { | ||
@@ -1074,6 +1080,10 @@ let sql = ''; | ||
_jsonWrapValue(jsonValue) { | ||
if (this.builder._isJsonObject(jsonValue)) { | ||
return JSON.stringify(jsonValue); | ||
if (!this.builder._isJsonObject(jsonValue)) { | ||
try { | ||
return JSON.stringify(JSON.parse(jsonValue.replace(/\n|\t/g, ''))); | ||
} catch (e) { | ||
return jsonValue; | ||
} | ||
} | ||
return jsonValue; | ||
return JSON.stringify(jsonValue); | ||
} | ||
@@ -1175,2 +1185,8 @@ | ||
: ''; | ||
const materialized = | ||
statement.materialized === undefined | ||
? '' | ||
: statement.materialized | ||
? 'materialized ' | ||
: 'not materialized '; | ||
return ( | ||
@@ -1185,3 +1201,5 @@ (val && | ||
columnList + | ||
' as (' + | ||
' as ' + | ||
materialized + | ||
'(' + | ||
val + | ||
@@ -1332,3 +1350,3 @@ ')') || | ||
_groupOrder(item, type) { | ||
_basicGroupOrder(item, type) { | ||
const column = this._formatGroupsItemValue(item.value, item.nulls); | ||
@@ -1347,2 +1365,23 @@ const direction = | ||
_groupOrder(item, type) { | ||
return this._basicGroupOrder(item, type); | ||
} | ||
_groupOrderNulls(item, type) { | ||
const column = this._formatGroupsItemValue(item.value); | ||
const direction = | ||
type === 'order' && item.type !== 'orderByRaw' | ||
? ` ${direction_( | ||
item.direction, | ||
this.builder, | ||
this.client, | ||
this.bindingsHolder | ||
)}` | ||
: ''; | ||
if (item.nulls && !(item.value instanceof Raw)) { | ||
return `${column}${direction ? direction : ''} nulls ${item.nulls}`; | ||
} | ||
return column + direction; | ||
} | ||
// Compiles the `order by` statements. | ||
@@ -1349,0 +1388,0 @@ _groupsOrders(type) { |
@@ -113,4 +113,9 @@ const extend = require('lodash/extend'); | ||
// Set column method to alter (default is add). | ||
AlterMethods.alter = function () { | ||
AlterMethods.alter = function ({ | ||
alterNullable = true, | ||
alterType = true, | ||
} = {}) { | ||
this._method = 'alter'; | ||
this.alterNullable = alterNullable; | ||
this.alterType = alterType; | ||
@@ -117,0 +122,0 @@ return this; |
@@ -130,5 +130,5 @@ /* eslint max-len:0 */ | ||
')' + | ||
deferrable + | ||
onUpdate + | ||
onDelete | ||
onDelete + | ||
deferrable | ||
); | ||
@@ -148,5 +148,5 @@ } else { | ||
')' + | ||
deferrable + | ||
onUpdate + | ||
onDelete | ||
onDelete + | ||
deferrable | ||
); | ||
@@ -153,0 +153,0 @@ } |
{ | ||
"name": "knex", | ||
"version": "1.0.1", | ||
"version": "1.0.2", | ||
"description": "A batteries-included SQL query & schema builder for PostgresSQL, MySQL, CockroachDB, MSSQL and SQLite3", | ||
@@ -87,5 +87,2 @@ "main": "knex", | ||
}, | ||
"sqlite3": { | ||
"optional": true | ||
}, | ||
"@vscode/sqlite3": { | ||
@@ -105,6 +102,6 @@ "optional": true | ||
"devDependencies": { | ||
"@types/node": "^16.11.19", | ||
"@types/node": "^16.11.22", | ||
"@vscode/sqlite3": "^5.0.7", | ||
"better-sqlite3": "^7.4.6", | ||
"chai": "^4.3.4", | ||
"better-sqlite3": "^7.5.0", | ||
"chai": "^4.3.6", | ||
"chai-as-promised": "^7.1.1", | ||
@@ -116,5 +113,5 @@ "chai-subset-in-order": "^3.1.0", | ||
"dtslint": "4.2.1", | ||
"eslint": "^8.1.0", | ||
"eslint": "^8.8.0", | ||
"eslint-config-prettier": "^8.3.0", | ||
"eslint-plugin-import": "^2.25.2", | ||
"eslint-plugin-import": "^2.25.4", | ||
"husky": "^4.3.8", | ||
@@ -124,3 +121,3 @@ "jake": "^8.1.1", | ||
"lint-staged": "^11.1.2", | ||
"mocha": "^9.1.4", | ||
"mocha": "^9.2.0", | ||
"mock-fs": "^5.1.2", | ||
@@ -135,12 +132,12 @@ "mysql": "^2.18.1", | ||
"rimraf": "^3.0.2", | ||
"sinon": "^12.0.1", | ||
"sinon": "^13.0.1", | ||
"sinon-chai": "^3.7.0", | ||
"source-map-support": "^0.5.21", | ||
"tap-spec": "^5.0.0", | ||
"tape": "^5.4.0", | ||
"tedious": "^12.2.0", | ||
"tape": "^5.5.0", | ||
"tedious": "^12.3.0", | ||
"toxiproxy-node-client": "^2.0.6", | ||
"ts-node": "^10.4.0", | ||
"tsd": "^0.19.1", | ||
"typescript": "4.5.4" | ||
"typescript": "4.5.5" | ||
}, | ||
@@ -147,0 +144,0 @@ "buildDependencies": [ |
@@ -6,3 +6,3 @@ ## Upgrading to new knex.js versions | ||
* Node.js older than 12 is no longer supported, make sure to update your environment; | ||
* If you are using `sqlite3` driver, please replace it with `@vscode/sqlite3`; | ||
* If you are using `sqlite3` driver dependency, please replace it with `@vscode/sqlite3` in your `package.json`; | ||
* `RETURNING` operations now always return an object with column names; | ||
@@ -9,0 +9,0 @@ * Migrator now returns list of migrations as objects. |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
829600
182
22123