1
0
Fork 0
mirror of synced 2024-09-30 17:18:14 +13:00

First version of schema generation for ms-sql, able to retrieve basic tables and rows.

This commit is contained in:
mike12345567 2021-10-27 18:36:27 +01:00
parent ac27ba4c81
commit 51dcdf0697

View file

@ -6,10 +6,18 @@ import {
SqlQuery,
} from "../definitions/datasource"
import { getSqlQuery } from "./utils"
import { DatasourcePlus } from "./base/datasourcePlus"
import { Table, TableSchema } from "../definitions/common";
module MSSQLModule {
const sqlServer = require("mssql")
const Sql = require("./base/sql")
const { FieldTypes } = require("../constants")
const {
buildExternalTableId,
convertType,
finaliseExternalTables,
} = require("./utils")
interface MSSQLConfig {
user: string
@ -22,6 +30,7 @@ module MSSQLModule {
const SCHEMA: Integration = {
docs: "https://github.com/tediousjs/node-mssql",
plus: true,
description:
"Microsoft SQL Server is a relational database management system developed by Microsoft. ",
friendlyName: "MS SQL Server",
@ -69,18 +78,66 @@ module MSSQLModule {
},
}
// TODO: need to update this
const TYPE_MAP = {
text: FieldTypes.LONGFORM,
blob: FieldTypes.LONGFORM,
enum: FieldTypes.STRING,
varchar: FieldTypes.STRING,
float: FieldTypes.NUMBER,
int: FieldTypes.NUMBER,
numeric: FieldTypes.NUMBER,
bigint: FieldTypes.NUMBER,
mediumint: FieldTypes.NUMBER,
decimal: FieldTypes.NUMBER,
dec: FieldTypes.NUMBER,
double: FieldTypes.NUMBER,
real: FieldTypes.NUMBER,
fixed: FieldTypes.NUMBER,
smallint: FieldTypes.NUMBER,
timestamp: FieldTypes.DATETIME,
date: FieldTypes.DATETIME,
datetime: FieldTypes.DATETIME,
time: FieldTypes.DATETIME,
tinyint: FieldTypes.BOOLEAN,
json: DatasourceFieldTypes.JSON,
}
async function internalQuery(client: any, query: SqlQuery) {
try {
return await client.query(query.sql, query.bindings || {})
if (Array.isArray(query.bindings)) {
let count = 0
for (let binding of query.bindings) {
client.input(`p${count++}`, binding)
}
}
return await client.query(query.sql)
} catch (err) {
// @ts-ignore
throw new Error(err)
}
}
class SqlServerIntegration extends Sql {
class SqlServerIntegration extends Sql implements DatasourcePlus {
private readonly config: MSSQLConfig
static pool: any
public tables: Record<string, Table> = {}
public schemaErrors: Record<string, string> = {}
MASTER_TABLES = [
"spt_fallback_db",
"spt_fallback_dev",
"spt_fallback_usg",
"spt_monitor",
"MSreplication_options"
]
TABLES_SQL = "SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE='BASE TABLE'"
getDefinitionSQL(tableName: string) {
return `select *
from INFORMATION_SCHEMA.COLUMNS
where TABLE_NAME='${tableName}'`
}
constructor(config: MSSQLConfig) {
super("mssql")
@ -89,6 +146,7 @@ module MSSQLModule {
...this.config,
options: {
encrypt: this.config.encrypt,
enableArithAbort: true,
},
}
delete clientCfg.encrypt
@ -107,6 +165,46 @@ module MSSQLModule {
}
}
/**
* Fetches the tables from the sql server database and assigns them to the datasource.
* @param {*} datasourceId - datasourceId to fetch
* @param entities - the tables that are to be built
*/
async buildSchema(datasourceId: string, entities: Record<string, Table>) {
await this.connect()
let tableNames = await internalQuery(this.client, getSqlQuery(this.TABLES_SQL))
if (tableNames == null || !Array.isArray(tableNames.recordset)) {
throw "Unable to get list of tables in database"
}
tableNames = tableNames.recordset.map((record: any) => record.TABLE_NAME).filter((name: string) => this.MASTER_TABLES.indexOf(name) === -1)
const tables: Record<string, Table> = {}
for (let tableName of tableNames) {
const definition = await internalQuery(this.client, getSqlQuery(this.getDefinitionSQL(tableName)))
let schema: TableSchema = {}
for (let def of definition.recordset) {
const name = def.COLUMN_NAME
if (typeof name !== "string") {
continue
}
const type: string = convertType(def.DATA_TYPE, TYPE_MAP)
const identity = false
schema[name] = {
autocolumn: identity,
name: name,
type,
}
}
tables[tableName] = {
_id: buildExternalTableId(datasourceId, tableName),
primary: ["id"],
name: tableName,
schema,
}
}
this.tables = tables
}
async read(query: SqlQuery | string) {
await this.connect()
const response = await internalQuery(this.client, getSqlQuery(query))
@ -132,6 +230,7 @@ module MSSQLModule {
}
async query(json: QueryJson) {
await this.connect()
const operation = this._operation(json).toLowerCase()
const input = this._query(json)
const response = await internalQuery(this.client, input)