Skip to content
This repository was archived by the owner on Apr 1, 2026. It is now read-only.

Commit dcac8e0

Browse files
Merge remote-tracking branch 'github/main' into fix_cf_reuse_configs
2 parents f713798 + e8c4603 commit dcac8e0

File tree

24 files changed

+523
-390
lines changed

24 files changed

+523
-390
lines changed

bigframes/bigquery/_operations/table.py

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@
1919
import google.cloud.bigquery
2020
import pandas as pd
2121

22+
import bigframes.core.compile.sqlglot.sql as sg_sql
2223
import bigframes.core.logging.log_adapter as log_adapter
23-
import bigframes.core.sql.table
2424
import bigframes.session
2525

2626

@@ -80,14 +80,16 @@ def create_external_table(
8080
"""
8181
import bigframes.pandas as bpd
8282

83-
sql = bigframes.core.sql.table.create_external_table_ddl(
84-
table_name=table_name,
85-
replace=replace,
86-
if_not_exists=if_not_exists,
87-
columns=columns,
88-
partition_columns=partition_columns,
89-
connection_name=connection_name,
90-
options=options,
83+
sql = sg_sql.to_sql(
84+
sg_sql.create_external_table(
85+
table_name=table_name,
86+
replace=replace,
87+
if_not_exists=if_not_exists,
88+
columns=columns,
89+
partition_columns=partition_columns,
90+
connection_name=connection_name,
91+
options=options,
92+
)
9193
)
9294

9395
if session is None:

bigframes/core/blocks.py

Lines changed: 49 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1822,9 +1822,9 @@ def melt(
18221822
Arguments correspond to pandas.melt arguments.
18231823
"""
18241824
# TODO: Implement col_level and ignore_index
1825-
value_labels: pd.Index = pd.Index(
1826-
[self.col_id_to_label[col_id] for col_id in value_vars]
1827-
)
1825+
value_labels: pd.Index = self.column_labels[
1826+
[self.value_columns.index(col_id) for col_id in value_vars]
1827+
]
18281828
id_labels = [self.col_id_to_label[col_id] for col_id in id_vars]
18291829

18301830
unpivot_expr, (var_col_ids, unpivot_out, passthrough_cols) = unpivot(
@@ -3417,6 +3417,7 @@ def unpivot(
34173417
joined_array, (labels_mapping, column_mapping) = labels_array.relational_join(
34183418
array_value, type="cross"
34193419
)
3420+
34203421
new_passthrough_cols = [column_mapping[col] for col in passthrough_columns]
34213422
# Last column is offsets
34223423
index_col_ids = [labels_mapping[col] for col in labels_array.column_ids[:-1]]
@@ -3426,20 +3427,24 @@ def unpivot(
34263427
unpivot_exprs: List[ex.Expression] = []
34273428
# Supports producing multiple stacked ouput columns for stacking only part of hierarchical index
34283429
for input_ids in unpivot_columns:
3429-
# row explode offset used to choose the input column
3430-
# we use offset instead of label as labels are not necessarily unique
3431-
cases = itertools.chain(
3432-
*(
3433-
(
3434-
ops.eq_op.as_expr(explode_offsets_id, ex.const(i)),
3435-
ex.deref(column_mapping[id_or_null])
3436-
if (id_or_null is not None)
3437-
else ex.const(None),
3430+
col_expr: ex.Expression
3431+
if not input_ids:
3432+
col_expr = ex.const(None, dtype=bigframes.dtypes.INT_DTYPE)
3433+
else:
3434+
# row explode offset used to choose the input column
3435+
# we use offset instead of label as labels are not necessarily unique
3436+
cases = itertools.chain(
3437+
*(
3438+
(
3439+
ops.eq_op.as_expr(explode_offsets_id, ex.const(i)),
3440+
ex.deref(column_mapping[id_or_null])
3441+
if (id_or_null is not None)
3442+
else ex.const(None),
3443+
)
3444+
for i, id_or_null in enumerate(input_ids)
34383445
)
3439-
for i, id_or_null in enumerate(input_ids)
34403446
)
3441-
)
3442-
col_expr = ops.case_when_op.as_expr(*cases)
3447+
col_expr = ops.case_when_op.as_expr(*cases)
34433448
unpivot_exprs.append(col_expr)
34443449

34453450
joined_array, unpivot_col_ids = joined_array.compute_values(unpivot_exprs)
@@ -3457,19 +3462,43 @@ def _pd_index_to_array_value(
34573462
Create an ArrayValue from a list of label tuples.
34583463
The last column will be row offsets.
34593464
"""
3465+
id_gen = bigframes.core.identifiers.standard_id_strings()
3466+
col_ids = [next(id_gen) for _ in range(index.nlevels)]
3467+
offset_id = next(id_gen)
3468+
34603469
rows = []
34613470
labels_as_tuples = utils.index_as_tuples(index)
34623471
for row_offset in range(len(index)):
3463-
id_gen = bigframes.core.identifiers.standard_id_strings()
34643472
row_label = labels_as_tuples[row_offset]
34653473
row_label = (row_label,) if not isinstance(row_label, tuple) else row_label
34663474
row = {}
3467-
for label_part, id in zip(row_label, id_gen):
3468-
row[id] = label_part if pd.notnull(label_part) else None
3469-
row[next(id_gen)] = row_offset
3475+
for label_part, col_id in zip(row_label, col_ids):
3476+
row[col_id] = label_part if pd.notnull(label_part) else None
3477+
row[offset_id] = row_offset
34703478
rows.append(row)
34713479

3472-
return core.ArrayValue.from_pyarrow(pa.Table.from_pylist(rows), session=session)
3480+
if not rows:
3481+
dtypes_list = getattr(index, "dtypes", None)
3482+
if dtypes_list is None:
3483+
dtypes_list = (
3484+
[index.dtype] if hasattr(index, "dtype") else [pd.Float64Dtype()]
3485+
)
3486+
3487+
fields = []
3488+
for col_id, dtype in zip(col_ids, dtypes_list):
3489+
try:
3490+
pa_type = bigframes.dtypes.bigframes_dtype_to_arrow_dtype(dtype)
3491+
except Exception:
3492+
pa_type = pa.string()
3493+
fields.append(pa.field(col_id, pa_type))
3494+
fields.append(pa.field(offset_id, pa.int64()))
3495+
schema = pa.schema(fields)
3496+
pt = pa.Table.from_pylist([], schema=schema)
3497+
else:
3498+
pt = pa.Table.from_pylist(rows)
3499+
pt = pt.rename_columns([*col_ids, offset_id])
3500+
3501+
return core.ArrayValue.from_pyarrow(pt, session=session)
34733502

34743503

34753504
def _resolve_index_col(

bigframes/core/compile/sqlglot/sql/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
table,
2222
to_sql,
2323
)
24-
from bigframes.core.compile.sqlglot.sql.ddl import load_data
24+
from bigframes.core.compile.sqlglot.sql.ddl import create_external_table, load_data
2525
from bigframes.core.compile.sqlglot.sql.dml import insert, replace
2626

2727
__all__ = [
@@ -33,6 +33,7 @@
3333
"table",
3434
"to_sql",
3535
# From ddl.py
36+
"create_external_table",
3637
"load_data",
3738
# From dml.py
3839
"insert",

0 commit comments

Comments
 (0)