Adding the ability to support schemas in MS-SQL.
This commit is contained in:
parent
e9ff42bf76
commit
a4ed8fe5e8
|
@ -1,5 +1,10 @@
|
|||
USE master;
|
||||
|
||||
IF NOT EXISTS(SELECT 1 FROM sys.schemas WHERE name = 'Chains')
|
||||
BEGIN
|
||||
EXEC sys.sp_executesql N'CREATE SCHEMA Chains;'
|
||||
END
|
||||
|
||||
IF OBJECT_ID ('dbo.products', 'U') IS NOT NULL
|
||||
DROP TABLE products;
|
||||
GO
|
||||
|
@ -61,3 +66,15 @@ VALUES ('Bob', '30'),
|
|||
('Bobert', '99'),
|
||||
('Jan', '22'),
|
||||
('Megan', '11');
|
||||
|
||||
|
||||
IF OBJECT_ID ('Chains.sizes', 'U') IS NOT NULL
|
||||
DROP TABLE Chains.sizes;
|
||||
GO
|
||||
CREATE TABLE Chains.sizes
|
||||
(
|
||||
sizeid int IDENTITY(1, 1),
|
||||
name varchar(30),
|
||||
CONSTRAINT pk_size PRIMARY KEY NONCLUSTERED (sizeid)
|
||||
);
|
||||
|
||||
|
|
|
@ -153,6 +153,7 @@ export interface QueryJson {
|
|||
datasourceId: string
|
||||
entityId: string
|
||||
operation: Operation
|
||||
schema?: string
|
||||
}
|
||||
resource: {
|
||||
fields: string[]
|
||||
|
|
|
@ -249,6 +249,9 @@ class InternalBuilder {
|
|||
create(knex: Knex, json: QueryJson, opts: QueryOptions): KnexQuery {
|
||||
const { endpoint, body } = json
|
||||
let query: KnexQuery = knex(endpoint.entityId)
|
||||
if (endpoint.schema) {
|
||||
query = query.withSchema(endpoint.schema)
|
||||
}
|
||||
const parsedBody = parseBody(body)
|
||||
// make sure no null values in body for creation
|
||||
for (let [key, value] of Object.entries(parsedBody)) {
|
||||
|
@ -267,6 +270,9 @@ class InternalBuilder {
|
|||
bulkCreate(knex: Knex, json: QueryJson): KnexQuery {
|
||||
const { endpoint, body } = json
|
||||
let query: KnexQuery = knex(endpoint.entityId)
|
||||
if (endpoint.schema) {
|
||||
query = query.withSchema(endpoint.schema)
|
||||
}
|
||||
if (!Array.isArray(body)) {
|
||||
return query
|
||||
}
|
||||
|
@ -275,7 +281,7 @@ class InternalBuilder {
|
|||
}
|
||||
|
||||
read(knex: Knex, json: QueryJson, limit: number): KnexQuery {
|
||||
let { endpoint, resource, filters, sort, paginate, relationships } = json
|
||||
let { endpoint, resource, filters, paginate, relationships } = json
|
||||
const tableName = endpoint.entityId
|
||||
// select all if not specified
|
||||
if (!resource) {
|
||||
|
@ -302,6 +308,9 @@ class InternalBuilder {
|
|||
}
|
||||
// start building the query
|
||||
let query: KnexQuery = knex(tableName).limit(foundLimit)
|
||||
if (endpoint.schema) {
|
||||
query = query.withSchema(endpoint.schema)
|
||||
}
|
||||
if (foundOffset) {
|
||||
query = query.offset(foundOffset)
|
||||
}
|
||||
|
@ -331,6 +340,9 @@ class InternalBuilder {
|
|||
update(knex: Knex, json: QueryJson, opts: QueryOptions): KnexQuery {
|
||||
const { endpoint, body, filters } = json
|
||||
let query: KnexQuery = knex(endpoint.entityId)
|
||||
if (endpoint.schema) {
|
||||
query = query.withSchema(endpoint.schema)
|
||||
}
|
||||
const parsedBody = parseBody(body)
|
||||
query = this.addFilters(query, filters, { tableName: endpoint.entityId })
|
||||
// mysql can't use returning
|
||||
|
@ -344,6 +356,9 @@ class InternalBuilder {
|
|||
delete(knex: Knex, json: QueryJson, opts: QueryOptions): KnexQuery {
|
||||
const { endpoint, filters } = json
|
||||
let query: KnexQuery = knex(endpoint.entityId)
|
||||
if (endpoint.schema) {
|
||||
query = query.withSchema(endpoint.schema)
|
||||
}
|
||||
query = this.addFilters(query, filters, { tableName: endpoint.entityId })
|
||||
// mysql can't use returning
|
||||
if (opts.disableReturning) {
|
||||
|
|
|
@ -19,6 +19,7 @@ import { Table, TableSchema } from "../definitions/common"
|
|||
module MSSQLModule {
|
||||
const sqlServer = require("mssql")
|
||||
const Sql = require("./base/sql")
|
||||
const DEFAULT_SCHEMA = "dbo"
|
||||
|
||||
interface MSSQLConfig {
|
||||
user: string
|
||||
|
@ -26,9 +27,17 @@ module MSSQLModule {
|
|||
server: string
|
||||
port: number
|
||||
database: string
|
||||
schema: string
|
||||
encrypt?: boolean
|
||||
}
|
||||
|
||||
interface TablesResponse {
|
||||
TABLE_CATALOG: string
|
||||
TABLE_SCHEMA: string
|
||||
TABLE_NAME: string
|
||||
TABLE_TYPE: string
|
||||
}
|
||||
|
||||
const SCHEMA: Integration = {
|
||||
docs: "https://github.com/tediousjs/node-mssql",
|
||||
plus: true,
|
||||
|
@ -58,6 +67,10 @@ module MSSQLModule {
|
|||
type: DatasourceFieldTypes.STRING,
|
||||
default: "root",
|
||||
},
|
||||
schema: {
|
||||
type: DatasourceFieldTypes.STRING,
|
||||
default: DEFAULT_SCHEMA,
|
||||
},
|
||||
encrypt: {
|
||||
type: DatasourceFieldTypes.BOOLEAN,
|
||||
default: true,
|
||||
|
@ -96,11 +109,41 @@ module MSSQLModule {
|
|||
TABLES_SQL =
|
||||
"SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE='BASE TABLE'"
|
||||
|
||||
constructor(config: MSSQLConfig) {
|
||||
super(SqlClients.MS_SQL)
|
||||
this.config = config
|
||||
const clientCfg = {
|
||||
...this.config,
|
||||
options: {
|
||||
encrypt: this.config.encrypt,
|
||||
enableArithAbort: true,
|
||||
},
|
||||
}
|
||||
delete clientCfg.encrypt
|
||||
if (!this.pool) {
|
||||
this.pool = new sqlServer.ConnectionPool(clientCfg)
|
||||
}
|
||||
}
|
||||
|
||||
getBindingIdentifier(): string {
|
||||
return `(@p${this.index++})`
|
||||
}
|
||||
|
||||
async connect() {
|
||||
try {
|
||||
this.client = await this.pool.connect()
|
||||
} catch (err) {
|
||||
// @ts-ignore
|
||||
throw new Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
async internalQuery(
|
||||
query: SqlQuery,
|
||||
operation: string | undefined = undefined
|
||||
) {
|
||||
const client = this.client
|
||||
const schema = this.config.schema
|
||||
const request = client.request()
|
||||
this.index = 0
|
||||
try {
|
||||
|
@ -151,35 +194,6 @@ module MSSQLModule {
|
|||
WHERE TABLE_NAME='${tableName}'`
|
||||
}
|
||||
|
||||
constructor(config: MSSQLConfig) {
|
||||
super(SqlClients.MS_SQL)
|
||||
this.config = config
|
||||
const clientCfg = {
|
||||
...this.config,
|
||||
options: {
|
||||
encrypt: this.config.encrypt,
|
||||
enableArithAbort: true,
|
||||
},
|
||||
}
|
||||
delete clientCfg.encrypt
|
||||
if (!this.pool) {
|
||||
this.pool = new sqlServer.ConnectionPool(clientCfg)
|
||||
}
|
||||
}
|
||||
|
||||
getBindingIdentifier(): string {
|
||||
return `(@p${this.index++})`
|
||||
}
|
||||
|
||||
async connect() {
|
||||
try {
|
||||
this.client = await this.pool.connect()
|
||||
} catch (err) {
|
||||
// @ts-ignore
|
||||
throw new Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
async runSQL(sql: string) {
|
||||
return (await this.internalQuery(getSqlQuery(sql))).recordset
|
||||
}
|
||||
|
@ -191,11 +205,14 @@ module MSSQLModule {
|
|||
*/
|
||||
async buildSchema(datasourceId: string, entities: Record<string, Table>) {
|
||||
await this.connect()
|
||||
let tableNames = await this.runSQL(this.TABLES_SQL)
|
||||
if (tableNames == null || !Array.isArray(tableNames)) {
|
||||
let tableInfo: TablesResponse[] = await this.runSQL(this.TABLES_SQL)
|
||||
if (tableInfo == null || !Array.isArray(tableInfo)) {
|
||||
throw "Unable to get list of tables in database"
|
||||
}
|
||||
tableNames = tableNames
|
||||
|
||||
const schema = this.config.schema || DEFAULT_SCHEMA
|
||||
const tableNames = tableInfo
|
||||
.filter((record: any) => record.TABLE_SCHEMA === schema)
|
||||
.map((record: any) => record.TABLE_NAME)
|
||||
.filter((name: string) => this.MASTER_TABLES.indexOf(name) === -1)
|
||||
|
||||
|
@ -267,7 +284,11 @@ module MSSQLModule {
|
|||
}
|
||||
|
||||
async query(json: QueryJson) {
|
||||
const schema = this.config.schema
|
||||
await this.connect()
|
||||
if (schema && schema !== DEFAULT_SCHEMA && json?.endpoint) {
|
||||
json.endpoint.schema = schema
|
||||
}
|
||||
const operation = this._operation(json)
|
||||
const queryFn = (query: any, op: string) => this.internalQuery(query, op)
|
||||
const processFn = (result: any) =>
|
||||
|
|
Loading…
Reference in New Issue