Skip to content

bug(bigquery): con.sql in interactive mode fails when use CREATE TEMPORARY FUNCTION #11429

@yama-yeah

Description

@yama-yeah

What happened?

The use of CREATE TEMPORARY FUNCTION causes ibis to malfunction.

minimum example:

subq=conn.sql(f"""CREATE TEMPORARY FUNCTION JUDGE_DAY() AS (DATE('2024-12-20'));
SELECT DISTINCT CALDAY
      FROM UNNEST(GENERATE_DATE_ARRAY(JUDGE_DAY(), CURRENT_DATE(), INTERVAL 1 WEEK)) AS CALDAY""")
subq.execute()

What version of ibis are you using?

10.6.0

What backend(s) are you using, if any?

BigQuery

Relevant log output

File /opt/conda/lib/python3.10/site-packages/ibis/expr/types/core.py:423, in Expr.execute(self, limit, params, **kwargs)
    369 def execute(
    370     self,
    371     *,
   (...)
    374     **kwargs: Any,
    375 ) -> pd.DataFrame | pd.Series | Any:
    376     """Execute an expression against its backend if one exists.
    377 
    378     Parameters
   (...)
    421     [`Value.to_pandas()`](./expression-generic.qmd#ibis.expr.types.generic.Value.to_pandas)
    422     """
--> 423     return self._find_backend(use_default=True).execute(
    424         self, limit=limit, params=params, **kwargs
    425     )

File /opt/conda/lib/python3.10/site-packages/ibis/backends/bigquery/__init__.py:982, in Backend.execute(self, expr, params, limit, query_job_config, **kwargs)
    980 table_expr = expr.as_table()
    981 schema = table_expr.schema() - ibis.schema({"_TABLE_SUFFIX": "string"})
--> 982 query = self._to_query(
    983     table_expr,
    984     params=params,
    985     limit=limit,
    986     query_job_config=query_job_config,
    987     **kwargs,
    988 )
    989 df = query.to_arrow(
    990     progress_bar_type=None, bqstorage_client=self.storage_client
    991 ).to_pandas(timestamp_as_object=True)
    992 # Drop _TABLE_SUFFIX if present in the results, then rename columns

File /opt/conda/lib/python3.10/site-packages/ibis/backends/bigquery/__init__.py:876, in Backend._to_query(self, table_expr, params, limit, query_job_config, **kwargs)
    866 def _to_query(
    867     self,
    868     table_expr: ir.Table,
   (...)
    873     **kwargs: Any,
    874 ) -> RowIterator:
    875     self._run_pre_execute_hooks(table_expr)
--> 876     sql = self.compile(table_expr, limit=limit, params=params, **kwargs)
    877     self._log(sql)
    879     return self.raw_sql(
    880         sql,
    881         params=params,
    882         query_job_config=query_job_config,
    883     )

File /opt/conda/lib/python3.10/site-packages/ibis/backends/bigquery/__init__.py:821, in Backend.compile(self, expr, limit, params, pretty, **kwargs)
    819 session_dataset_id = getattr(session_dataset, "dataset_id", None)
    820 session_project = getattr(session_dataset, "project", None)
--> 821 query = self.compiler.to_sqlglot(
    822     expr,
    823     limit=limit,
    824     params=params,
    825     session_dataset_id=session_dataset_id,
    826     session_project=session_project,
    827     **kwargs,
    828 )
    829 queries = query if isinstance(query, list) else [query]
    830 sql = ";\n".join(query.sql(self.dialect, pretty=pretty) for query in queries)

File /opt/conda/lib/python3.10/site-packages/ibis/backends/sql/compilers/bigquery/__init__.py:239, in BigQueryCompiler.to_sqlglot(self, expr, limit, params, session_dataset_id, session_project)
    207 def to_sqlglot(
    208     self,
    209     expr: ir.Expr,
   (...)
    214     session_project: str | None = None,
    215 ) -> Any:
    216     """Compile an Ibis expression.
    217 
    218     Parameters
   (...)
    237 
    238     """
--> 239     sql = super().to_sqlglot(expr, limit=limit, params=params)
    241     table_expr = expr.as_table()
    243     memtable_names = frozenset(
    244         op.name for op in table_expr.op().find(ops.InMemoryTable)
    245     )

File /opt/conda/lib/python3.10/site-packages/ibis/backends/sql/compilers/base.py:597, in SQLGlotCompiler.to_sqlglot(self, expr, limit, params)
    594 if params is None:
    595     params = {}
--> 597 sql = self.translate(table_expr.op(), params=params)
    598 assert not isinstance(sql, sge.Subquery)
    600 if isinstance(sql, sge.Table):

File /opt/conda/lib/python3.10/site-packages/ibis/backends/sql/compilers/base.py:665, in SQLGlotCompiler.translate(self, op, params)
    662             return result.as_(alias, quoted=self.quoted)
    664 # apply translate rules in topological order
--> 665 results = op.map(fn)
    667 # get the root node as a sqlglot select statement
    668 out = results[op]

File /opt/conda/lib/python3.10/site-packages/ibis/common/graph.py:305, in Node.map(self, fn, filter)
    299 for node in graph:
    300     # minor optimization to directly recurse into the children
    301     kwargs = {
    302         k: _recursive_lookup(v, results)
    303         for k, v in zip(node.__argnames__, node.__args__)
    304     }
--> 305     results[node] = fn(node, results, **kwargs)
    307 return results

File /opt/conda/lib/python3.10/site-packages/ibis/backends/sql/compilers/base.py:645, in SQLGlotCompiler.translate.<locals>.fn(node, __unused__, **kwargs)
    644 def fn(node, __unused__, **kwargs):
--> 645     result = self.visit_node(node, **kwargs)
    647     # if it's not a relation then we don't need to do anything special
    648     if node is op or not isinstance(node, ops.Relation):

File /opt/conda/lib/python3.10/site-packages/ibis/backends/sql/compilers/base.py:691, in SQLGlotCompiler.visit_node(self, op, **kwargs)
    689 method = getattr(self, f"visit_{type(op).__name__}", None)
    690 if method is not None:
--> 691     return method(op, **kwargs)
    692 else:
    693     raise com.OperationNotDefinedError(
    694         f"No translation rule for {type(op).__name__}"
    695     )

File /opt/conda/lib/python3.10/site-packages/ibis/backends/sql/compilers/base.py:1541, in SQLGlotCompiler.visit_SQLQueryResult(self, op, query, schema, source)
   1540 def visit_SQLQueryResult(self, op, *, query, schema, source):
-> 1541     return sg.parse_one(query, dialect=self.dialect).subquery(copy=False)

AttributeError: 'Create' object has no attribute 'subquery'

Code of Conduct

  • I agree to follow this project's Code of Conduct

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugIncorrect behavior inside of ibis

    Type

    No type

    Projects

    Status

    backlog

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions