-
Notifications
You must be signed in to change notification settings - Fork 10
/
knexnest.js
123 lines (103 loc) · 4.54 KB
/
knexnest.js
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
'use strict';
var NestHydrationJS = require('nesthydrationjs')();
/* expects a knex object and returns a promise */
var knexnest = function (knexQuery, listOnEmpty) {
// structPropToColumnMap will be sorted out properly inside nest of
// NestHydration this just indicates if empty should be object or array
var structPropToColumnMap = null;
if (knexQuery.client.config ? knexQuery.client.config.client === 'postgres' : knexQuery.client.Raw.name === 'Raw_PG') {
// Postgres limit column name lengths to 63 characters, need to work
// around that.
// Knex also doesn't provide get or set mechanisms for the column
// information once received by select method. So the following gets
// dirty by reaching in to pull out the _statement property, filtering
// it for columns, processes those and puts the new values back in,
// wiping out the old columns
if (knexQuery._statements === undefined) {
return Promise.reject('knex query object not structured as expected for KnexNest: does not have _statements property');
}
var aliasList = [];
var renamedMap = {};
var uniqueId = 0;
var column, alias, prepend, renamed, renamedColumn;
for (var i = 0; i < knexQuery._statements.length; i++) {
if (knexQuery._statements[i].grouping !== 'columns') {
continue;
}
if (knexQuery._statements[i].value === undefined) {
return Promise.reject('knex query object not structured as expected for KnexNest: _statements item with column grouping does not have value property');
}
// columns statement, use it
for (var j = 0; j < knexQuery._statements[i].value.length; j++) {
renamedColumn = null;
// each column in the column statement
column = knexQuery._statements[i].value[j].sql
? knexQuery._statements[i].value[j].sql
: knexQuery._statements[i].value[j]
;
column = column.trim();
if (column.substr(-1) === '"') {
// assume the line has the format
// tableNameOrAlias.columnName "alias"
// or
// tableNameOrAlias.columnName AS "alias"
alias = column.slice(column.lastIndexOf('"', column.length - 2) + 1, -1);
if (alias.length > knexnest.MAX_POSTGRES_COLUMN_NAME_LENGTH) {
// shorten the alias to allowed size
prepend = 'col_' + (uniqueId++) + '_';
renamed = prepend + alias.substr(-1 * knexnest.MAX_POSTGRES_COLUMN_NAME_LENGTH + prepend.length);
// add to mapping used after db executed to reverse this rename
renamedMap[alias] = renamed;
// replace the original alias with the shortened one
renamedColumn = column.substr(0, column.indexOf('"')) + '"' + renamed + '"';
}
aliasList.push(alias);
} else if (column.toLowerCase().indexOf(' as ') !== -1) {
// assume the line has the format
// tableNameOrAlias.columnName AS alias
alias = column.substr(column.lastIndexOf(' ') + 1);
if (alias.length > knexnest.MAX_POSTGRES_COLUMN_NAME_LENGTH) {
// shorten the alias to allowed size
prepend = 'col_' + (uniqueId++) + '_';
renamed = prepend + alias.substr(-1 * knexnest.MAX_POSTGRES_COLUMN_NAME_LENGTH + prepend.length);
// add to mapping used after db executed to reverse this rename
renamedMap[alias] = renamed;
// replace the original alias with the shortened one
renamedColumn = column.substr(0, column.lastIndexOf(' ') + 1) + renamed;
}
aliasList.push(alias);
} else if (column.indexOf('.') !== -1) {
// assume the line has the format
// tableNameOrAlias.columnName
aliasList.push(column.substr(column.indexOf('.') + 1));
} else {
// assume the line has the format
// columnName
aliasList.push(column);
}
if (renamedColumn !== null) {
if (knexQuery._statements[i].value[j].sql) {
knexQuery._statements[i].value[j].sql = renamedColumn;
} else {
knexQuery._statements[i].value[j] = renamedColumn;
}
}
}
}
// manually specify the propertyMapping based on the aliases determined in rename process
structPropToColumnMap = NestHydrationJS.structPropToColumnMapFromColumnHints(aliasList, renamedMap);
if (!(structPropToColumnMap instanceof Array) && listOnEmpty) {
return Promise.reject('listOnEmpty param conflicts with query which specifies an object or null result');
}
}
if (structPropToColumnMap === null && listOnEmpty) {
structPropToColumnMap = true;
}
return knexQuery
.then(function (data) {
return NestHydrationJS.nest(data, structPropToColumnMap);
})
;
};
knexnest.MAX_POSTGRES_COLUMN_NAME_LENGTH = 63;
module.exports = knexnest;