Executes a single SQL statement
( # pylint: disable=too-many-arguments,too-many-locals,too-many-statements
sql_statement: str,
query: Query,
user_name: Optional[str],
session: Session,
cursor: Any,
log_params: Optional[Dict[str, Any]],
apply_ctas: bool = False,
)
| 176 | |
| 177 | |
| 178 | def execute_sql_statement( # pylint: disable=too-many-arguments,too-many-locals,too-many-statements |
| 179 | sql_statement: str, |
| 180 | query: Query, |
| 181 | user_name: Optional[str], |
| 182 | session: Session, |
| 183 | cursor: Any, |
| 184 | log_params: Optional[Dict[str, Any]], |
| 185 | apply_ctas: bool = False, |
| 186 | ) -> SupersetResultSet: |
| 187 | """Executes a single SQL statement""" |
| 188 | database = query.database |
| 189 | db_engine_spec = database.db_engine_spec |
| 190 | parsed_query = ParsedQuery(sql_statement) |
| 191 | sql = parsed_query.stripped() |
| 192 | # This is a test to see if the query is being |
| 193 | # limited by either the dropdown or the sql. |
| 194 | # We are testing to see if more rows exist than the limit. |
| 195 | increased_limit = None if query.limit is None else query.limit + 1 |
| 196 | |
| 197 | if not db_engine_spec.is_readonly_query(parsed_query) and not database.allow_dml: |
| 198 | raise SupersetErrorException( |
| 199 | SupersetError( |
| 200 | message=__("Only SELECT statements are allowed against this database."), |
| 201 | error_type=SupersetErrorType.DML_NOT_ALLOWED_ERROR, |
| 202 | level=ErrorLevel.ERROR, |
| 203 | ) |
| 204 | ) |
| 205 | if apply_ctas: |
| 206 | if not query.tmp_table_name: |
| 207 | start_dttm = datetime.fromtimestamp(query.start_time) |
| 208 | query.tmp_table_name = "tmp_{}_table_{}".format( |
| 209 | query.user_id, start_dttm.strftime("%Y_%m_%d_%H_%M_%S") |
| 210 | ) |
| 211 | sql = parsed_query.as_create_table( |
| 212 | query.tmp_table_name, |
| 213 | schema_name=query.tmp_schema_name, |
| 214 | method=query.ctas_method, |
| 215 | ) |
| 216 | query.select_as_cta_used = True |
| 217 | |
| 218 | # Do not apply limit to the CTA queries when SQLLAB_CTAS_NO_LIMIT is set to true |
| 219 | if db_engine_spec.is_select_query(parsed_query) and not ( |
| 220 | query.select_as_cta_used and SQLLAB_CTAS_NO_LIMIT |
| 221 | ): |
| 222 | if SQL_MAX_ROW and (not query.limit or query.limit > SQL_MAX_ROW): |
| 223 | query.limit = SQL_MAX_ROW |
| 224 | if query.limit: |
| 225 | # We are fetching one more than the requested limit in order |
| 226 | # to test whether there are more rows than the limit. |
| 227 | # Later, the extra row will be dropped before sending |
| 228 | # the results back to the user. |
| 229 | sql = database.apply_limit_to_sql(sql, increased_limit, force=True) |
| 230 | |
| 231 | # Hook to allow environment-specific mutation (usually comments) to the SQL |
| 232 | sql = SQL_QUERY_MUTATOR(sql, user_name, security_manager, database) |
| 233 | try: |
| 234 | query.executed_sql = sql |
| 235 | if log_query: |
no test coverage detected