query_builder.ts 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. import { reduce } from 'lodash';
  2. import kbn from 'app/core/utils/kbn';
  3. function renderTagCondition(tag: { operator: any; value: string; condition: any; key: string }, index: number) {
  4. // FIXME: merge this function with influx_query_model/renderTagCondition
  5. let str = '';
  6. let operator = tag.operator;
  7. let value = tag.value;
  8. if (index > 0) {
  9. str = (tag.condition || 'AND') + ' ';
  10. }
  11. if (!operator) {
  12. if (/^\/.*\/$/.test(tag.value)) {
  13. operator = '=~';
  14. } else {
  15. operator = '=';
  16. }
  17. }
  18. // quote value unless regex or number, or if empty-string
  19. if (value === '' || (operator !== '=~' && operator !== '!~' && isNaN(+value))) {
  20. value = "'" + value.replace(/\\/g, '\\\\').replace(/\'/g, "\\'") + "'";
  21. }
  22. return str + '"' + tag.key + '" ' + operator + ' ' + value;
  23. }
  24. export class InfluxQueryBuilder {
  25. constructor(private target: { measurement: any; tags: any; policy?: any }, private database?: string) {}
  26. buildExploreQuery(type: string, withKey?: string, withMeasurementFilter?: string): string {
  27. let query = '';
  28. let measurement;
  29. let policy;
  30. if (type === 'TAG_KEYS') {
  31. query = 'SHOW TAG KEYS';
  32. measurement = this.target.measurement;
  33. policy = this.target.policy;
  34. } else if (type === 'TAG_VALUES') {
  35. query = 'SHOW TAG VALUES';
  36. measurement = this.target.measurement;
  37. policy = this.target.policy;
  38. } else if (type === 'MEASUREMENTS') {
  39. query = 'SHOW MEASUREMENTS';
  40. if (withMeasurementFilter) {
  41. // we do a case-insensitive regex-based lookup
  42. query += ' WITH MEASUREMENT =~ /(?i)' + kbn.regexEscape(withMeasurementFilter) + '/';
  43. }
  44. } else if (type === 'FIELDS') {
  45. measurement = this.target.measurement;
  46. policy = this.target.policy;
  47. if (!measurement.match('^/.*/')) {
  48. measurement = '"' + measurement + '"';
  49. if (policy && policy !== 'default') {
  50. policy = '"' + policy + '"';
  51. measurement = policy + '.' + measurement;
  52. }
  53. }
  54. return 'SHOW FIELD KEYS FROM ' + measurement;
  55. } else if (type === 'RETENTION POLICIES') {
  56. query = 'SHOW RETENTION POLICIES on "' + this.database + '"';
  57. return query;
  58. }
  59. if (measurement) {
  60. if (!measurement.match('^/.*/') && !measurement.match(/^merge\(.*\)/)) {
  61. measurement = '"' + measurement + '"';
  62. }
  63. if (policy && policy !== 'default') {
  64. policy = '"' + policy + '"';
  65. measurement = policy + '.' + measurement;
  66. }
  67. query += ' FROM ' + measurement;
  68. }
  69. if (withKey) {
  70. query += ' WITH KEY = "' + withKey + '"';
  71. }
  72. if (this.target.tags && this.target.tags.length > 0) {
  73. const whereConditions = reduce(
  74. this.target.tags,
  75. (memo, tag) => {
  76. // do not add a condition for the key we want to explore for
  77. if (tag.key === withKey) {
  78. return memo;
  79. }
  80. // value operators not supported in these types of queries
  81. if (tag.operator === '>' || tag.operator === '<') {
  82. return memo;
  83. }
  84. memo.push(renderTagCondition(tag, memo.length));
  85. return memo;
  86. },
  87. [] as string[]
  88. );
  89. if (whereConditions.length > 0) {
  90. query += ' WHERE ' + whereConditions.join(' ');
  91. }
  92. }
  93. if (type === 'MEASUREMENTS') {
  94. query += ' LIMIT 100';
  95. //Solve issue #2524 by limiting the number of measurements returned
  96. //LIMIT must be after WITH MEASUREMENT and WHERE clauses
  97. //This also could be used for TAG KEYS and TAG VALUES, if desired
  98. }
  99. return query;
  100. }
  101. }