forked from sqlpad/sqlpad
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathutils.js
More file actions
138 lines (126 loc) · 4.13 KB
/
utils.js
File metadata and controls
138 lines (126 loc) · 4.13 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
/**
* Formats flat schema query results into a hierarchy
*
* Expected input is
* {
* rows: [
* {
* schema_name: '', // or table_schema. optional. name of schema if DB uses schemas
* schema_description: '', // description of schema. optional.
* table_name: '', // name of table.
* table_description: '', // description of table. optional.
* column_name: '', // name of column.
* column_description: '', // description of column. optional.
* data_type: '', // data type of column
* }
* ]
* }
*
* Returned format is
* {
* schemas: [
* {
* name: '',
* description: '',
* tables: [
* {
* name: '',
* description: '',
* columns: [
* {
* name: '',
* description: '',
* dataType: ''
* }
* ]
* }
* ]
* }
* ]
* }
*
* @param {object} queryResult
* @param {array} [queryResult.rows]
*/
function formatSchemaQueryResults(queryResult) {
if (!queryResult || !queryResult.rows || !queryResult.rows.length) {
return {};
}
// IDs will be full paths of objects
// `schemaname`, `schemaname.tablename`
let hasSchema = false;
const schemasById = {};
const tablesById = {};
for (const row of queryResult.rows) {
// queryResult row casing may not always be consistent with what is specified in query
// HANA is always uppercase despire aliasing as lower case for example
// For example a row from HANA might be { TABLE_SCHEMA: 'name' } instead of { table_schema: 'name' } expected
// To account for this loop through rows and normalize the case
const cleanRow = {};
Object.keys(row).forEach((key) => {
cleanRow[key.toLowerCase()] = row[key];
});
// Originally information schemas returned a field "table_schema" for schema name
// "schema_name" fits better and is more consistent
// This supports both fields, preferring schema_name if set;
const schemaName = cleanRow.schema_name || cleanRow.table_schema;
const schemaDescription = cleanRow.schema_description;
const tableName = cleanRow.table_name;
const tableDescription = cleanRow.table_description;
const columnName = cleanRow.column_name;
const dataType = cleanRow.data_type;
const columnDescription = cleanRow.column_description;
const schemaId = schemaName;
const tableId = schemaName ? `${schemaName}.${tableName}` : undefined;
// If schema exists and hasn't been added to index yet, add it
if (schemaId && !schemasById[schemaId]) {
hasSchema = true;
schemasById[schemaId] = {
name: schemaName,
description: schemaDescription,
tables: [],
// temporary index to make it efficient to add tables
tablesById: {},
};
}
// If table hasn't been captured in index yet, add it
if (!tablesById[tableId]) {
const table = {
name: tableName,
description: tableDescription,
columns: [],
};
tablesById[tableId] = table;
// If schema exists and table is not yet there, add it to schema
// Its pushed to tables array for final product, and added to tablesById map
// so final operation can remove tablesById map and not have to iterate the list again
if (schemaId && !schemasById[schemaId].tablesById[tableId]) {
schemasById[schemaId].tables.push(table);
schemasById[schemaId].tablesById[tableId] = table;
}
}
const column = {
name: columnName,
description: columnDescription,
dataType,
};
tablesById[tableId].columns.push(column);
}
// If schema is present, loop over values and remove the tablesById
// The resulting array will be in the format needed
if (hasSchema) {
return {
schemas: Object.values(schemasById).map((schema) => {
delete schema.tablesById;
return schema;
}),
};
}
// If there was no schema, tablesById has everything needed
return {
tables: Object.values(tablesById),
};
}
module.exports = {
formatSchemaQueryResults,
};