Simplifying internal client structure

This commit is contained in:
Tim Griesser 2016-09-13 08:15:58 -04:00
parent 53c5984a3b
commit f5bad1ae54
14 changed files with 155 additions and 114 deletions

View File

@ -56,6 +56,7 @@
},
"scripts": {
"build": "npm run babel",
"debug_test": "node-debug _mocha -t 0 test/index.js",
"babel": "rm -rf ./lib && babel src --out-dir lib --copy-files",
"coveralls": "cat ./test/coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js",
"dev": "rm -rf ./lib && babel -w src --out-dir lib --copy-files",

View File

@ -8,6 +8,7 @@ import Client from '../../client';
import Promise from 'bluebird';
import * as helpers from '../../helpers';
import Formatter from '../../formatter'
import Transaction from './transaction';
import QueryCompiler from './query/compiler';
import SchemaCompiler from './schema/compiler';
@ -41,17 +42,29 @@ assign(Client_MSSQL.prototype, {
return require('mssql');
},
formatter() {
return new MSSQL_Formatter(this)
},
transaction() {
return new Transaction(this, ...arguments)
},
QueryCompiler,
queryCompiler() {
return new QueryCompiler(this, ...arguments)
},
SchemaCompiler,
schemaCompiler() {
return new SchemaCompiler(this, ...arguments)
},
TableCompiler,
tableCompiler() {
return new TableCompiler(this, ...arguments)
},
ColumnCompiler,
columnCompiler() {
return new ColumnCompiler(this, ...arguments)
},
wrapIdentifier(value) {
return (value !== '*' ? `[${value.replace(/\[/g, '\[')}]` : '*')
@ -201,6 +214,21 @@ assign(Client_MSSQL.prototype, {
})
class MSSQL_Formatter extends Formatter {
// Accepts a string or array of columns to wrap as appropriate.
columnizeWithPrefix(prefix, target) {
const columns = typeof target === 'string' ? [target] : target
let str = '', i = -1;
while (++i < columns.length) {
if (i > 0) str += ', '
str += prefix + this.wrap(columns[i])
}
return str
}
}
// MSSQL Specific error handler
function connectionErrorHandler(client, connection, err) {
if (connection && err && err.fatal) {

View File

@ -129,11 +129,11 @@ assign(QueryCompiler_MSSQL.prototype, {
case 'update':
case 'insert':
return value
? `output inserted.${this.formatter.columnize(value)}`
? `output ${this.formatter.columnizeWithPrefix('inserted.', value)}`
: '';
case 'del':
return value
? `output deleted.${this.formatter.columnize(value)}`
? `output ${this.formatter.columnizeWithPrefix('deleted.', value)}`
: '';
case 'rowcount':
return value

View File

@ -34,13 +34,21 @@ assign(Client_MySQL.prototype, {
return require('mysql')
},
QueryCompiler,
queryCompiler() {
return new QueryCompiler(this, ...arguments)
},
SchemaCompiler,
schemaCompiler() {
return new SchemaCompiler(this, ...arguments)
},
TableCompiler,
tableCompiler() {
return new TableCompiler(this, ...arguments)
},
ColumnCompiler,
columnCompiler() {
return new ColumnCompiler(this, ...arguments)
},
transaction() {
return new Transaction(this, ...arguments)

View File

@ -0,0 +1,21 @@
import Formatter from '../../formatter'
import {ReturningHelper} from './utils'
export default class Oracle_Formatter extends Formatter {
alias(first, second) {
return first + ' ' + second;
}
parameter(value, notSetValue) {
// Returning helper uses always ROWID as string
if (value instanceof ReturningHelper && this.client.driver) {
value = new this.client.driver.OutParam(this.client.driver.OCCISTRING)
}
else if (typeof value === 'boolean') {
value = value ? 1 : 0
}
return super.parameter(value, notSetValue)
}
}

View File

@ -8,7 +8,7 @@ import Client from '../../client';
import Promise from 'bluebird';
import * as helpers from '../../helpers';
import {bufferToString} from '../../query/string';
import Formatter from '../../formatter';
import Formatter from './formatter';
import Transaction from './transaction';
import QueryCompiler from './query/compiler';
@ -42,18 +42,28 @@ assign(Client_Oracle.prototype, {
},
formatter() {
return new Oracle_Formatter(this)
return new Formatter(this)
},
QueryCompiler,
queryCompiler() {
return new QueryCompiler(this, ...arguments)
},
SchemaCompiler,
schemaCompiler() {
return new SchemaCompiler(this, ...arguments)
},
ColumnBuilder,
columnBuilder() {
return new ColumnBuilder(this, ...arguments)
},
ColumnCompiler,
columnCompiler() {
return new ColumnCompiler(this, ...arguments)
},
TableCompiler,
tableCompiler() {
return new TableCompiler(this, ...arguments)
},
prepBindings(bindings) {
return map(bindings, (value) => {
@ -174,22 +184,3 @@ assign(Client_Oracle.prototype, {
}
})
export class Oracle_Formatter extends Formatter {
alias(first, second) {
return first + ' ' + second;
}
parameter(value, notSetValue) {
// Returning helper uses always ROWID as string
if (value instanceof ReturningHelper && this.client.driver) {
value = new this.client.driver.OutParam(this.client.driver.OCCISTRING)
}
else if (typeof value === 'boolean') {
value = value ? 1 : 0
}
return super.parameter(value, notSetValue)
}
}

View File

@ -11,10 +11,8 @@ const Promise = require('bluebird');
const stream = require('stream');
const helpers = require('../../helpers');
const Transaction = require('./transaction');
const Client_Oracle = require('../oracle');
const Oracle_Formatter = require('../oracle/formatter');
const BlobHelper = require('./utils').BlobHelper;
import Client_Oracle, {Oracle_Formatter} from '../oracle';
function Client_Oracledb() {
Client_Oracle.apply(this, arguments);
@ -33,12 +31,18 @@ Client_Oracledb.prototype._driver = function() {
return oracledb;
};
Client_Oracledb.prototype.QueryCompiler = QueryCompiler;
Client_Oracledb.prototype.ColumnCompiler = ColumnCompiler;
Client_Oracledb.prototype.queryCompiler = function() {
return new QueryCompiler(this, ...arguments)
}
Client_Oracledb.prototype.columnCompiler = function() {
return new ColumnCompiler(this, ...arguments)
}
Client_Oracledb.prototype.formatter = function() {
return new Oracledb_Formatter(this)
};
Client_Oracledb.prototype.Transaction = Transaction;
}
Client_Oracledb.prototype.transaction = function() {
return new Transaction(this, ...arguments)
}
Client_Oracledb.prototype.prepBindings = function(bindings) {
const self = this;

View File

@ -26,13 +26,21 @@ inherits(Client_PG, Client)
assign(Client_PG.prototype, {
QueryCompiler,
queryCompiler() {
return new QueryCompiler(this, ...arguments)
},
ColumnCompiler,
columnCompiler() {
return new ColumnCompiler(this, ...arguments)
},
SchemaCompiler,
schemaCompiler() {
return new SchemaCompiler(this, ...arguments)
},
TableCompiler,
tableCompiler() {
return new TableCompiler(this, ...arguments)
},
dialect: 'postgresql',

View File

@ -37,13 +37,21 @@ assign(Client_SQLite3.prototype, {
return require('sqlite3')
},
SchemaCompiler,
schemaCompiler() {
return new SchemaCompiler(this, ...arguments)
},
QueryCompiler,
queryCompiler() {
return new QueryCompiler(this, ...arguments)
},
ColumnCompiler,
columnCompiler() {
return new ColumnCompiler(this, ...arguments)
},
TableCompiler,
tableCompiler() {
return new TableCompiler(this, ...arguments)
},
ddl(compiler, pragma, connection) {
return new SQLite3_DDL(this, compiler, pragma, connection)

View File

@ -3,7 +3,6 @@ import Raw from './raw';
import { warn } from './helpers';
import Client from './client';
import makeClient from './util/make-client';
import makeKnex from './util/make-knex';
import parseConnection from './util/parse-connection';
@ -24,12 +23,12 @@ export default function Knex(config) {
}
let Dialect;
if (arguments.length === 0 || (!config.client && !config.dialect)) {
Dialect = makeClient(Client)
Dialect = Client
} else if (typeof config.client === 'function' && config.client.prototype instanceof Client) {
Dialect = makeClient(config.client)
Dialect = config.client
} else {
const clientName = config.client || config.dialect
Dialect = makeClient(require(`./dialects/${aliases[clientName] || clientName}/index.js`))
Dialect = require(`./dialects/${aliases[clientName] || clientName}/index.js`)
}
if (typeof config.connection === 'string') {
config = assign({}, config, {connection: parseConnection(config.connection).connection})

View File

@ -162,11 +162,12 @@ function makeTransactor(trx, connection, trxClient) {
const transactor = makeKnex(trxClient);
transactor.transaction = (container, options) =>
new trxClient.Transaction(trxClient, container, options, trx);
transactor.savepoint = (container, options) =>
transactor.transaction(container, options);
transactor.transaction = function(container, options) {
return trxClient.transaction(container, options, trx);
}
transactor.savepoint = function(container, options) {
return transactor.transaction(container, options);
}
if (trx.client.transacting) {
transactor.commit = value => trx.release(connection, value)

View File

@ -1,8 +1,5 @@
import inherits from 'inherits';
import { assign } from 'lodash'
// Ensure the client has fresh objects so we can tack onto
// the prototypes without mutating them globally.
export default function makeClient(ParentClient) {
@ -16,49 +13,5 @@ export default function makeClient(ParentClient) {
}
inherits(Client, ParentClient)
function QueryBuilder(client) {
QueryBuilder.super_.call(this, client)
}
inherits(QueryBuilder, ParentClient.prototype.QueryBuilder)
function SchemaBuilder(client) {
SchemaBuilder.super_.call(this, client)
}
inherits(SchemaBuilder, ParentClient.prototype.SchemaBuilder)
function SchemaCompiler(client, builder) {
SchemaCompiler.super_.call(this, client, builder)
}
inherits(SchemaCompiler, ParentClient.prototype.SchemaCompiler)
function TableBuilder(client, method, tableName, fn) {
TableBuilder.super_.call(this, client, method, tableName, fn)
}
inherits(TableBuilder, ParentClient.prototype.TableBuilder)
function TableCompiler(client, tableBuilder) {
TableCompiler.super_.call(this, client, tableBuilder)
}
inherits(TableCompiler, ParentClient.prototype.TableCompiler)
function ColumnBuilder(client, tableBuilder, type, args) {
ColumnBuilder.super_.call(this, client, tableBuilder, type, args)
}
inherits(ColumnBuilder, ParentClient.prototype.ColumnBuilder)
function ColumnCompiler(client, tableCompiler, columnBuilder) {
ColumnCompiler.super_.call(this, client, tableCompiler, columnBuilder)
}
inherits(ColumnCompiler, ParentClient.prototype.ColumnCompiler)
assign(Client.prototype, {
SchemaBuilder,
SchemaCompiler,
TableBuilder,
TableCompiler,
ColumnBuilder,
ColumnCompiler
})
return Client
}

View File

@ -247,7 +247,6 @@ module.exports = function(knex) {
});
it('should allow for nested transactions', function() {
return knex.transaction(function(trx) {
return trx.select('*').from('accounts').then(function() {
return trx.transaction(function() {

View File

@ -78,12 +78,32 @@ module.exports = function(knex) {
});
}
client.Raw.prototype.testSql =
client.QueryBuilder.prototype.testSql =
client.SchemaBuilder.prototype.testSql = function Logger$testSql(handler) {
handler(testSqlTester.bind(null, this));
return this;
};
function makeTestSQL(builder) {
const tester = testSqlTester.bind(null, builder)
return function(handler) {
handler(tester)
return this
}
}
const originalRaw = client.raw
const originalQueryBuilder = client.queryBuilder
const originalSchemaBuilder = client.schemaBuilder
client.raw = function() {
const raw = originalRaw.apply(this, arguments)
raw.testSql = makeTestSQL(raw)
return raw
}
client.queryBuilder = function() {
const qb = originalQueryBuilder.apply(this, arguments)
qb.testSql = makeTestSQL(qb)
return qb
}
client.schemaBuilder = function() {
const sb = originalSchemaBuilder.apply(this, arguments)
sb.testSql = makeTestSQL(sb)
return sb
}
return knex;
}