sql_part.ts 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. import _ from 'lodash';
  2. import { SqlPartDef, SqlPart, functionRenderer, suffixRenderer } from 'app/core/components/sql_part/sql_part';
  3. var index = [];
  4. function createPart(part): any {
  5. var def = index[part.type];
  6. if (!def) {
  7. return null;
  8. }
  9. return new SqlPart(part, def);
  10. }
  11. function register(options: any) {
  12. index[options.type] = new SqlPartDef(options);
  13. }
  14. function aliasRenderer(part, innerExpr) {
  15. return innerExpr + ' AS ' + '"' + part.params[0] + '"';
  16. }
  17. function aggregateRenderer(part, innerExpr) {
  18. return part.params[0] + '(' + innerExpr + ')';
  19. }
  20. function columnRenderer(part, innerExpr) {
  21. return part.params[0];
  22. }
  23. function replaceAggregationAddStrategy(selectParts, partModel) {
  24. var hasAlias = false;
  25. // look for existing aggregation
  26. for (var i = 0; i < selectParts.length; i++) {
  27. var part = selectParts[i];
  28. if (part.def.type === 'aggregate') {
  29. selectParts[i] = partModel;
  30. return;
  31. }
  32. if (part.def.type === 'alias') {
  33. hasAlias = true;
  34. }
  35. }
  36. // add alias if none exists yet
  37. if (!hasAlias) {
  38. var aliasModel = createPart({ type: 'alias', params: [selectParts[0].params[0]] });
  39. selectParts.push(aliasModel);
  40. }
  41. selectParts.splice(1, 0, partModel);
  42. }
  43. function replaceSpecialAddStrategy(selectParts, partModel) {
  44. var hasAlias = false;
  45. // look for existing aggregation
  46. for (var i = 0; i < selectParts.length; i++) {
  47. var part = selectParts[i];
  48. if (part.def.type === 'special') {
  49. selectParts[i] = partModel;
  50. return;
  51. }
  52. if (part.def.type === 'alias') {
  53. hasAlias = true;
  54. }
  55. }
  56. // add alias if none exists yet
  57. if (!hasAlias) {
  58. var aliasModel = createPart({ type: 'alias', params: [selectParts[0].params[0]] });
  59. selectParts.push(aliasModel);
  60. }
  61. selectParts.splice(1, 0, partModel);
  62. }
  63. function addMathStrategy(selectParts, partModel) {
  64. var partCount = selectParts.length;
  65. if (partCount > 0) {
  66. // if last is math, replace it
  67. if (selectParts[partCount - 1].def.type === 'math') {
  68. selectParts[partCount - 1] = partModel;
  69. return;
  70. }
  71. // if next to last is math, replace it
  72. if (partCount > 1 && selectParts[partCount - 2].def.type === 'math') {
  73. selectParts[partCount - 2] = partModel;
  74. return;
  75. } else if (selectParts[partCount - 1].def.type === 'alias') {
  76. // if last is alias add it before
  77. selectParts.splice(partCount - 1, 0, partModel);
  78. return;
  79. }
  80. }
  81. selectParts.push(partModel);
  82. }
  83. function addAliasStrategy(selectParts, partModel) {
  84. var partCount = selectParts.length;
  85. if (partCount > 0) {
  86. // if last is alias, replace it
  87. if (selectParts[partCount - 1].def.type === 'alias') {
  88. selectParts[partCount - 1] = partModel;
  89. return;
  90. }
  91. }
  92. selectParts.push(partModel);
  93. }
  94. function addColumnStrategy(selectParts, partModel, query) {
  95. // copy all parts
  96. var parts = _.map(selectParts, function(part: any) {
  97. return createPart({ type: part.def.type, params: _.clone(part.params) });
  98. });
  99. query.selectModels.push(parts);
  100. }
  101. function addExpressionStrategy(selectParts, partModel, query) {
  102. // copy all parts
  103. var parts = _.map(selectParts, function(part: any) {
  104. return createPart({ type: part.def.type, params: _.clone(part.params) });
  105. });
  106. query.selectModels.push(parts);
  107. }
  108. register({
  109. type: 'column',
  110. style: 'label',
  111. addStrategy: addColumnStrategy,
  112. params: [{ type: 'column', dynamicLookup: true }],
  113. defaultParams: ['value'],
  114. renderer: columnRenderer,
  115. });
  116. register({
  117. type: 'expression',
  118. style: 'expression',
  119. label: 'Expr:',
  120. addStrategy: addExpressionStrategy,
  121. params: [
  122. { name: 'left', type: 'string', dynamicLookup: true },
  123. { name: 'op', type: 'string', dynamicLookup: true },
  124. { name: 'right', type: 'string', dynamicLookup: true },
  125. ],
  126. defaultParams: ['value', '=', 'value'],
  127. renderer: columnRenderer,
  128. });
  129. register({
  130. type: 'macro',
  131. style: 'label',
  132. label: 'Macro:',
  133. addStrategy: addExpressionStrategy,
  134. params: [],
  135. defaultParams: [],
  136. renderer: columnRenderer,
  137. });
  138. register({
  139. type: 'aggregate',
  140. style: 'label',
  141. addStrategy: replaceAggregationAddStrategy,
  142. params: [{ name: 'name', type: 'string', dynamicLookup: true }],
  143. defaultParams: ['avg'],
  144. renderer: aggregateRenderer,
  145. });
  146. register({
  147. type: 'math',
  148. style: 'label',
  149. addStrategy: addMathStrategy,
  150. params: [{ name: 'expr', type: 'string' }],
  151. defaultParams: [' / 100'],
  152. renderer: suffixRenderer,
  153. });
  154. register({
  155. type: 'alias',
  156. style: 'label',
  157. addStrategy: addAliasStrategy,
  158. params: [{ name: 'name', type: 'string', quote: 'double' }],
  159. defaultParams: ['alias'],
  160. renderMode: 'suffix',
  161. renderer: aliasRenderer,
  162. });
  163. register({
  164. type: 'time',
  165. style: 'function',
  166. label: 'time',
  167. params: [
  168. {
  169. name: 'interval',
  170. type: 'interval',
  171. options: ['$__interval', '1s', '10s', '1m', '5m', '10m', '15m', '1h'],
  172. },
  173. {
  174. name: 'fill',
  175. type: 'string',
  176. options: ['none', 'NULL', '0'],
  177. },
  178. ],
  179. defaultParams: ['$__interval', 'none'],
  180. renderer: functionRenderer,
  181. });
  182. register({
  183. type: 'special',
  184. style: 'label',
  185. params: [
  186. {
  187. name: 'function',
  188. type: 'string',
  189. options: ['increase', 'rate'],
  190. },
  191. ],
  192. defaultParams: ['increase'],
  193. addStrategy: replaceSpecialAddStrategy,
  194. renderer: aggregateRenderer,
  195. });
  196. export default {
  197. create: createPart,
  198. };