|
73 | 73 | _KERNEL_MANAGED_HEADERS = frozenset({"authorization", "x-databricks-org-id"}) |
74 | 74 |
|
75 | 75 |
|
| 76 | +def _strip_leading_sql_comments(sql: str) -> str: |
| 77 | + """Skip SQL comments so unsupported transfers cannot appear successful.""" |
| 78 | + i = 0 |
| 79 | + n = len(sql) |
| 80 | + while i < n: |
| 81 | + if sql[i].isspace(): |
| 82 | + i += 1 |
| 83 | + elif sql.startswith("--", i): |
| 84 | + nl = sql.find("\n", i) |
| 85 | + i = n if nl == -1 else nl + 1 |
| 86 | + elif sql.startswith("/*", i): |
| 87 | + close = sql.find("*/", i + 2) |
| 88 | + i = n if close == -1 else close + 2 |
| 89 | + else: |
| 90 | + break |
| 91 | + return sql[i:] |
| 92 | + |
| 93 | + |
| 94 | +def _is_staging_statement(operation: str) -> bool: |
| 95 | + stripped = _strip_leading_sql_comments(operation) |
| 96 | + verb = stripped.split(None, 1)[0].upper() if stripped.strip() else "" |
| 97 | + return verb in ("PUT", "GET", "REMOVE") |
| 98 | + |
| 99 | + |
76 | 100 | def _is_not_found(exc: BaseException) -> bool: |
77 | 101 | """True iff ``exc`` is a kernel ``NotFound`` error (HTTP 404 / |
78 | 102 | ``STATEMENT_NOT_FOUND``). |
@@ -530,7 +554,14 @@ def execute_command( |
530 | 554 | allowed_paths = cursor.connection.staging_allowed_local_path |
531 | 555 | if isinstance(allowed_paths, str): |
532 | 556 | allowed_paths = [allowed_paths] |
533 | | - stmt.set_staging_allowed_local_paths(allowed_paths or []) |
| 557 | + set_paths = getattr(stmt, "set_staging_allowed_local_paths", None) |
| 558 | + if callable(set_paths): |
| 559 | + set_paths(allowed_paths or []) |
| 560 | + elif _is_staging_statement(operation): |
| 561 | + raise NotSupportedError( |
| 562 | + "Volume transfers require a databricks-sql-kernel wheel " |
| 563 | + "with staging_allowed_local_paths support." |
| 564 | + ) |
534 | 565 | stmt.set_row_limit(row_limit) |
535 | 566 | if query_tags: |
536 | 567 | # Per-statement query tags. The kernel serialises the |
|
0 commit comments