query_part.ts 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447
  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 (
  61. part.def.category === categories.Math ||
  62. part.def.category === categories.Aliasing
  63. ) {
  64. break;
  65. }
  66. }
  67. selectParts.splice(i, 0, partModel);
  68. }
  69. function addMathStrategy(selectParts, partModel) {
  70. var partCount = selectParts.length;
  71. if (partCount > 0) {
  72. // if last is math, replace it
  73. if (selectParts[partCount - 1].def.type === "math") {
  74. selectParts[partCount - 1] = partModel;
  75. return;
  76. }
  77. // if next to last is math, replace it
  78. if (partCount > 1 && selectParts[partCount - 2].def.type === "math") {
  79. selectParts[partCount - 2] = partModel;
  80. return;
  81. } else if (selectParts[partCount - 1].def.type === "alias") {
  82. // if last is alias add it before
  83. selectParts.splice(partCount - 1, 0, partModel);
  84. return;
  85. }
  86. }
  87. selectParts.push(partModel);
  88. }
  89. function addAliasStrategy(selectParts, partModel) {
  90. var partCount = selectParts.length;
  91. if (partCount > 0) {
  92. // if last is alias, replace it
  93. if (selectParts[partCount - 1].def.type === "alias") {
  94. selectParts[partCount - 1] = partModel;
  95. return;
  96. }
  97. }
  98. selectParts.push(partModel);
  99. }
  100. function addFieldStrategy(selectParts, partModel, query) {
  101. // copy all parts
  102. var parts = _.map(selectParts, function(part: any) {
  103. return createPart({ type: part.def.type, params: _.clone(part.params) });
  104. });
  105. query.selectModels.push(parts);
  106. }
  107. register({
  108. type: "field",
  109. addStrategy: addFieldStrategy,
  110. category: categories.Fields,
  111. params: [{ type: "field", dynamicLookup: true }],
  112. defaultParams: ["value"],
  113. renderer: fieldRenderer
  114. });
  115. // Aggregations
  116. register({
  117. type: "count",
  118. addStrategy: replaceAggregationAddStrategy,
  119. category: categories.Aggregations,
  120. params: [],
  121. defaultParams: [],
  122. renderer: functionRenderer
  123. });
  124. register({
  125. type: "distinct",
  126. addStrategy: replaceAggregationAddStrategy,
  127. category: categories.Aggregations,
  128. params: [],
  129. defaultParams: [],
  130. renderer: functionRenderer
  131. });
  132. register({
  133. type: "integral",
  134. addStrategy: replaceAggregationAddStrategy,
  135. category: categories.Aggregations,
  136. params: [],
  137. defaultParams: [],
  138. renderer: functionRenderer
  139. });
  140. register({
  141. type: "mean",
  142. addStrategy: replaceAggregationAddStrategy,
  143. category: categories.Aggregations,
  144. params: [],
  145. defaultParams: [],
  146. renderer: functionRenderer
  147. });
  148. register({
  149. type: "median",
  150. addStrategy: replaceAggregationAddStrategy,
  151. category: categories.Aggregations,
  152. params: [],
  153. defaultParams: [],
  154. renderer: functionRenderer
  155. });
  156. register({
  157. type: "mode",
  158. addStrategy: replaceAggregationAddStrategy,
  159. category: categories.Aggregations,
  160. params: [],
  161. defaultParams: [],
  162. renderer: functionRenderer
  163. });
  164. register({
  165. type: "sum",
  166. addStrategy: replaceAggregationAddStrategy,
  167. category: categories.Aggregations,
  168. params: [],
  169. defaultParams: [],
  170. renderer: functionRenderer
  171. });
  172. // transformations
  173. register({
  174. type: "derivative",
  175. addStrategy: addTransformationStrategy,
  176. category: categories.Transformations,
  177. params: [
  178. {
  179. name: "duration",
  180. type: "interval",
  181. options: ["1s", "10s", "1m", "5m", "10m", "15m", "1h"]
  182. }
  183. ],
  184. defaultParams: ["10s"],
  185. renderer: functionRenderer
  186. });
  187. register({
  188. type: "spread",
  189. addStrategy: addTransformationStrategy,
  190. category: categories.Transformations,
  191. params: [],
  192. defaultParams: [],
  193. renderer: functionRenderer
  194. });
  195. register({
  196. type: "non_negative_derivative",
  197. addStrategy: addTransformationStrategy,
  198. category: categories.Transformations,
  199. params: [
  200. {
  201. name: "duration",
  202. type: "interval",
  203. options: ["1s", "10s", "1m", "5m", "10m", "15m", "1h"]
  204. }
  205. ],
  206. defaultParams: ["10s"],
  207. renderer: functionRenderer
  208. });
  209. register({
  210. type: "difference",
  211. addStrategy: addTransformationStrategy,
  212. category: categories.Transformations,
  213. params: [],
  214. defaultParams: [],
  215. renderer: functionRenderer
  216. });
  217. register({
  218. type: "non_negative_difference",
  219. addStrategy: addTransformationStrategy,
  220. category: categories.Transformations,
  221. params: [],
  222. defaultParams: [],
  223. renderer: functionRenderer
  224. });
  225. register({
  226. type: "moving_average",
  227. addStrategy: addTransformationStrategy,
  228. category: categories.Transformations,
  229. params: [{ name: "window", type: "int", options: [5, 10, 20, 30, 40] }],
  230. defaultParams: [10],
  231. renderer: functionRenderer
  232. });
  233. register({
  234. type: "cumulative_sum",
  235. addStrategy: addTransformationStrategy,
  236. category: categories.Transformations,
  237. params: [],
  238. defaultParams: [],
  239. renderer: functionRenderer
  240. });
  241. register({
  242. type: "stddev",
  243. addStrategy: addTransformationStrategy,
  244. category: categories.Transformations,
  245. params: [],
  246. defaultParams: [],
  247. renderer: functionRenderer
  248. });
  249. register({
  250. type: "time",
  251. category: groupByTimeFunctions,
  252. params: [
  253. {
  254. name: "interval",
  255. type: "time",
  256. options: ["$__interval", "1s", "10s", "1m", "5m", "10m", "15m", "1h"]
  257. }
  258. ],
  259. defaultParams: ["$__interval"],
  260. renderer: functionRenderer
  261. });
  262. register({
  263. type: "fill",
  264. category: groupByTimeFunctions,
  265. params: [
  266. {
  267. name: "fill",
  268. type: "string",
  269. options: ["none", "null", "0", "previous", "linear"]
  270. }
  271. ],
  272. defaultParams: ["null"],
  273. renderer: functionRenderer
  274. });
  275. register({
  276. type: "elapsed",
  277. addStrategy: addTransformationStrategy,
  278. category: categories.Transformations,
  279. params: [
  280. {
  281. name: "duration",
  282. type: "interval",
  283. options: ["1s", "10s", "1m", "5m", "10m", "15m", "1h"]
  284. }
  285. ],
  286. defaultParams: ["10s"],
  287. renderer: functionRenderer
  288. });
  289. // predictions
  290. register({
  291. type: "holt_winters",
  292. addStrategy: addTransformationStrategy,
  293. category: categories.Predictors,
  294. params: [
  295. { name: "number", type: "int", options: [5, 10, 20, 30, 40] },
  296. { name: "season", type: "int", options: [0, 1, 2, 5, 10] }
  297. ],
  298. defaultParams: [10, 2],
  299. renderer: functionRenderer
  300. });
  301. register({
  302. type: "holt_winters_with_fit",
  303. addStrategy: addTransformationStrategy,
  304. category: categories.Predictors,
  305. params: [
  306. { name: "number", type: "int", options: [5, 10, 20, 30, 40] },
  307. { name: "season", type: "int", options: [0, 1, 2, 5, 10] }
  308. ],
  309. defaultParams: [10, 2],
  310. renderer: functionRenderer
  311. });
  312. // Selectors
  313. register({
  314. type: "bottom",
  315. addStrategy: replaceAggregationAddStrategy,
  316. category: categories.Selectors,
  317. params: [{ name: "count", type: "int" }],
  318. defaultParams: [3],
  319. renderer: functionRenderer
  320. });
  321. register({
  322. type: "first",
  323. addStrategy: replaceAggregationAddStrategy,
  324. category: categories.Selectors,
  325. params: [],
  326. defaultParams: [],
  327. renderer: functionRenderer
  328. });
  329. register({
  330. type: "last",
  331. addStrategy: replaceAggregationAddStrategy,
  332. category: categories.Selectors,
  333. params: [],
  334. defaultParams: [],
  335. renderer: functionRenderer
  336. });
  337. register({
  338. type: "max",
  339. addStrategy: replaceAggregationAddStrategy,
  340. category: categories.Selectors,
  341. params: [],
  342. defaultParams: [],
  343. renderer: functionRenderer
  344. });
  345. register({
  346. type: "min",
  347. addStrategy: replaceAggregationAddStrategy,
  348. category: categories.Selectors,
  349. params: [],
  350. defaultParams: [],
  351. renderer: functionRenderer
  352. });
  353. register({
  354. type: "percentile",
  355. addStrategy: replaceAggregationAddStrategy,
  356. category: categories.Selectors,
  357. params: [{ name: "nth", type: "int" }],
  358. defaultParams: [95],
  359. renderer: functionRenderer
  360. });
  361. register({
  362. type: "top",
  363. addStrategy: replaceAggregationAddStrategy,
  364. category: categories.Selectors,
  365. params: [{ name: "count", type: "int" }],
  366. defaultParams: [3],
  367. renderer: functionRenderer
  368. });
  369. register({
  370. type: "tag",
  371. category: groupByTimeFunctions,
  372. params: [{ name: "tag", type: "string", dynamicLookup: true }],
  373. defaultParams: ["tag"],
  374. renderer: fieldRenderer
  375. });
  376. register({
  377. type: "math",
  378. addStrategy: addMathStrategy,
  379. category: categories.Math,
  380. params: [{ name: "expr", type: "string" }],
  381. defaultParams: [" / 100"],
  382. renderer: suffixRenderer
  383. });
  384. register({
  385. type: "alias",
  386. addStrategy: addAliasStrategy,
  387. category: categories.Aliasing,
  388. params: [{ name: "name", type: "string", quote: "double" }],
  389. defaultParams: ["alias"],
  390. renderMode: "suffix",
  391. renderer: aliasRenderer
  392. });
  393. export default {
  394. create: createPart,
  395. getCategories: function() {
  396. return categories;
  397. }
  398. };