|
77 | 77 | serializable. The variable reference is indicated by a ``$`` before |
78 | 78 | the variable name (ex. ``$my_dict_var``). See ``In[6]`` and ``In[7]`` |
79 | 79 | in the Examples section below. |
| 80 | + * ``--engine <engine>`` (Optional[line argument]): |
| 81 | + Set the execution engine, either 'pandas' (default) or 'bigframes' |
| 82 | + (experimental). |
| 83 | + * ``--pyformat`` (Optional[line argument]): |
| 84 | + Warning! Do not use with user-provided values. |
| 85 | + This doesn't escape values. Use --params instead for proper SQL escaping. |
| 86 | + This enables Python string formatting in the query text. |
| 87 | + Useful for values not supported by SQL query params such as table IDs. |
80 | 88 |
|
81 | 89 | * ``<query>`` (required, cell argument): |
82 | 90 | SQL query to run. If the query does not contain any whitespace (aside |
|
122 | 130 | import bigquery_magics._versions_helpers |
123 | 131 | import bigquery_magics.config |
124 | 132 | import bigquery_magics.graph_server as graph_server |
125 | | -import bigquery_magics.line_arg_parser.exceptions |
| 133 | +import bigquery_magics.pyformat |
126 | 134 | import bigquery_magics.version |
127 | 135 |
|
128 | 136 | try: |
@@ -401,6 +409,17 @@ def _create_dataset_if_necessary(client, dataset_id): |
401 | 409 | default=False, |
402 | 410 | help=("Visualizes the query results as a graph"), |
403 | 411 | ) |
| 412 | +@magic_arguments.argument( |
| 413 | + "--pyformat", |
| 414 | + action="store_true", |
| 415 | + default=False, |
| 416 | + help=( |
| 417 | + "Warning! Do not use with user-provided values. " |
| 418 | + "This doesn't escape values. Use --params instead for proper SQL escaping. " |
| 419 | + "This enables Python string formatting in the query text. " |
| 420 | + "Useful for values not supported by SQL query params such as table IDs. " |
| 421 | + ), |
| 422 | +) |
404 | 423 | def _cell_magic(line, query): |
405 | 424 | """Underlying function for bigquery cell magic |
406 | 425 |
|
@@ -515,7 +534,6 @@ def _query_with_bigframes(query: str, params: List[Any], args: Any): |
515 | 534 |
|
516 | 535 | def _query_with_pandas(query: str, params: List[Any], args: Any): |
517 | 536 | bq_client, bqstorage_client = _create_clients(args) |
518 | | - |
519 | 537 | try: |
520 | 538 | return _make_bq_query( |
521 | 539 | query, |
@@ -779,26 +797,30 @@ def _make_bq_query( |
779 | 797 |
|
780 | 798 | def _validate_and_resolve_query(query: str, args: Any) -> str: |
781 | 799 | # Check if query is given as a reference to a variable. |
782 | | - if not query.startswith("$"): |
783 | | - return query |
| 800 | + if query.startswith("$"): |
| 801 | + query_var_name = query[1:] |
784 | 802 |
|
785 | | - query_var_name = query[1:] |
| 803 | + if not query_var_name: |
| 804 | + missing_msg = 'Missing query variable name, empty "$" is not allowed.' |
| 805 | + raise NameError(missing_msg) |
786 | 806 |
|
787 | | - if not query_var_name: |
788 | | - missing_msg = 'Missing query variable name, empty "$" is not allowed.' |
789 | | - raise NameError(missing_msg) |
| 807 | + if query_var_name.isidentifier(): |
| 808 | + ip = get_ipython() |
| 809 | + query = ip.user_ns.get(query_var_name, ip) # ip serves as a sentinel |
790 | 810 |
|
791 | | - if query_var_name.isidentifier(): |
| 811 | + if query is ip: |
| 812 | + raise NameError( |
| 813 | + f"Unknown query, variable {query_var_name} does not exist." |
| 814 | + ) |
| 815 | + elif not isinstance(query, (str, bytes)): |
| 816 | + raise TypeError( |
| 817 | + f"Query variable {query_var_name} must be a string " |
| 818 | + "or a bytes-like value." |
| 819 | + ) |
| 820 | + |
| 821 | + if args.pyformat: |
792 | 822 | ip = get_ipython() |
793 | | - query = ip.user_ns.get(query_var_name, ip) # ip serves as a sentinel |
794 | | - |
795 | | - if query is ip: |
796 | | - raise NameError(f"Unknown query, variable {query_var_name} does not exist.") |
797 | | - elif not isinstance(query, (str, bytes)): |
798 | | - raise TypeError( |
799 | | - f"Query variable {query_var_name} must be a string " |
800 | | - "or a bytes-like value." |
801 | | - ) |
| 823 | + query = bigquery_magics.pyformat.pyformat(query, ip.user_ns) |
802 | 824 | return query |
803 | 825 |
|
804 | 826 |
|
|
0 commit comments