query_part.ts 8.3 KB

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