Repository: ibis-project/ibis

Issue:
bug(bigquery):  Numeric precision increase 1 unexpectedly after every sub/add operations
### What happened?

The numeric precision get automacially increase 1 per sub/add operations unexpectedly, though BQ only supports `precision=38` for `NUMERIC` and `precision=76` for `BIGNUMERIC`.

The code to repro the issue:

```
>>> import ibis
>>> bq = ibis.bigquery.connect(project_id="bigframes-dev")
>>> taxi_dt = bq.table("bigquery-public-data.new_york_taxi_trips.tlc_yellow_trips_2022")
>>> taxi_dt['trip_distance'].type()
Decimal(precision=38, scale=9, nullable=True)
>>> result = taxi_dt['trip_distance']+taxi_dt['trip_distance']
>>> result.type()
Decimal(precision=39, scale=9, nullable=True)
```
The expected `result.type()` would be `Decimal(precision=38, scale=9, nullable=True)`


### What version of ibis are you using?

7.1.0

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

BigQuery

### Relevant log output

_No response_

### Code of Conduct

- [X] I agree to follow this project's Code of Conduct


Discussion:
The [_promote_decimal_binop](https://github.com/ibis-project/ibis/blob/8e190bb70c36b83828906a142f34a8d285aca518/ibis/expr/rules.py#L111) function auto increases the decimal for binop. I tried to check if the `left.arg.table.source.db_identity` is `bigquery.Backend` in this function. However, this will introduce the circular import (ibis/backends -> ibis/expr -> ibis/backends). 
Any other potential solution to fix the issue here?
The decimal type evolution introduced to fix https://github.com/ibis-project/ibis/issues/4319 for DB2 is inconsistent with how types evolve in BigQuery, which follows these rules: https://cloud.google.com/bigquery/docs/reference/standard-sql/operators#arithmetic_operators

In BigQuery DataFrames, we rely on the type of the Ibis expression to (1) determine which pandas type we're emulating and (2) in our I/O, when we actually execute the query we don't actually do .execute() so that we have a little more control over how the query is run. In both of these steps, we expect there to be a pretty constant mapping from ibis type to BigQuery type. For example, here's one of our mappings for (1) https://github.com/googleapis/python-bigquery-dataframes/blob/b90241e6db8fa7b5dce29c5fc5e0d6d81d6595e6/bigframes/dtypes.py#L110-L131

Resolving patch:
diff --git a/ibis/expr/rules.py b/ibis/expr/rules.py
--- a/ibis/expr/rules.py
+++ b/ibis/expr/rules.py
@@ -1,6 +1,5 @@
 from __future__ import annotations
 
-import operator
 from itertools import product, starmap
 from typing import Optional
 
@@ -108,39 +107,6 @@ def _promote_integral_binop(exprs, op):
     return dt.highest_precedence(dtypes)
 
 
-def _promote_decimal_binop(args, op):
-    if len(args) != 2:
-        return highest_precedence_dtype(args)
-
-    # TODO: Add support for setting the maximum precision and maximum scale
-    left = args[0].dtype
-    right = args[1].dtype
-
-    max_prec = 31 if left.precision <= 31 and right.precision <= 31 else 63
-    max_scale = 31
-
-    if op is operator.mul:
-        return dt.Decimal(
-            min(max_prec, left.precision + right.precision),
-            min(max_scale, left.scale + right.scale),
-        )
-    elif op is operator.add or op is operator.sub:
-        return dt.Decimal(
-            min(
-                max_prec,
-                max(
-                    left.precision - left.scale,
-                    right.precision - right.scale,
-                )
-                + max(left.scale, right.scale)
-                + 1,
-            ),
-            max(left.scale, right.scale),
-        )
-    else:
-        return highest_precedence_dtype(args)
-
-
 @public
 def numeric_like(name, op):
     @attribute
@@ -149,8 +115,6 @@ def dtype(self):
         dtypes = [arg.dtype for arg in args]
         if util.all_of(dtypes, dt.Integer):
             result = _promote_integral_binop(args, op)
-        elif util.all_of(dtypes, dt.Decimal):
-            result = _promote_decimal_binop(args, op)
         else:
             result = highest_precedence_dtype(args)
 


Test patch:
diff --git a/ibis/tests/expr/test_decimal.py b/ibis/tests/expr/test_decimal.py
--- a/ibis/tests/expr/test_decimal.py
+++ b/ibis/tests/expr/test_decimal.py
@@ -36,15 +36,15 @@ def test_promote_decimal_type_mul(lineitem):
     col_1 = lineitem.l_extendedprice
     col_2 = lineitem.l_discount
     result = col_1 * col_2
-    assert result.type().precision == 24
-    assert result.type().scale == 4
+    assert result.type().precision == 12
+    assert result.type().scale == 2
 
 
 def test_promote_decimal_type_add(lineitem):
     col_1 = lineitem.l_extendedprice
     col_2 = lineitem.l_discount
     result = col_1 + col_2
-    assert result.type().precision == 13
+    assert result.type().precision == 12
     assert result.type().scale == 2
 
 
@@ -60,7 +60,7 @@ def test_promote_decimal_type_max():
     t = ibis.table([("a", "decimal(31, 3)"), ("b", "decimal(31, 3)")], "t")
     result = t.a * t.b
     assert result.type().precision == 31
-    assert result.type().scale == 6
+    assert result.type().scale == 3
 
 
 @pytest.mark.parametrize(