Build a dynamic query based on requested columns with proper histogram support
(self, params: QueryParams, requested_columns: List[str],
latency_columns: Optional[List[str]] = None)
| 469 | return f.read() |
| 470 | |
| 471 | def build_dynamic_query(self, params: QueryParams, requested_columns: List[str], |
| 472 | latency_columns: Optional[List[str]] = None) -> str: |
| 473 | """Build a dynamic query based on requested columns with proper histogram support""" |
| 474 | # Standardize column names to lowercase |
| 475 | requested_columns = [col.lower() for col in requested_columns] |
| 476 | # Convert requested columns to set for analysis |
| 477 | columns_set = set(requested_columns) |
| 478 | |
| 479 | # Add standard computed columns |
| 480 | columns_set.update(['samples', 'avg_threads']) |
| 481 | |
| 482 | # Add latency columns if provided (standardize to lowercase) |
| 483 | if latency_columns: |
| 484 | columns_set.update([col.lower() for col in latency_columns]) |
| 485 | |
| 486 | # Determine required data sources |
| 487 | required_sources = self._determine_required_sources(columns_set) |
| 488 | |
| 489 | # Check if we need histograms (lowercase comparison) |
| 490 | need_sc_histogram = 'sclat_histogram' in columns_set |
| 491 | need_io_histogram = 'iolat_histogram' in columns_set |
| 492 | |
| 493 | # Time range for the query |
| 494 | low_time = (params.low_time or (datetime.now() - timedelta(hours=1))).isoformat() |
| 495 | high_time = (params.high_time or datetime.now()).isoformat() |
| 496 | |
| 497 | # Start building the query |
| 498 | query_parts = [] |
| 499 | |
| 500 | # Build base CTE with all joins and bucket calculations |
| 501 | base_select = ["samples.*"] |
| 502 | |
| 503 | # Add computed columns that might be needed |
| 504 | computed_column_defs = { |
| 505 | 'filenamesum': "REGEXP_REPLACE(samples.FILENAME, '[0-9]+', '*', 'g') as filenamesum", |
| 506 | 'comm2': """CASE |
| 507 | WHEN samples.COMM LIKE 'ora_p%' |
| 508 | THEN regexp_replace(samples.COMM, '(?:p[0-9a-z]+_)', 'p*_', 'g') |
| 509 | ELSE regexp_replace(samples.COMM, '[0-9]+', '*', 'g') |
| 510 | END as comm2""", |
| 511 | # Stack-related computed columns (these are computed in SELECT, not available in base_samples) |
| 512 | 'KSTACK_CURRENT_FUNC': 'KSTACK_CURRENT_FUNC', |
| 513 | 'USTACK_CURRENT_FUNC': 'USTACK_CURRENT_FUNC' |
| 514 | } |
| 515 | |
| 516 | # Add any computed columns that are requested |
| 517 | for col in requested_columns: |
| 518 | if col in computed_column_defs: |
| 519 | base_select.append(computed_column_defs[col]) |
| 520 | |
| 521 | if 'syscend' in required_sources: |
| 522 | base_select.extend([ |
| 523 | "sc.tid AS sc_tid", |
| 524 | "sc.duration_ns AS sc_duration_ns", |
| 525 | "sc.type AS sc_type" |
| 526 | ]) |
| 527 | if need_sc_histogram: |
| 528 | base_select.append( |
no test coverage detected