@quillsql/node 0.3.7 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assets/pgtypes.js +2785 -0
- package/dist/db/BigQuery.js +201 -0
- package/dist/db/{CachedPools.js → CachedConnection.js} +11 -23
- package/dist/db/DatabaseHelper.js +187 -0
- package/dist/db/Mysql.js +192 -0
- package/dist/db/Postgres.js +161 -0
- package/dist/db/Snowflake.js +189 -0
- package/dist/index.js +80 -24
- package/dist/index.uspec.js +3 -2
- package/dist/models/Client.js +2 -0
- package/dist/utils/RunQueryProcesses.js +3 -18
- package/dist/utils/schemaConversion.js +15 -0
- package/dist/utils/textProcessing.js +17 -0
- package/examples/node-server/app.ts +40 -9
- package/package.json +6 -2
- package/src/assets/pgtypes.ts +2782 -0
- package/src/db/BigQuery.ts +213 -0
- package/src/db/{CachedPools.ts → CachedConnection.ts} +25 -21
- package/src/db/DatabaseHelper.ts +352 -0
- package/src/db/Mysql.ts +216 -0
- package/src/db/Postgres.ts +187 -0
- package/src/db/Snowflake.ts +203 -0
- package/src/index.ts +136 -34
- package/src/index.uspec.ts +9 -2
- package/src/models/Client.ts +29 -0
- package/src/models/Quill.ts +10 -6
- package/src/utils/RunQueryProcesses.ts +3 -26
- package/src/utils/schemaConversion.ts +11 -0
- package/src/utils/textProcessing.ts +13 -0
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.formatPostgresConfig = exports.getSchemaColumnInfoPostgress = exports.getForeignKeysPostgres = exports.getColumnsByTablePostgres = exports.getTablesBySchemaPostgres = exports.getSchemasPostgres = exports.runQueryPostgres = exports.disconnectFromPostgres = exports.connectToPostgres = void 0;
|
|
13
|
+
const pg_1 = require("pg");
|
|
14
|
+
const textProcessing_1 = require("../utils/textProcessing");
|
|
15
|
+
const pgtypes_1 = require("../assets/pgtypes");
|
|
16
|
+
function connectToPostgres(config) {
|
|
17
|
+
return new pg_1.Pool(config);
|
|
18
|
+
}
|
|
19
|
+
exports.connectToPostgres = connectToPostgres;
|
|
20
|
+
function disconnectFromPostgres(pool) {
|
|
21
|
+
pool.end();
|
|
22
|
+
}
|
|
23
|
+
exports.disconnectFromPostgres = disconnectFromPostgres;
|
|
24
|
+
function runQueryPostgres(sql, pool) {
|
|
25
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
26
|
+
const results = yield pool.query(sql);
|
|
27
|
+
return {
|
|
28
|
+
fields: results.fields.map((field) => ({
|
|
29
|
+
name: field.name,
|
|
30
|
+
dataTypeID: field.dataTypeID,
|
|
31
|
+
})),
|
|
32
|
+
rows: results.rows,
|
|
33
|
+
};
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
exports.runQueryPostgres = runQueryPostgres;
|
|
37
|
+
function getSchemasPostgres(pool) {
|
|
38
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
39
|
+
const sql = `SELECT schema_name FROM information_schema.schemata
|
|
40
|
+
WHERE schema_name NOT LIKE 'pg_%' AND schema_name != 'information_schema';`;
|
|
41
|
+
const results = yield runQueryPostgres(sql, pool);
|
|
42
|
+
return results.rows.map((row) => row.schema_name);
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
exports.getSchemasPostgres = getSchemasPostgres;
|
|
46
|
+
function getTablesBySchemaPostgres(pool, schemaNames) {
|
|
47
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
48
|
+
const allColumns = yield Promise.all(schemaNames.map((schema) => __awaiter(this, void 0, void 0, function* () {
|
|
49
|
+
const sql = `SELECT table_name, table_schema FROM information_schema.tables WHERE table_schema = '${schema}'`;
|
|
50
|
+
const results = yield runQueryPostgres(sql, pool);
|
|
51
|
+
return results.rows.map((row) => {
|
|
52
|
+
return { tableName: row.table_name, schemaName: row.table_schema };
|
|
53
|
+
});
|
|
54
|
+
})));
|
|
55
|
+
return allColumns.flat();
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
exports.getTablesBySchemaPostgres = getTablesBySchemaPostgres;
|
|
59
|
+
function getColumnsByTablePostgres(pool, schemaName, tableName) {
|
|
60
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
61
|
+
const sql = `SELECT column_name FROM information_schema.columns WHERE table_schema = '${schemaName}' and table_name = '${tableName}'`;
|
|
62
|
+
const results = yield runQueryPostgres(sql, pool);
|
|
63
|
+
return results.rows.map((row) => row.column_name);
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
exports.getColumnsByTablePostgres = getColumnsByTablePostgres;
|
|
67
|
+
function getForeignKeysPostgres(pool, schemaName, tableName, primaryKey) {
|
|
68
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
69
|
+
const depluralizedTableName = (0, textProcessing_1.depluralize)(tableName);
|
|
70
|
+
let sql = `SELECT column_name FROM information_schema.columns
|
|
71
|
+
WHERE table_schema = '${schemaName}'
|
|
72
|
+
and table_name != '${tableName}'
|
|
73
|
+
and (column_name = '${primaryKey}'
|
|
74
|
+
or column_name = '${depluralizedTableName}_${primaryKey}'
|
|
75
|
+
or column_name = '${depluralizedTableName}${(0, textProcessing_1.capitalize)(primaryKey)}')`;
|
|
76
|
+
const results = yield runQueryPostgres(sql, pool);
|
|
77
|
+
let foreignKeysString = results.rows.map((key) => {
|
|
78
|
+
return key.column_name;
|
|
79
|
+
});
|
|
80
|
+
foreignKeysString = foreignKeysString.filter((key) => key !== "id" && key !== "_id_");
|
|
81
|
+
foreignKeysString = [...new Set(foreignKeysString)];
|
|
82
|
+
if (foreignKeysString.length === 0) {
|
|
83
|
+
sql = `SELECT column_name FROM information_schema.columns
|
|
84
|
+
WHERE table_schema = '${schemaName}'
|
|
85
|
+
and table_name != '${tableName}'
|
|
86
|
+
and (column_name like '${tableName}%'
|
|
87
|
+
or column_name like '%\\_id'
|
|
88
|
+
or column_name like '%Id'
|
|
89
|
+
or column_name like '%\\_${primaryKey}'
|
|
90
|
+
or column_name like '%${(0, textProcessing_1.capitalize)(primaryKey)}')`;
|
|
91
|
+
const results = yield runQueryPostgres(sql, pool);
|
|
92
|
+
foreignKeysString = results.rows.map((key) => {
|
|
93
|
+
return key.column_name;
|
|
94
|
+
});
|
|
95
|
+
foreignKeysString = [...new Set(foreignKeysString)];
|
|
96
|
+
}
|
|
97
|
+
return foreignKeysString;
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
exports.getForeignKeysPostgres = getForeignKeysPostgres;
|
|
101
|
+
function getSchemaColumnInfoPostgress(pool, schemaName, tableNames) {
|
|
102
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
103
|
+
const allColumns = yield Promise.all(tableNames.map((tableName) => __awaiter(this, void 0, void 0, function* () {
|
|
104
|
+
const query = `
|
|
105
|
+
SELECT column_name as "columnName", udt_name as "fieldType"
|
|
106
|
+
FROM information_schema.columns
|
|
107
|
+
WHERE table_schema = '${tableName.schemaName}'
|
|
108
|
+
AND table_name = '${tableName.tableName}'
|
|
109
|
+
ORDER BY ordinal_position;
|
|
110
|
+
`;
|
|
111
|
+
const results = yield runQueryPostgres(query, pool);
|
|
112
|
+
return {
|
|
113
|
+
tableName: `${tableName.schemaName}.${tableName.tableName}`,
|
|
114
|
+
displayName: `${tableName.schemaName}.${tableName.tableName}`,
|
|
115
|
+
columns: results.rows.map((row) => {
|
|
116
|
+
var _a;
|
|
117
|
+
let pgType = (_a = pgtypes_1.PG_TYPES.find((pgType) => {
|
|
118
|
+
return pgType.typname === row.fieldType;
|
|
119
|
+
})) === null || _a === void 0 ? void 0 : _a.oid;
|
|
120
|
+
if (!pgType) {
|
|
121
|
+
pgType = 1043;
|
|
122
|
+
}
|
|
123
|
+
return {
|
|
124
|
+
columnName: row.columnName,
|
|
125
|
+
displayName: row.columnName,
|
|
126
|
+
dataTypeID: pgType,
|
|
127
|
+
fieldType: row.fieldType,
|
|
128
|
+
};
|
|
129
|
+
}),
|
|
130
|
+
};
|
|
131
|
+
})));
|
|
132
|
+
return allColumns;
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
exports.getSchemaColumnInfoPostgress = getSchemaColumnInfoPostgress;
|
|
136
|
+
function formatPostgresConfig(connectionString) {
|
|
137
|
+
return { connectionString, ssl: { rejectUnauthorized: false } };
|
|
138
|
+
}
|
|
139
|
+
exports.formatPostgresConfig = formatPostgresConfig;
|
|
140
|
+
// CURRENTLY UNUSED BUT MAYBE USEFUL IN THE FUTURE
|
|
141
|
+
function getSslConfig(client) {
|
|
142
|
+
if (!client.useSsl) {
|
|
143
|
+
return undefined;
|
|
144
|
+
}
|
|
145
|
+
if (client.serverCa && client.clientKey && client.clientCert) {
|
|
146
|
+
return {
|
|
147
|
+
rejectUnauthorized: false,
|
|
148
|
+
ca: client.serverCa,
|
|
149
|
+
key: client.clientKey,
|
|
150
|
+
cert: client.clientCert,
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
if (client.serverCa) {
|
|
154
|
+
return {
|
|
155
|
+
rejectUnauthorized: false,
|
|
156
|
+
ca: client.serverCa,
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
// if using ssl with no certificates
|
|
160
|
+
return { rejectUnauthorized: false };
|
|
161
|
+
}
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.getSchemaColumnInfoSnowflake = exports.getForeignKeysSnowflake = exports.disconnectFromSnowflake = exports.connectToSnowflake = exports.formatSnowflakeConfig = exports.getColumnsByTableSnowflake = exports.getTablesBySchemaSnowflake = exports.getSchemasSnowflake = exports.runQuerySnowflake = void 0;
|
|
16
|
+
const snowflake_sdk_1 = __importDefault(require("snowflake-sdk"));
|
|
17
|
+
const textProcessing_1 = require("../utils/textProcessing");
|
|
18
|
+
const POSTGRES_SNOWFLAKE_MAP = {
|
|
19
|
+
BOOLEAN: 16,
|
|
20
|
+
FIXED: 1700, // DECIMAL or NUMERIC
|
|
21
|
+
REAL: 700, // FLOAT4
|
|
22
|
+
DOUBLE: 701, // FLOAT8
|
|
23
|
+
TEXT: 25, // TEXT in PostgreSQL
|
|
24
|
+
DATE: 1082,
|
|
25
|
+
DATETIME: 1184, // TIMESTAMP in PostgreSQL
|
|
26
|
+
TIME: 1083,
|
|
27
|
+
TIMESTAMP_LTZ: 1184,
|
|
28
|
+
TIMESTAMP_NTZ: 1184,
|
|
29
|
+
TIMESTAMP_TZ: 1184,
|
|
30
|
+
VARIANT: 114, // JSONB in PostgreSQL
|
|
31
|
+
OBJECT: 114, // JSONB, as an equivalent for structured JSON
|
|
32
|
+
ARRAY: 1009, // TEXT[], assuming most common case
|
|
33
|
+
BINARY: 17, // BYTEA
|
|
34
|
+
};
|
|
35
|
+
function runQuerySnowflake(sql, connection) {
|
|
36
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
37
|
+
const results = yield new Promise((resolve, reject) => {
|
|
38
|
+
connection.execute({
|
|
39
|
+
sqlText: sql,
|
|
40
|
+
complete: (err, stmt, rows) => {
|
|
41
|
+
if (err) {
|
|
42
|
+
reject(err);
|
|
43
|
+
return { success: false, message: err.message };
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
resolve({
|
|
47
|
+
rows,
|
|
48
|
+
fields: stmt.getColumns().map((col) => ({
|
|
49
|
+
name: col.getName(),
|
|
50
|
+
dataTypeID: POSTGRES_SNOWFLAKE_MAP[col.getType().toUpperCase()],
|
|
51
|
+
})),
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
return results;
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
exports.runQuerySnowflake = runQuerySnowflake;
|
|
61
|
+
function getSchemasSnowflake(connection) {
|
|
62
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
63
|
+
const sql = `SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA
|
|
64
|
+
WHERE SCHEMA_NAME != 'INFORMATION_SCHEMA'`;
|
|
65
|
+
const results = yield runQuerySnowflake(sql, connection);
|
|
66
|
+
return results.rows.map((row) => row.SCHEMA_NAME);
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
exports.getSchemasSnowflake = getSchemasSnowflake;
|
|
70
|
+
function getTablesBySchemaSnowflake(connection, schemaNames) {
|
|
71
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
72
|
+
const allColumns = yield Promise.all(schemaNames.map((schema) => __awaiter(this, void 0, void 0, function* () {
|
|
73
|
+
const query = `SELECT
|
|
74
|
+
TABLE_NAME as "tableName",
|
|
75
|
+
TABLE_SCHEMA as "schemaName"
|
|
76
|
+
FROM INFORMATION_SCHEMA.TABLES
|
|
77
|
+
WHERE TABLE_SCHEMA = '${schema}';
|
|
78
|
+
`;
|
|
79
|
+
const results = yield runQuerySnowflake(query, connection);
|
|
80
|
+
return results.rows.map((row) => {
|
|
81
|
+
return { tableName: row.tableName, schemaName: row.schemaName };
|
|
82
|
+
});
|
|
83
|
+
})));
|
|
84
|
+
return allColumns.flat();
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
exports.getTablesBySchemaSnowflake = getTablesBySchemaSnowflake;
|
|
88
|
+
function getColumnsByTableSnowflake(connection, schemaName, tableName) {
|
|
89
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
90
|
+
const sql = `SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = '${schemaName}' AND TABLE_NAME = '${tableName}'`;
|
|
91
|
+
const results = yield runQuerySnowflake(sql, connection);
|
|
92
|
+
return results.rows.map((row) => row.COLUMN_NAME);
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
exports.getColumnsByTableSnowflake = getColumnsByTableSnowflake;
|
|
96
|
+
function formatSnowflakeConfig(connectionString) {
|
|
97
|
+
const parsed = new URL(connectionString);
|
|
98
|
+
return {
|
|
99
|
+
account: parsed.hostname,
|
|
100
|
+
username: parsed.username,
|
|
101
|
+
password: parsed.password,
|
|
102
|
+
database: parsed.pathname.split("/")[1],
|
|
103
|
+
warehouse: parsed.pathname.split("/")[2],
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
exports.formatSnowflakeConfig = formatSnowflakeConfig;
|
|
107
|
+
function connectToSnowflake(config) {
|
|
108
|
+
const connection = snowflake_sdk_1.default.createConnection(config);
|
|
109
|
+
connection.connect((err) => {
|
|
110
|
+
if (err) {
|
|
111
|
+
console.error(`Failed to connect to Snowflake: ${err.message}`);
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
return connection;
|
|
115
|
+
}
|
|
116
|
+
exports.connectToSnowflake = connectToSnowflake;
|
|
117
|
+
function disconnectFromSnowflake(connection) {
|
|
118
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
119
|
+
connection.destroy((err, conn) => {
|
|
120
|
+
if (err) {
|
|
121
|
+
console.error(`Failed to disconnect from Snowflake: ${err.message}`);
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
exports.disconnectFromSnowflake = disconnectFromSnowflake;
|
|
127
|
+
function getForeignKeysSnowflake(connection, schemaName, tableName, primaryKey) {
|
|
128
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
129
|
+
let depluralizedTableName = (0, textProcessing_1.depluralize)(tableName);
|
|
130
|
+
let sql = `SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS
|
|
131
|
+
WHERE TABLE_SCHEMA = '${schemaName}'
|
|
132
|
+
AND TABLE_NAME = '${schemaName}'
|
|
133
|
+
and TABLE_NAME != '${tableName}'
|
|
134
|
+
and (COLUMN_NAME = '${primaryKey}'
|
|
135
|
+
or COLUMN_NAME = '${depluralizedTableName}_${primaryKey}'
|
|
136
|
+
or COLUMN_NAME = '${depluralizedTableName}${(0, textProcessing_1.capitalize)(primaryKey)}')`;
|
|
137
|
+
const results = yield runQuerySnowflake(sql, connection);
|
|
138
|
+
let foreignKeysString = results.rows.map((key) => {
|
|
139
|
+
return key.COLUMN_NAME;
|
|
140
|
+
});
|
|
141
|
+
foreignKeysString = foreignKeysString.filter((key) => key !== "id" && key !== "_id_");
|
|
142
|
+
foreignKeysString = [...new Set(foreignKeysString)];
|
|
143
|
+
if (foreignKeysString.length === 0) {
|
|
144
|
+
sql = `SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS
|
|
145
|
+
WHERE TABLE_SCHEMA = '${schemaName}'
|
|
146
|
+
AND TABLE_NAME = '${schemaName}'
|
|
147
|
+
and TABLE_NAME != '${tableName}'
|
|
148
|
+
and (COLUMN_NAME like '${depluralizedTableName}%'
|
|
149
|
+
or column_name like '%\\_id'
|
|
150
|
+
or column_name like '%Id'
|
|
151
|
+
or COLUMN_NAME like '%\\_${primaryKey}'
|
|
152
|
+
or COLUMN_NAME like '%${(0, textProcessing_1.capitalize)(primaryKey)}')`;
|
|
153
|
+
const results = yield runQuerySnowflake(sql, connection);
|
|
154
|
+
foreignKeysString = results.rows.map((key) => {
|
|
155
|
+
return key.COLUMN_NAME;
|
|
156
|
+
});
|
|
157
|
+
foreignKeysString = [...new Set(foreignKeysString)];
|
|
158
|
+
}
|
|
159
|
+
return foreignKeysString;
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
exports.getForeignKeysSnowflake = getForeignKeysSnowflake;
|
|
163
|
+
function getSchemaColumnInfoSnowflake(connection, schemaName, tableNames) {
|
|
164
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
165
|
+
const allColumns = yield Promise.all(tableNames.map((tableName) => __awaiter(this, void 0, void 0, function* () {
|
|
166
|
+
const query = `SELECT
|
|
167
|
+
COLUMN_NAME as "columnName", DATA_TYPE as "dataType"
|
|
168
|
+
FROM INFORMATION_SCHEMA.COLUMNS
|
|
169
|
+
WHERE TABLE_SCHEMA = '${tableName.schemaName}' AND TABLE_NAME = '${tableName.tableName}';
|
|
170
|
+
`;
|
|
171
|
+
const results = yield runQuerySnowflake(query, connection);
|
|
172
|
+
return {
|
|
173
|
+
tableName: `${tableName.schemaName}.${tableName.tableName}`,
|
|
174
|
+
displayName: `${tableName.schemaName}.${tableName.tableName}`,
|
|
175
|
+
columns: results.rows.map((row) => {
|
|
176
|
+
const postgresType = POSTGRES_SNOWFLAKE_MAP[row.dataType];
|
|
177
|
+
return {
|
|
178
|
+
columnName: row.columnName,
|
|
179
|
+
displayName: row.columnName,
|
|
180
|
+
dataTypeID: postgresType,
|
|
181
|
+
fieldType: row.dataType,
|
|
182
|
+
};
|
|
183
|
+
}),
|
|
184
|
+
};
|
|
185
|
+
})));
|
|
186
|
+
return allColumns;
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
exports.getSchemaColumnInfoSnowflake = getSchemaColumnInfoSnowflake;
|
package/dist/index.js
CHANGED
|
@@ -12,10 +12,12 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
12
12
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
13
|
};
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
-
const
|
|
15
|
+
const CachedConnection_1 = require("./db/CachedConnection");
|
|
16
16
|
const axios_1 = __importDefault(require("axios"));
|
|
17
17
|
require("dotenv/config");
|
|
18
18
|
const RunQueryProcesses_1 = require("./utils/RunQueryProcesses");
|
|
19
|
+
const DatabaseHelper_1 = require("./db/DatabaseHelper");
|
|
20
|
+
const schemaConversion_1 = require("./utils/schemaConversion");
|
|
19
21
|
const HOST = process.env.ENV === "development"
|
|
20
22
|
? "http://localhost:8080"
|
|
21
23
|
: "https://quill-344421.uc.r.appspot.com";
|
|
@@ -23,31 +25,38 @@ const HOST = process.env.ENV === "development"
|
|
|
23
25
|
* Quill - Fullstack API Platform for Dashboards and Reporting.
|
|
24
26
|
*/
|
|
25
27
|
class QuillClass {
|
|
26
|
-
constructor(privateKey, databaseConnectionString, cache = {}) {
|
|
27
|
-
this.
|
|
28
|
-
this.baseUrl = HOST;
|
|
28
|
+
constructor(privateKey, databaseType, databaseConnectionString, databaseCredentials, cache = {}, metadataServerURL) {
|
|
29
|
+
this.baseUrl = metadataServerURL ? metadataServerURL : HOST;
|
|
29
30
|
this.config = { headers: { Authorization: `Bearer ${privateKey}` } };
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
let credentials = databaseCredentials;
|
|
32
|
+
if (databaseConnectionString) {
|
|
33
|
+
credentials = (0, DatabaseHelper_1.getDatabaseCredentials)(databaseType, databaseConnectionString);
|
|
34
|
+
}
|
|
35
|
+
this.targetConnection = new CachedConnection_1.CachedConnection(databaseType, credentials, cache);
|
|
33
36
|
}
|
|
34
37
|
query({ orgId, metadata }) {
|
|
35
|
-
var _a, _b;
|
|
38
|
+
var _a, _b, _c;
|
|
36
39
|
return __awaiter(this, void 0, void 0, function* () {
|
|
37
|
-
this.
|
|
40
|
+
this.targetConnection.orgId = orgId;
|
|
38
41
|
try {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
42
|
+
const preQueryResults = metadata.preQueries
|
|
43
|
+
? yield this.runQueries(metadata.preQueries, this.targetConnection.databaseType, metadata.databaseType, metadata.runQueryConfig)
|
|
44
|
+
: {};
|
|
45
|
+
if ((_a = metadata.runQueryConfig) === null || _a === void 0 ? void 0 : _a.overridePost) {
|
|
46
|
+
return {
|
|
47
|
+
data: { queryResults: preQueryResults },
|
|
48
|
+
status: "success",
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
const response = yield this.postQuill(metadata.task, Object.assign(Object.assign(Object.assign({}, metadata), preQueryResults), { orgId, viewQuery: metadata.preQueries ? metadata.preQueries[0] : undefined }));
|
|
43
52
|
// if there is no metadata object in the response, create one
|
|
44
53
|
if (!response.metadata) {
|
|
45
54
|
response.metadata = {};
|
|
46
55
|
}
|
|
47
|
-
const results = yield this.runQueries(response.queries, response.metadata.runQueryConfig);
|
|
56
|
+
const results = yield this.runQueries(response.queries, this.targetConnection.databaseType, metadata.databaseType, response.metadata.runQueryConfig);
|
|
48
57
|
// QUICK JANKY FIX TO UPDATE METADATA AFTER GETTING MAPPED ARRAYS
|
|
49
58
|
if (results.mappedArray &&
|
|
50
|
-
((
|
|
59
|
+
((_c = (_b = response.metadata) === null || _b === void 0 ? void 0 : _b.runQueryConfig) === null || _c === void 0 ? void 0 : _c.arrayToMap)) {
|
|
51
60
|
const arrayToMap = response.metadata.runQueryConfig.arrayToMap;
|
|
52
61
|
results.mappedArray.forEach((array, index) => {
|
|
53
62
|
response.metadata[arrayToMap.arrayName][index][arrayToMap.field] =
|
|
@@ -76,26 +85,64 @@ class QuillClass {
|
|
|
76
85
|
}
|
|
77
86
|
});
|
|
78
87
|
}
|
|
79
|
-
runQueries(queries, runQueryConfig) {
|
|
88
|
+
runQueries(queries, pkDatabaseType, databaseType, runQueryConfig) {
|
|
80
89
|
return __awaiter(this, void 0, void 0, function* () {
|
|
81
90
|
let results;
|
|
82
91
|
if (!queries)
|
|
83
92
|
return Object.assign(Object.assign({}, results), { queryResults: [] });
|
|
93
|
+
if (databaseType &&
|
|
94
|
+
databaseType.toLowerCase() !== pkDatabaseType.toLowerCase()) {
|
|
95
|
+
return {
|
|
96
|
+
dbMismatched: true,
|
|
97
|
+
backendDatbaseType: pkDatabaseType,
|
|
98
|
+
queryResults: [],
|
|
99
|
+
};
|
|
100
|
+
}
|
|
84
101
|
if (runQueryConfig === null || runQueryConfig === void 0 ? void 0 : runQueryConfig.arrayToMap) {
|
|
85
|
-
const mappedArray = yield (0, RunQueryProcesses_1.mapQueries)(queries,
|
|
102
|
+
const mappedArray = yield (0, RunQueryProcesses_1.mapQueries)(queries, this.targetConnection);
|
|
86
103
|
return Object.assign(Object.assign({}, results), { queryResults: [], mappedArray });
|
|
87
104
|
}
|
|
105
|
+
else if (runQueryConfig === null || runQueryConfig === void 0 ? void 0 : runQueryConfig.getColumns) {
|
|
106
|
+
const queryResult = yield this.targetConnection.query(`${queries[0]} limit 1`);
|
|
107
|
+
const columns = queryResult.fields.map((field) => {
|
|
108
|
+
return {
|
|
109
|
+
fieldType: (0, schemaConversion_1.convertTypeToPostgres)(field.dataTypeID),
|
|
110
|
+
name: field.name,
|
|
111
|
+
displayName: field.name,
|
|
112
|
+
isVisible: true,
|
|
113
|
+
field: field.name,
|
|
114
|
+
};
|
|
115
|
+
});
|
|
116
|
+
return { columns };
|
|
117
|
+
}
|
|
118
|
+
else if (runQueryConfig === null || runQueryConfig === void 0 ? void 0 : runQueryConfig.getTables) {
|
|
119
|
+
const queryResult = yield (0, DatabaseHelper_1.getTablesBySchemaByDatabase)(this.targetConnection.databaseType, this.targetConnection.pool, runQueryConfig.schemaNames || runQueryConfig.schema);
|
|
120
|
+
const schemaInfo = yield (0, DatabaseHelper_1.getColumnInfoBySchemaByDatabase)(this.targetConnection.databaseType, this.targetConnection.pool, runQueryConfig.schema, queryResult);
|
|
121
|
+
return schemaInfo;
|
|
122
|
+
}
|
|
88
123
|
else {
|
|
124
|
+
if (runQueryConfig === null || runQueryConfig === void 0 ? void 0 : runQueryConfig.limitThousand) {
|
|
125
|
+
queries = queries.map((query) => {
|
|
126
|
+
return query.replace(/;/, "") + " limit 1000;";
|
|
127
|
+
});
|
|
128
|
+
}
|
|
89
129
|
const queryResults = yield Promise.all(queries.map((query) => __awaiter(this, void 0, void 0, function* () {
|
|
90
|
-
return yield this.
|
|
130
|
+
return yield this.targetConnection.query(query);
|
|
91
131
|
})));
|
|
92
132
|
results = Object.assign(Object.assign({}, results), { queryResults });
|
|
93
|
-
if (runQueryConfig === null || runQueryConfig === void 0 ? void 0 : runQueryConfig.getSchema) {
|
|
94
|
-
results = Object.assign(Object.assign({}, results), { columns: yield (0, RunQueryProcesses_1.getTableSchema)(queryResults[0], this.targetPool) });
|
|
95
|
-
}
|
|
96
133
|
if (runQueryConfig === null || runQueryConfig === void 0 ? void 0 : runQueryConfig.removeFields) {
|
|
97
134
|
results = Object.assign(Object.assign({}, results), { queryResults: (0, RunQueryProcesses_1.removeFields)(queryResults, runQueryConfig.removeFields) });
|
|
98
135
|
}
|
|
136
|
+
if (runQueryConfig === null || runQueryConfig === void 0 ? void 0 : runQueryConfig.convertDatatypes) {
|
|
137
|
+
results = queryResults.map((result) => {
|
|
138
|
+
return {
|
|
139
|
+
fields: result.fields.map((field) => {
|
|
140
|
+
return Object.assign(Object.assign({}, field), { fieldType: (0, schemaConversion_1.convertTypeToPostgres)(field.dataTypeID), isVisible: true, field: field.name, displayName: field.name, name: field.name });
|
|
141
|
+
}),
|
|
142
|
+
rows: result.rows,
|
|
143
|
+
};
|
|
144
|
+
});
|
|
145
|
+
}
|
|
99
146
|
}
|
|
100
147
|
return results;
|
|
101
148
|
});
|
|
@@ -108,14 +155,23 @@ class QuillClass {
|
|
|
108
155
|
}
|
|
109
156
|
close() {
|
|
110
157
|
return __awaiter(this, void 0, void 0, function* () {
|
|
111
|
-
yield this.
|
|
158
|
+
yield this.targetConnection.close();
|
|
112
159
|
});
|
|
113
160
|
}
|
|
114
161
|
}
|
|
115
162
|
exports.default = QuillClass;
|
|
116
|
-
const Quill = ({ privateKey, databaseConnectionString, cache, }) => {
|
|
117
|
-
return new QuillClass(privateKey, databaseConnectionString, cache);
|
|
163
|
+
const Quill = ({ privateKey, databaseConnectionString, databaseConfig, cache, databaseType, metadataServerURL, }) => {
|
|
164
|
+
return new QuillClass(privateKey, databaseType, databaseConnectionString, databaseConfig, cache, metadataServerURL);
|
|
118
165
|
};
|
|
119
166
|
module.exports = Quill;
|
|
120
167
|
module.exports.Quill = Quill;
|
|
121
168
|
module.exports.default = Quill;
|
|
169
|
+
module.exports.getTablesBySchemaByDatabase = DatabaseHelper_1.getTablesBySchemaByDatabase;
|
|
170
|
+
module.exports.getDatabaseCredentials = DatabaseHelper_1.getDatabaseCredentials;
|
|
171
|
+
module.exports.getColumnsByTableByDatabase = DatabaseHelper_1.getColumnsByTableByDatabase;
|
|
172
|
+
module.exports.getForiegnKeysByDatabase = DatabaseHelper_1.getForiegnKeysByDatabase;
|
|
173
|
+
module.exports.getSchemasByDatabase = DatabaseHelper_1.getSchemasByDatabase;
|
|
174
|
+
module.exports.getColumnInfoBySchemaByDatabase =
|
|
175
|
+
DatabaseHelper_1.getColumnInfoBySchemaByDatabase;
|
|
176
|
+
module.exports.connectToDatabase = DatabaseHelper_1.connectToDatabase;
|
|
177
|
+
module.exports.runQueryByDatabase = DatabaseHelper_1.runQueryByDatabase;
|
package/dist/index.uspec.js
CHANGED
|
@@ -4,12 +4,13 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
const _1 = __importDefault(require("."));
|
|
7
|
+
const DatabaseHelper_1 = require("./db/DatabaseHelper");
|
|
7
8
|
jest.mock(".");
|
|
8
9
|
describe("Quill", () => {
|
|
9
10
|
let quill;
|
|
10
11
|
beforeEach(() => {
|
|
11
|
-
quill = new _1.default("dummy_private_key", "dummy_db_url");
|
|
12
|
-
quill.
|
|
12
|
+
quill = new _1.default("dummy_private_key", DatabaseHelper_1.DatabaseType.postgres, "dummy_db_url", {}, undefined);
|
|
13
|
+
quill.targetConnection.query = jest.fn().mockResolvedValue([]);
|
|
13
14
|
});
|
|
14
15
|
describe("query", () => {
|
|
15
16
|
it("return nothing when suppling no queries", () => {
|
|
@@ -9,22 +9,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
9
9
|
});
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.mapQueries = exports.removeFields =
|
|
13
|
-
function getTableSchema(queryResults, targetPool) {
|
|
14
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
15
|
-
const typesQuery = yield targetPool.query("select typname, oid, typarray from pg_type order by oid;");
|
|
16
|
-
const schema = queryResults[0].fields.map((field) => {
|
|
17
|
-
return {
|
|
18
|
-
fieldType: typesQuery.rows.filter((type) => field.dataTypeID === type.oid)[0].typname,
|
|
19
|
-
name: field.name,
|
|
20
|
-
displayName: field.name,
|
|
21
|
-
isVisible: true,
|
|
22
|
-
};
|
|
23
|
-
});
|
|
24
|
-
return schema;
|
|
25
|
-
});
|
|
26
|
-
}
|
|
27
|
-
exports.getTableSchema = getTableSchema;
|
|
12
|
+
exports.mapQueries = exports.removeFields = void 0;
|
|
28
13
|
function removeFields(queryResults, fieldsToRemove) {
|
|
29
14
|
const fields = queryResults.fields.filter((field) => fieldsToRemove.includes(field.name));
|
|
30
15
|
const rows = queryResults.map((row) => {
|
|
@@ -35,11 +20,11 @@ function removeFields(queryResults, fieldsToRemove) {
|
|
|
35
20
|
});
|
|
36
21
|
}
|
|
37
22
|
exports.removeFields = removeFields;
|
|
38
|
-
function mapQueries(queries,
|
|
23
|
+
function mapQueries(queries, targetConnection) {
|
|
39
24
|
return __awaiter(this, void 0, void 0, function* () {
|
|
40
25
|
const mappedArray = [];
|
|
41
26
|
for (let i = 0; i < queries.length; i++) {
|
|
42
|
-
const queryResult = yield
|
|
27
|
+
const queryResult = yield targetConnection.query(queries[i]);
|
|
43
28
|
mappedArray.push(queryResult.rows);
|
|
44
29
|
}
|
|
45
30
|
return mappedArray;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.convertTypeToPostgres = void 0;
|
|
4
|
+
const pgtypes_1 = require("../assets/pgtypes");
|
|
5
|
+
function convertTypeToPostgres(data_type_id) {
|
|
6
|
+
var _a;
|
|
7
|
+
const type = pgtypes_1.PG_TYPES.find((type) => data_type_id === type.oid)
|
|
8
|
+
? (_a = pgtypes_1.PG_TYPES.find((type) => data_type_id === type.oid)) === null || _a === void 0 ? void 0 : _a.typname
|
|
9
|
+
: undefined;
|
|
10
|
+
if (!type) {
|
|
11
|
+
return "varchar";
|
|
12
|
+
}
|
|
13
|
+
return type;
|
|
14
|
+
}
|
|
15
|
+
exports.convertTypeToPostgres = convertTypeToPostgres;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.depluralize = exports.capitalize = void 0;
|
|
4
|
+
function capitalize(text) {
|
|
5
|
+
return text.charAt(0).toUpperCase() + text.slice(1);
|
|
6
|
+
}
|
|
7
|
+
exports.capitalize = capitalize;
|
|
8
|
+
function depluralize(text) {
|
|
9
|
+
if (text.endsWith("ies")) {
|
|
10
|
+
return text.slice(0, -3) + "y";
|
|
11
|
+
}
|
|
12
|
+
if (text.endsWith("s")) {
|
|
13
|
+
return text.slice(0, -1);
|
|
14
|
+
}
|
|
15
|
+
return text;
|
|
16
|
+
}
|
|
17
|
+
exports.depluralize = depluralize;
|