query_part.ts 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408
  1. ///<reference path="../../../headers/common.d.ts" />
  2. import _ from 'lodash';
  3. import {
  4. QueryPartDef,
  5. QueryPart,
  6. functionRenderer,
  7. suffixRenderer,
  8. } from 'app/core/components/query_part/query_part';
  9. var index = [];
  10. var categories = {
  11. Aggregations: [],
  12. Selectors: [],
  13. Transformations: [],
  14. Predictors: [],
  15. Math: [],
  16. Aliasing: [],
  17. Fields: [],
  18. };
  19. function createPart(part): any {
  20. var def = index[part.type];
  21. if (!def) {
  22. throw {message: 'Could not find query part ' + part.type};
  23. }
  24. return new QueryPart(part, def);
  25. }
  26. function register(options: any) {
  27. index[options.type] = new QueryPartDef(options);
  28. options.category.push(index[options.type]);
  29. }
  30. var groupByTimeFunctions = [];
  31. function aliasRenderer(part, innerExpr) {
  32. return innerExpr + ' AS ' + '"' + part.params[0] + '"';
  33. }
  34. function fieldRenderer(part, innerExpr) {
  35. if (part.params[0] === '*') {
  36. return '*';
  37. }
  38. return '"' + part.params[0] + '"';
  39. }
  40. function replaceAggregationAddStrategy(selectParts, partModel) {
  41. // look for existing aggregation
  42. for (var i = 0; i < selectParts.length; i++) {
  43. var part = selectParts[i];
  44. if (part.def.category === categories.Aggregations) {
  45. selectParts[i] = partModel;
  46. return;
  47. }
  48. if (part.def.category === categories.Selectors) {
  49. selectParts[i] = partModel;
  50. return;
  51. }
  52. }
  53. selectParts.splice(1, 0, partModel);
  54. }
  55. function addTransformationStrategy(selectParts, partModel) {
  56. var i;
  57. // look for index to add transformation
  58. for (i = 0; i < selectParts.length; i++) {
  59. var part = selectParts[i];
  60. if (part.def.category === categories.Math || part.def.category === categories.Aliasing) {
  61. break;
  62. }
  63. }
  64. selectParts.splice(i, 0, partModel);
  65. }
  66. function addMathStrategy(selectParts, partModel) {
  67. var partCount = selectParts.length;
  68. if (partCount > 0) {
  69. // if last is math, replace it
  70. if (selectParts[partCount-1].def.type === 'math') {
  71. selectParts[partCount-1] = partModel;
  72. return;
  73. }
  74. // if next to last is math, replace it
  75. if (partCount > 1 && selectParts[partCount-2].def.type === 'math') {
  76. selectParts[partCount-2] = partModel;
  77. return;
  78. } else if (selectParts[partCount-1].def.type === 'alias') { // if last is alias add it before
  79. selectParts.splice(partCount-1, 0, partModel);
  80. return;
  81. }
  82. }
  83. selectParts.push(partModel);
  84. }
  85. function addAliasStrategy(selectParts, partModel) {
  86. var partCount = selectParts.length;
  87. if (partCount > 0) {
  88. // if last is alias, replace it
  89. if (selectParts[partCount-1].def.type === 'alias') {
  90. selectParts[partCount-1] = partModel;
  91. return;
  92. }
  93. }
  94. selectParts.push(partModel);
  95. }
  96. function addFieldStrategy(selectParts, partModel, query) {
  97. // copy all parts
  98. var parts = _.map(selectParts, function(part: any) {
  99. return createPart({type: part.def.type, params: _.clone(part.params)});
  100. });
  101. query.selectModels.push(parts);
  102. }
  103. register({
  104. type: 'field',
  105. addStrategy: addFieldStrategy,
  106. category: categories.Fields,
  107. params: [{type: 'field', dynamicLookup: true}],
  108. defaultParams: ['value'],
  109. renderer: fieldRenderer,
  110. });
  111. // Aggregations
  112. register({
  113. type: 'count',
  114. addStrategy: replaceAggregationAddStrategy,
  115. category: categories.Aggregations,
  116. params: [],
  117. defaultParams: [],
  118. renderer: functionRenderer,
  119. });
  120. register({
  121. type: 'distinct',
  122. addStrategy: replaceAggregationAddStrategy,
  123. category: categories.Aggregations,
  124. params: [],
  125. defaultParams: [],
  126. renderer: functionRenderer,
  127. });
  128. register({
  129. type: 'integral',
  130. addStrategy: replaceAggregationAddStrategy,
  131. category: categories.Aggregations,
  132. params: [],
  133. defaultParams: [],
  134. renderer: functionRenderer,
  135. });
  136. register({
  137. type: 'mean',
  138. addStrategy: replaceAggregationAddStrategy,
  139. category: categories.Aggregations,
  140. params: [],
  141. defaultParams: [],
  142. renderer: functionRenderer,
  143. });
  144. register({
  145. type: 'median',
  146. addStrategy: replaceAggregationAddStrategy,
  147. category: categories.Aggregations,
  148. params: [],
  149. defaultParams: [],
  150. renderer: functionRenderer,
  151. });
  152. register({
  153. type: 'mode',
  154. addStrategy: replaceAggregationAddStrategy,
  155. category: categories.Aggregations,
  156. params: [],
  157. defaultParams: [],
  158. renderer: functionRenderer,
  159. });
  160. register({
  161. type: 'sum',
  162. addStrategy: replaceAggregationAddStrategy,
  163. category: categories.Aggregations,
  164. params: [],
  165. defaultParams: [],
  166. renderer: functionRenderer,
  167. });
  168. // transformations
  169. register({
  170. type: 'derivative',
  171. addStrategy: addTransformationStrategy,
  172. category: categories.Transformations,
  173. params: [{ name: "duration", type: "interval", options: ['1s', '10s', '1m', '5m', '10m', '15m', '1h']}],
  174. defaultParams: ['10s'],
  175. renderer: functionRenderer,
  176. });
  177. register({
  178. type: 'spread',
  179. addStrategy: addTransformationStrategy,
  180. category: categories.Transformations,
  181. params: [],
  182. defaultParams: [],
  183. renderer: functionRenderer,
  184. });
  185. register({
  186. type: 'non_negative_derivative',
  187. addStrategy: addTransformationStrategy,
  188. category: categories.Transformations,
  189. params: [{ name: "duration", type: "interval", options: ['1s', '10s', '1m', '5m', '10m', '15m', '1h']}],
  190. defaultParams: ['10s'],
  191. renderer: functionRenderer,
  192. });
  193. register({
  194. type: 'difference',
  195. addStrategy: addTransformationStrategy,
  196. category: categories.Transformations,
  197. params: [],
  198. defaultParams: [],
  199. renderer: functionRenderer,
  200. });
  201. register({
  202. type: 'non_negative_difference',
  203. addStrategy: addTransformationStrategy,
  204. category: categories.Transformations,
  205. params: [],
  206. defaultParams: [],
  207. renderer: functionRenderer,
  208. });
  209. register({
  210. type: 'moving_average',
  211. addStrategy: addTransformationStrategy,
  212. category: categories.Transformations,
  213. params: [{ name: "window", type: "int", options: [5, 10, 20, 30, 40]}],
  214. defaultParams: [10],
  215. renderer: functionRenderer,
  216. });
  217. register({
  218. type: 'cumulative_sum',
  219. addStrategy: addTransformationStrategy,
  220. category: categories.Transformations,
  221. params: [],
  222. defaultParams: [],
  223. renderer: functionRenderer,
  224. });
  225. register({
  226. type: 'stddev',
  227. addStrategy: addTransformationStrategy,
  228. category: categories.Transformations,
  229. params: [],
  230. defaultParams: [],
  231. renderer: functionRenderer,
  232. });
  233. register({
  234. type: 'time',
  235. category: groupByTimeFunctions,
  236. params: [{ name: "interval", type: "time", options: ['$__interval', '1s', '10s', '1m', '5m', '10m', '15m', '1h']}],
  237. defaultParams: ['$__interval'],
  238. renderer: functionRenderer,
  239. });
  240. register({
  241. type: 'fill',
  242. category: groupByTimeFunctions,
  243. params: [{ name: "fill", type: "string", options: ['none', 'null', '0', 'previous', 'linear'] }],
  244. defaultParams: ['null'],
  245. renderer: functionRenderer,
  246. });
  247. register({
  248. type: 'elapsed',
  249. addStrategy: addTransformationStrategy,
  250. category: categories.Transformations,
  251. params: [{ name: "duration", type: "interval", options: ['1s', '10s', '1m', '5m', '10m', '15m', '1h']}],
  252. defaultParams: ['10s'],
  253. renderer: functionRenderer,
  254. });
  255. // predictions
  256. register({
  257. type: 'holt_winters',
  258. addStrategy: addTransformationStrategy,
  259. category: categories.Predictors,
  260. params: [{ name: "number", type: "int", options: [5, 10, 20, 30, 40]}, { name: "season", type: "int", options: [0, 1, 2, 5, 10]}],
  261. defaultParams: [10, 2],
  262. renderer: functionRenderer,
  263. });
  264. register({
  265. type: 'holt_winters_with_fit',
  266. addStrategy: addTransformationStrategy,
  267. category: categories.Predictors,
  268. params: [{ name: "number", type: "int", options: [5, 10, 20, 30, 40]}, { name: "season", type: "int", options: [0, 1, 2, 5, 10]}],
  269. defaultParams: [10, 2],
  270. renderer: functionRenderer,
  271. });
  272. // Selectors
  273. register({
  274. type: 'bottom',
  275. addStrategy: replaceAggregationAddStrategy,
  276. category: categories.Selectors,
  277. params: [{name: 'count', type: 'int'}],
  278. defaultParams: [3],
  279. renderer: functionRenderer,
  280. });
  281. register({
  282. type: 'first',
  283. addStrategy: replaceAggregationAddStrategy,
  284. category: categories.Selectors,
  285. params: [],
  286. defaultParams: [],
  287. renderer: functionRenderer,
  288. });
  289. register({
  290. type: 'last',
  291. addStrategy: replaceAggregationAddStrategy,
  292. category: categories.Selectors,
  293. params: [],
  294. defaultParams: [],
  295. renderer: functionRenderer,
  296. });
  297. register({
  298. type: 'max',
  299. addStrategy: replaceAggregationAddStrategy,
  300. category: categories.Selectors,
  301. params: [],
  302. defaultParams: [],
  303. renderer: functionRenderer,
  304. });
  305. register({
  306. type: 'min',
  307. addStrategy: replaceAggregationAddStrategy,
  308. category: categories.Selectors,
  309. params: [],
  310. defaultParams: [],
  311. renderer: functionRenderer,
  312. });
  313. register({
  314. type: 'percentile',
  315. addStrategy: replaceAggregationAddStrategy,
  316. category: categories.Selectors,
  317. params: [{name: 'nth', type: 'int'}],
  318. defaultParams: [95],
  319. renderer: functionRenderer,
  320. });
  321. register({
  322. type: 'top',
  323. addStrategy: replaceAggregationAddStrategy,
  324. category: categories.Selectors,
  325. params: [{name: 'count', type: 'int'}],
  326. defaultParams: [3],
  327. renderer: functionRenderer,
  328. });
  329. register({
  330. type: 'tag',
  331. category: groupByTimeFunctions,
  332. params: [{name: 'tag', type: 'string', dynamicLookup: true}],
  333. defaultParams: ['tag'],
  334. renderer: fieldRenderer,
  335. });
  336. register({
  337. type: 'math',
  338. addStrategy: addMathStrategy,
  339. category: categories.Math,
  340. params: [{ name: "expr", type: "string"}],
  341. defaultParams: [' / 100'],
  342. renderer: suffixRenderer,
  343. });
  344. register({
  345. type: 'alias',
  346. addStrategy: addAliasStrategy,
  347. category: categories.Aliasing,
  348. params: [{ name: "name", type: "string", quote: 'double'}],
  349. defaultParams: ['alias'],
  350. renderMode: 'suffix',
  351. renderer: aliasRenderer,
  352. });
  353. export default {
  354. create: createPart,
  355. getCategories: function() {
  356. return categories;
  357. }
  358. };