meta_query.ts 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. export class PostgresMetaQuery {
  2. constructor(private target, private queryModel) {}
  3. // quote identifier as literal to use in metadata queries
  4. quoteIdentAsLiteral(value) {
  5. return this.queryModel.quoteLiteral(this.queryModel.unquoteIdentifier(value));
  6. }
  7. findMetricTable() {
  8. // query that returns first table found that has a timestamptz column and a float column
  9. let query = `
  10. SELECT
  11. table_name,
  12. ( SELECT
  13. column_name
  14. FROM information_schema.columns c
  15. WHERE
  16. c.table_schema = t.table_schema AND
  17. c.table_name = t.table_name AND
  18. udt_name IN ('timestamptz','timestamp')
  19. ORDER BY ordinal_position LIMIT 1
  20. ) AS time_column,
  21. ( SELECT
  22. column_name
  23. FROM information_schema.columns c
  24. WHERE
  25. c.table_schema = t.table_schema AND
  26. c.table_name = t.table_name AND
  27. udt_name='float8'
  28. ORDER BY ordinal_position LIMIT 1
  29. ) AS value_column
  30. FROM information_schema.tables t
  31. WHERE
  32. table_schema IN (
  33. SELECT CASE WHEN trim(unnest) = \'"$user"\' THEN user ELSE trim(unnest) END
  34. FROM unnest(string_to_array(current_setting(\'search_path\'),\',\'))
  35. ) AND
  36. EXISTS
  37. ( SELECT 1
  38. FROM information_schema.columns c
  39. WHERE
  40. c.table_schema = t.table_schema AND
  41. c.table_name = t.table_name AND
  42. udt_name IN ('timestamptz','timestamp')
  43. )
  44. ( SELECT 1
  45. FROM information_schema.columns c
  46. WHERE
  47. c.table_schema = t.table_schema AND
  48. c.table_name = t.table_name AND
  49. udt_name='float8'
  50. )
  51. LIMIT 1
  52. ;`;
  53. return query;
  54. }
  55. buildSchemaConstraint() {
  56. let query = `
  57. table_schema IN (
  58. SELECT CASE WHEN trim(unnest) = \'"$user"\' THEN user ELSE trim(unnest) END
  59. FROM unnest(string_to_array(current_setting(\'search_path\'),\',\'))
  60. )`;
  61. return query;
  62. }
  63. buildTableConstraint(table: string) {
  64. let query = '';
  65. // check for schema qualified table
  66. if (table.includes('.')) {
  67. let parts = table.split('.');
  68. query = 'table_schema = ' + this.quoteIdentAsLiteral(parts[0]);
  69. query += ' AND table_name = ' + this.quoteIdentAsLiteral(parts[1]);
  70. return query;
  71. } else {
  72. query = `
  73. table_schema IN (
  74. SELECT CASE WHEN trim(unnest) = \'"$user"\' THEN user ELSE trim(unnest) END
  75. FROM unnest(string_to_array(current_setting(\'search_path\'),\',\'))
  76. )`;
  77. query += ' AND table_name = ' + this.quoteIdentAsLiteral(table);
  78. return query;
  79. }
  80. }
  81. buildTableQuery() {
  82. let query = 'SELECT quote_ident(table_name) FROM information_schema.tables WHERE ';
  83. query += this.buildSchemaConstraint();
  84. query += ' ORDER BY table_name';
  85. return query;
  86. }
  87. buildColumnQuery(type?: string) {
  88. let query = 'SELECT quote_ident(column_name) FROM information_schema.columns WHERE ';
  89. query += this.buildTableConstraint(this.target.table);
  90. switch (type) {
  91. case 'time': {
  92. query +=
  93. " AND data_type IN ('timestamp without time zone','timestamp with time zone','bigint','integer','double precision','real')";
  94. break;
  95. }
  96. case 'metric': {
  97. query += " AND data_type IN ('text','char','varchar')";
  98. break;
  99. }
  100. case 'value': {
  101. query += " AND data_type IN ('bigint','integer','double precision','real')";
  102. query += ' AND column_name <> ' + this.quoteIdentAsLiteral(this.target.timeColumn);
  103. break;
  104. }
  105. case 'group': {
  106. query += " AND data_type IN ('text','char','varchar')";
  107. break;
  108. }
  109. }
  110. query += ' ORDER BY column_name';
  111. return query;
  112. }
  113. buildValueQuery(column: string) {
  114. let query = 'SELECT DISTINCT quote_literal(' + column + ')';
  115. query += ' FROM ' + this.target.table;
  116. query += ' WHERE $__timeFilter(' + this.target.timeColumn + ')';
  117. query += ' ORDER BY 1 LIMIT 100';
  118. return query;
  119. }
  120. buildDatatypeQuery(column: string) {
  121. let query = `
  122. SELECT data_type
  123. FROM information_schema.columns
  124. WHERE
  125. table_schema IN (
  126. SELECT CASE WHEN trim(unnest) = \'"$user"\' THEN user ELSE trim(unnest) END
  127. FROM unnest(string_to_array(current_setting(\'search_path\'),\',\'))
  128. LIMIT 1
  129. )
  130. `;
  131. query += ' AND table_name = ' + this.quoteIdentAsLiteral(this.target.table);
  132. query += ' AND column_name = ' + this.quoteIdentAsLiteral(column);
  133. return query;
  134. }
  135. buildAggregateQuery() {
  136. let query = 'SELECT DISTINCT proname FROM pg_aggregate ';
  137. query += 'INNER JOIN pg_proc ON pg_aggregate.aggfnoid = pg_proc.oid ';
  138. query += 'INNER JOIN pg_type ON pg_type.oid=pg_proc.prorettype ';
  139. query += "WHERE pronargs=1 AND typname IN ('float8') AND aggkind='n' ORDER BY 1";
  140. return query;
  141. }
  142. }