Repository: ibis-project/ibis

Issue:
bug: count() has varying column naming behavior
### What happened?

per upcoming release changelog:

* **api:** `Table.count()` is no longer automatically named `"count"`. Use `Table.count().name("count")` to achieve the previous behavior.

however take a simple example:

```python
[ins] In [1]: import ibis

[ins] In [2]: ibis.options.interactive = True

[ins] In [3]: t = ibis.examples.penguins.fetch()

[ins] In [4]: t.group_by("species").count()
Out[4]:
┏━━━━━━━━━━━┳━━━━━━━┓
┃ species   ┃ count ┃
┡━━━━━━━━━━━╇━━━━━━━┩
│ string    │ int64 │
├───────────┼───────┤
│ Adelie    │   152 │
│ Gentoo    │   124 │
│ Chinstrap │    68 │
└───────────┴───────┘

[ins] In [5]: t.group_by("species").agg(ibis._.species.count())
Out[5]:
┏━━━━━━━━━━━┳━━━━━━━━━━━━━━━━┓
┃ species   ┃ Count(species) ┃
┡━━━━━━━━━━━╇━━━━━━━━━━━━━━━━┩
│ string    │ int64          │
├───────────┼────────────────┤
│ Adelie    │            152 │
│ Gentoo    │            124 │
│ Chinstrap │             68 │
└───────────┴────────────────┘
```


### What version of ibis are you using?

master

### What backend(s) are you using, if any?

duckdb

### Relevant log output

```sh
n/a
```


### Code of Conduct

- [X] I agree to follow this project's Code of Conduct


Discussion:

Resolving patch:
diff --git a/ibis/expr/types/generic.py b/ibis/expr/types/generic.py
--- a/ibis/expr/types/generic.py
+++ b/ibis/expr/types/generic.py
@@ -1228,7 +1228,7 @@ def topk(
         arg_table = find_first_base_table(self.op()).to_expr()
 
         if by is None:
-            by = self.count().name("count")
+            by = self.count()
 
         if callable(by):
             by = by(arg_table)
diff --git a/ibis/expr/types/groupby.py b/ibis/expr/types/groupby.py
--- a/ibis/expr/types/groupby.py
+++ b/ibis/expr/types/groupby.py
@@ -299,20 +299,15 @@ def over(
             window=window,
         )
 
-    def count(self, metric_name: str = 'count') -> ir.Table:
+    def count(self) -> ir.Table:
         """Computing the number of rows per group.
 
-        Parameters
-        ----------
-        metric_name
-            Name to use for the row count metric
-
         Returns
         -------
         Table
             The aggregated table
         """
-        metric = self.table.count().name(metric_name)
+        metric = self.table.count()
         return self.table.aggregate([metric], by=self.by, having=self._having)
 
     size = count


Test patch:
diff --git a/ibis/backends/clickhouse/tests/test_select.py b/ibis/backends/clickhouse/tests/test_select.py
--- a/ibis/backends/clickhouse/tests/test_select.py
+++ b/ibis/backends/clickhouse/tests/test_select.py
@@ -80,21 +80,21 @@ def test_limit_offset(alltypes):
 def test_subquery(alltypes, df):
     t = alltypes
 
-    expr = t.mutate(d=t.double_col).limit(1000).group_by('string_col').size()
+    expr = t.mutate(d=t.double_col).limit(100).group_by('string_col').size()
     result = expr.execute()
 
     result = result.sort_values('string_col').reset_index(drop=True)
     expected = (
         df.assign(d=df.double_col.fillna(0))
-        .head(1000)
+        .head(100)
         .groupby('string_col')
         .string_col.count()
-        .reset_index(name='count')
+        .rename("CountStar()")
+        .reset_index()
         .sort_values('string_col')
         .reset_index(drop=True)
     )
 
-    result['count'] = result['count'].astype('int64')
     tm.assert_frame_equal(result, expected)
 
 
diff --git a/ibis/backends/flink/tests/snapshots/test_translator/test_translate_count_star/out.sql b/ibis/backends/flink/tests/snapshots/test_translator/test_translate_count_star/out.sql
--- a/ibis/backends/flink/tests/snapshots/test_translator/test_translate_count_star/out.sql
+++ b/ibis/backends/flink/tests/snapshots/test_translator/test_translate_count_star/out.sql
@@ -1,3 +1,3 @@
-SELECT t0.`i`, count(*) AS `count`
+SELECT t0.`i`, count(*) AS `CountStar(table)`
 FROM table t0
 GROUP BY t0.`i`
\ No newline at end of file
diff --git a/ibis/backends/impala/tests/snapshots/test_bucket_histogram/test_bucket_assign_labels/out.sql b/ibis/backends/impala/tests/snapshots/test_bucket_histogram/test_bucket_assign_labels/out.sql
--- a/ibis/backends/impala/tests/snapshots/test_bucket_histogram/test_bucket_assign_labels/out.sql
+++ b/ibis/backends/impala/tests/snapshots/test_bucket_histogram/test_bucket_assign_labels/out.sql
@@ -5,7 +5,7 @@ SELECT
     WHEN 2 THEN '10 to 25'
     WHEN 3 THEN '25 to 50'
     ELSE 'error'
-  END AS `tier2`, t0.`count`
+  END AS `tier2`, t0.`CountStar(alltypes)`
 FROM (
   SELECT
     CASE
@@ -14,7 +14,7 @@ FROM (
       WHEN (10 <= t1.`f`) AND (t1.`f` < 25) THEN 2
       WHEN (25 <= t1.`f`) AND (t1.`f` <= 50) THEN 3
       ELSE CAST(NULL AS tinyint)
-    END AS `tier`, count(1) AS `count`
+    END AS `tier`, count(1) AS `CountStar(alltypes)`
   FROM `alltypes` t1
   GROUP BY 1
 ) t0
\ No newline at end of file
diff --git a/ibis/backends/impala/tests/snapshots/test_sql/test_join_key_name/out.sql b/ibis/backends/impala/tests/snapshots/test_sql/test_join_key_name/out.sql
--- a/ibis/backends/impala/tests/snapshots/test_sql/test_join_key_name/out.sql
+++ b/ibis/backends/impala/tests/snapshots/test_sql/test_join_key_name/out.sql
@@ -10,7 +10,7 @@ WITH t0 AS (
       ON t6.`o_custkey` = t5.`c_custkey`
 ),
 t1 AS (
-  SELECT extract(t0.`odate`, 'year') AS `year`, count(1) AS `count`
+  SELECT extract(t0.`odate`, 'year') AS `year`, count(1) AS `CountStar()`
   FROM t0
   WHERE t0.`o_totalprice` > (
     SELECT avg(t3.`o_totalprice`) AS `mean`
@@ -20,12 +20,13 @@ t1 AS (
   GROUP BY 1
 ),
 t2 AS (
-  SELECT extract(t0.`odate`, 'year') AS `year`, count(1) AS `count`
+  SELECT extract(t0.`odate`, 'year') AS `year`, count(1) AS `CountStar()`
   FROM t0
   GROUP BY 1
 )
-SELECT t2.`year`, t2.`count` AS `pre_count`, t1.`count` AS `post_count`,
-       t1.`count` / CAST(t2.`count` AS double) AS `fraction`
+SELECT t2.`year`, t2.`CountStar()` AS `pre_count`,
+       t1.`CountStar()` AS `post_count`,
+       t1.`CountStar()` / CAST(t2.`CountStar()` AS double) AS `fraction`
 FROM t2
   INNER JOIN t1
     ON t2.`year` = t1.`year`
\ No newline at end of file
diff --git a/ibis/backends/impala/tests/snapshots/test_sql/test_join_key_name2/out.sql b/ibis/backends/impala/tests/snapshots/test_sql/test_join_key_name2/out.sql
--- a/ibis/backends/impala/tests/snapshots/test_sql/test_join_key_name2/out.sql
+++ b/ibis/backends/impala/tests/snapshots/test_sql/test_join_key_name2/out.sql
@@ -10,11 +10,12 @@ WITH t0 AS (
       ON t6.`o_custkey` = t5.`c_custkey`
 ),
 t1 AS (
-  SELECT extract(t0.`odate`, 'year') AS `year`, count(1) AS `count`
+  SELECT extract(t0.`odate`, 'year') AS `year`, count(1) AS `CountStar()`
   FROM t0
   GROUP BY 1
 )
-SELECT t1.`year`, t1.`count` AS `pre_count`, t2.`count` AS `post_count`
+SELECT t1.`year`, t1.`CountStar()` AS `pre_count`,
+       t2.`CountStar()` AS `post_count`
 FROM t1
   INNER JOIN t1 t2
     ON t1.`year` = t2.`year`
\ No newline at end of file
diff --git a/ibis/backends/impala/tests/snapshots/test_sql/test_nested_join_base/out.sql b/ibis/backends/impala/tests/snapshots/test_sql/test_nested_join_base/out.sql
--- a/ibis/backends/impala/tests/snapshots/test_sql/test_nested_join_base/out.sql
+++ b/ibis/backends/impala/tests/snapshots/test_sql/test_nested_join_base/out.sql
@@ -1,10 +1,10 @@
 WITH t0 AS (
-  SELECT t2.`uuid`, count(1) AS `count`
+  SELECT t2.`uuid`, count(1) AS `CountStar(t)`
   FROM `t` t2
   GROUP BY 1
 ),
 t1 AS (
-  SELECT t0.`uuid`, max(t0.`count`) AS `max_count`
+  SELECT t0.`uuid`, max(t0.`CountStar(t)`) AS `max_count`
   FROM t0
   GROUP BY 1
 )
diff --git a/ibis/backends/impala/tests/snapshots/test_sql/test_nested_joins_single_cte/out.sql b/ibis/backends/impala/tests/snapshots/test_sql/test_nested_joins_single_cte/out.sql
--- a/ibis/backends/impala/tests/snapshots/test_sql/test_nested_joins_single_cte/out.sql
+++ b/ibis/backends/impala/tests/snapshots/test_sql/test_nested_joins_single_cte/out.sql
@@ -1,10 +1,10 @@
 WITH t0 AS (
-  SELECT t4.`uuid`, count(1) AS `count`
+  SELECT t4.`uuid`, count(1) AS `CountStar(t)`
   FROM `t` t4
   GROUP BY 1
 ),
 t1 AS (
-  SELECT t0.`uuid`, max(t0.`count`) AS `max_count`
+  SELECT t0.`uuid`, max(t0.`CountStar(t)`) AS `max_count`
   FROM t0
   GROUP BY 1
 ),
@@ -18,7 +18,7 @@ t3 AS (
   FROM t1
     LEFT OUTER JOIN t0
       ON (t1.`uuid` = t0.`uuid`) AND
-         (t1.`max_count` = t0.`count`)
+         (t1.`max_count` = t0.`CountStar(t)`)
 )
 SELECT t3.*, t2.`last_visit`
 FROM t3
diff --git a/ibis/backends/impala/tests/test_bucket_histogram.py b/ibis/backends/impala/tests/test_bucket_histogram.py
--- a/ibis/backends/impala/tests/test_bucket_histogram.py
+++ b/ibis/backends/impala/tests/test_bucket_histogram.py
@@ -83,6 +83,6 @@ def test_bucket_assign_labels(table, snapshot):
     labelled = size.tier.label(
         ['Under 0', '0 to 10', '10 to 25', '25 to 50'], nulls='error'
     ).name('tier2')
-    expr = size[labelled, size['count']]
+    expr = size[labelled, size[1]]
 
     snapshot.assert_match(ImpalaCompiler.to_sql(expr), "out.sql")
diff --git a/ibis/backends/impala/tests/test_ddl.py b/ibis/backends/impala/tests/test_ddl.py
--- a/ibis/backends/impala/tests/test_ddl.py
+++ b/ibis/backends/impala/tests/test_ddl.py
@@ -26,7 +26,7 @@ def temp_view(con) -> str:
 def test_create_exists_view(con, temp_view):
     assert temp_view not in con.list_tables()
 
-    t1 = con.table('functional_alltypes').group_by('string_col').size()
+    t1 = con.table('functional_alltypes').limit(1)
     t2 = con.create_view(temp_view, t1)
 
     assert temp_view in con.list_tables()
diff --git a/ibis/backends/impala/tests/test_sql.py b/ibis/backends/impala/tests/test_sql.py
--- a/ibis/backends/impala/tests/test_sql.py
+++ b/ibis/backends/impala/tests/test_sql.py
@@ -51,7 +51,7 @@ def test_limit_cte_extract(limit_cte_extract, snapshot):
 def test_nested_join_base(snapshot):
     t = ibis.table(dict(uuid='string', ts='timestamp'), name='t')
     counts = t.group_by('uuid').size()
-    max_counts = counts.group_by('uuid').aggregate(max_count=lambda x: x['count'].max())
+    max_counts = counts.group_by('uuid').aggregate(max_count=lambda x: x[1].max())
     result = max_counts.left_join(counts, 'uuid').select(counts)
     compiled_result = ImpalaCompiler.to_sql(result)
     snapshot.assert_match(compiled_result, "out.sql")
@@ -64,10 +64,10 @@ def test_nested_joins_single_cte(snapshot):
 
     last_visit = t.group_by('uuid').aggregate(last_visit=t.ts.max())
 
-    max_counts = counts.group_by('uuid').aggregate(max_count=counts['count'].max())
+    max_counts = counts.group_by('uuid').aggregate(max_count=counts[1].max())
 
     main_kw = max_counts.left_join(
-        counts, ['uuid', max_counts.max_count == counts['count']]
+        counts, ['uuid', max_counts.max_count == counts[1]]
     ).select(counts)
 
     result = main_kw.left_join(last_visit, 'uuid').select(
@@ -272,12 +272,12 @@ def test_join_key_name(tpch, snapshot):
     amount_filter = tpch.o_totalprice > conditional_avg
     post_sizes = tpch[amount_filter].group_by(year).size()
 
-    percent = (post_sizes['count'] / pre_sizes['count'].cast('double')).name('fraction')
+    percent = (post_sizes[1] / pre_sizes[1].cast('double')).name('fraction')
 
     expr = pre_sizes.join(post_sizes, pre_sizes.year == post_sizes.year)[
         pre_sizes.year,
-        pre_sizes['count'].name('pre_count'),
-        post_sizes['count'].name('post_count'),
+        pre_sizes[1].name('pre_count'),
+        post_sizes[1].name('post_count'),
         percent,
     ]
     result = ibis.impala.compile(expr)
@@ -292,8 +292,8 @@ def test_join_key_name2(tpch, snapshot):
 
     expr = pre_sizes.join(post_sizes, pre_sizes.year == post_sizes.year)[
         pre_sizes.year,
-        pre_sizes['count'].name('pre_count'),
-        post_sizes['count'].name('post_count'),
+        pre_sizes[1].name('pre_count'),
+        post_sizes[1].name('post_count'),
     ]
     result = ibis.impala.compile(expr)
     snapshot.assert_match(result, "out.sql")
diff --git a/ibis/backends/postgres/tests/test_functions.py b/ibis/backends/postgres/tests/test_functions.py
--- a/ibis/backends/postgres/tests/test_functions.py
+++ b/ibis/backends/postgres/tests/test_functions.py
@@ -717,7 +717,8 @@ def test_subquery(alltypes, df):
         .head(1000)
         .groupby('string_col')
         .string_col.count()
-        .reset_index(name='count')
+        .rename("CountStar()")
+        .reset_index()
         .sort_values('string_col')
         .reset_index(drop=True)
     )
diff --git a/ibis/backends/sqlite/tests/test_functions.py b/ibis/backends/sqlite/tests/test_functions.py
--- a/ibis/backends/sqlite/tests/test_functions.py
+++ b/ibis/backends/sqlite/tests/test_functions.py
@@ -545,7 +545,7 @@ def test_subquery(alltypes, df):
         .groupby('string_col')
         .size()
         .reset_index()
-        .rename(columns={0: 'count'})
+        .rename(columns={0: 'CountStar()'})
     )
     tm.assert_frame_equal(result, expected)
 
diff --git a/ibis/backends/tests/test_aggregation.py b/ibis/backends/tests/test_aggregation.py
--- a/ibis/backends/tests/test_aggregation.py
+++ b/ibis/backends/tests/test_aggregation.py
@@ -1258,7 +1258,7 @@ def test_topk_op(alltypes, df, result_fn, expected_fn):
     df = df.sort_values('string_col')
     result = result_fn(t).execute()
     expected = expected_fn(df)
-    assert all(result['count'].values == expected.values)
+    assert all(result.iloc[:, 1].values == expected.values)
 
 
 @pytest.mark.parametrize(
diff --git a/ibis/tests/expr/test_table.py b/ibis/tests/expr/test_table.py
--- a/ibis/tests/expr/test_table.py
+++ b/ibis/tests/expr/test_table.py
@@ -473,20 +473,20 @@ def test_order_by(table):
 
 
 def test_order_by_desc_deferred_sort_key(table):
-    result = table.group_by('g').size().order_by(ibis.desc('count'))
+    result = table.group_by('g').size().order_by(ibis._[1].desc())
 
     tmp = table.group_by('g').size()
-    expected = tmp.order_by(ibis.desc(tmp['count']))
+    expected = tmp.order_by(ibis.desc(tmp[1]))
 
     assert_equal(result, expected)
 
 
 def test_order_by_asc_deferred_sort_key(table):
-    result = table.group_by('g').size().order_by(ibis.asc('count'))
+    result = table.group_by('g').size().order_by(ibis._[1])
 
     tmp = table.group_by('g').size()
-    expected = tmp.order_by(tmp['count'])
-    expected2 = tmp.order_by(ibis.asc(tmp['count']))
+    expected = tmp.order_by(tmp[1])
+    expected2 = tmp.order_by(ibis.asc(tmp[1]))
 
     assert_equal(result, expected)
     assert_equal(result, expected2)
@@ -727,15 +727,11 @@ def test_group_by_count_size(table):
     result1 = table.group_by('g').size()
     result2 = table.group_by('g').count()
 
-    expected = table.group_by('g').aggregate([table.count().name('count')])
+    expected = table.group_by('g').aggregate(table.count())
 
     assert_equal(result1, expected)
     assert_equal(result2, expected)
 
-    result = table.group_by('g').count('foo')
-    expected = table.group_by('g').aggregate([table.count().name('foo')])
-    assert_equal(result, expected)
-
 
 def test_group_by_column_select_api(table):
     grouped = table.group_by('g')
diff --git a/ibis/tests/sql/snapshots/test_compiler/test_having_size/out.sql b/ibis/tests/sql/snapshots/test_compiler/test_having_size/out.sql
--- a/ibis/tests/sql/snapshots/test_compiler/test_having_size/out.sql
+++ b/ibis/tests/sql/snapshots/test_compiler/test_having_size/out.sql
@@ -1,4 +1,4 @@
-SELECT t0.`string_col`, count(1) AS `count`
+SELECT t0.`string_col`, count(1) AS `CountStar(functional_alltypes)`
 FROM functional_alltypes t0
 GROUP BY 1
 HAVING max(t0.`double_col`) = 1
\ No newline at end of file
diff --git a/ibis/tests/sql/snapshots/test_select_sql/test_topk_analysis_bug/out.sql b/ibis/tests/sql/snapshots/test_select_sql/test_topk_analysis_bug/out.sql
--- a/ibis/tests/sql/snapshots/test_select_sql/test_topk_analysis_bug/out.sql
+++ b/ibis/tests/sql/snapshots/test_select_sql/test_topk_analysis_bug/out.sql
@@ -15,7 +15,7 @@ t2 AS (
   FROM airlines t3
   WHERE t3.`dest` IN ('ORD', 'JFK', 'SFO')
 )
-SELECT `origin`, count(1) AS `count`
+SELECT `origin`, count(1) AS `CountStar()`
 FROM t2
   LEFT SEMI JOIN t1
     ON t2.`dest` = t1.`dest`
diff --git a/ibis/tests/sql/snapshots/test_select_sql/test_topk_operation/e2.sql b/ibis/tests/sql/snapshots/test_select_sql/test_topk_operation/e2.sql
--- a/ibis/tests/sql/snapshots/test_select_sql/test_topk_operation/e2.sql
+++ b/ibis/tests/sql/snapshots/test_select_sql/test_topk_operation/e2.sql
@@ -1,12 +1,12 @@
 WITH t0 AS (
-  SELECT t2.`city`, count(t2.`city`) AS `count`
+  SELECT t2.`city`, count(t2.`city`) AS `Count(city)`
   FROM tbl t2
   GROUP BY 1
 ),
 t1 AS (
   SELECT t0.*
   FROM t0
-  ORDER BY t0.`count` DESC
+  ORDER BY t0.`Count(city)` DESC
   LIMIT 10
 )
 SELECT *