Execute query and return results
(self, query: str, params: QueryParams = None,
debug: bool = False, debug_profile: bool = False)
| 125 | return self.prepare_dynamic_query(params, latency_columns) |
| 126 | |
| 127 | def execute(self, query: str, params: QueryParams = None, |
| 128 | debug: bool = False, debug_profile: bool = False) -> QueryResult: |
| 129 | """Execute query and return results""" |
| 130 | if debug or debug_profile: |
| 131 | self.logger.debug("\n" + "="*80) |
| 132 | self.logger.debug("DEBUG SQL: About to execute the following query:") |
| 133 | self.logger.debug("="*80) |
| 134 | self.logger.debug(query) |
| 135 | self.logger.debug("="*80) |
| 136 | |
| 137 | conn = self.data_source.connect() |
| 138 | |
| 139 | # Enable profiling if requested |
| 140 | # When debug logging is enabled, capture a human-readable plan/profile tree |
| 141 | # Use DuckDB's query profiling facilities instead of EXPLAIN-after |
| 142 | profile_enabled = False |
| 143 | profile_mode = None |
| 144 | profile_file: Optional[Path] = None |
| 145 | if debug or debug_profile: |
| 146 | # Try to enable profiling; prefer human-readable tree, fallback to standard |
| 147 | try: |
| 148 | conn.execute("PRAGMA disable_profiling") |
| 149 | # Choose profiling mode based on configuration, with safe fallbacks |
| 150 | desired = (self.duckdb_profiling_mode or 'standard').lower() |
| 151 | attempted = [] |
| 152 | for mode in [desired, 'standard', 'query_tree']: |
| 153 | if mode in attempted: |
| 154 | continue |
| 155 | attempted.append(mode) |
| 156 | try: |
| 157 | conn.execute(f"PRAGMA profiling_mode='{mode}'") |
| 158 | profile_mode = mode |
| 159 | break |
| 160 | except Exception: |
| 161 | continue |
| 162 | if not profile_mode: |
| 163 | raise RuntimeError("Could not set DuckDB profiling_mode") |
| 164 | # Direct DuckDB to write the profile to a temp file we can read |
| 165 | try: |
| 166 | profile_file = Path.cwd() / f".duckdb_profile_{int(time.time()*1000)}.txt" |
| 167 | conn.execute(f"PRAGMA profiling_output='{str(profile_file)}'") |
| 168 | except Exception: |
| 169 | profile_file = None |
| 170 | conn.execute("PRAGMA enable_profiling") |
| 171 | profile_enabled = True |
| 172 | except Exception: |
| 173 | profile_enabled = False |
| 174 | |
| 175 | start_time = time.time() |
| 176 | |
| 177 | try: |
| 178 | result = conn.execute(query) |
| 179 | columns = [desc[0] for desc in result.description] |
| 180 | rows = result.fetchall() |
| 181 | |
| 182 | # Fetch and log the plan/profile tree from the just-executed query |
| 183 | if profile_enabled and debug: |
| 184 | try: |
no test coverage detected