prompt: You will be provided with a partial code base and an issue statement explaining a problem to resolve.
  <issue>
  bug: comparing bool expr to bool literal generates invalid sql
  It looks like one of the recent refactorings may have broken comparisons of boolean to boolean:
  
  This test:
  
  ```python
  def test_bool_bool():
      import ibis
      from ibis.backends.base.sql.compiler import Compiler
  
      t = ibis.table(
          [('dest', 'string'), ('origin', 'string'), ('arrdelay', 'int32')],
          'airlines',
      )
  
      x = ibis.literal(True)
      top = t[(t.dest.cast('int64') == 0) == x]
  
      result = Compiler.to_sql(top)
      print(result)
  ```
  
  produces this SQL:
  
  ```sql
  SELECT *
  FROM airlines
  WHERE CAST(`dest` AS bigint) = 0 = TRUE
  ```
  
  </issue>
  <code>
  [start of ibis/backends/base/sql/registry/helpers.py]
  1 import ibis.common.exceptions as com
  2 import ibis.expr.datatypes as dt
  3 import ibis.expr.operations as ops
  4 import ibis.expr.types as ir
  5 from ibis.backends.base.sql.registry import identifiers
  6 
  7 
  8 def format_call(translator, func, *args):
  9     formatted_args = []
  10     for arg in args:
  11         fmt_arg = translator.translate(arg)
  12         formatted_args.append(fmt_arg)
  13 
  14     return '{}({})'.format(func, ', '.join(formatted_args))
  15 
  16 
  17 def quote_identifier(name, quotechar='`', force=False):
  18     """Add quotes to the `name` identifier if needed."""
  19     if force or name.count(' ') or name in identifiers.base_identifiers:
  20         return '{0}{1}{0}'.format(quotechar, name)
  21     else:
  22         return name
  23 
  24 
  25 def needs_parens(op):
  26     if isinstance(op, ir.Expr):
  27         op = op.op()
  28     op_klass = type(op)
  29     # function calls don't need parens
  30     return op_klass in {
  31         ops.Negate,
  32         ops.IsNull,
  33         ops.NotNull,
  34         ops.Add,
  35         ops.Subtract,
  36         ops.Multiply,
  37         ops.Divide,
  38         ops.Power,
  39         ops.Modulus,
  40         ops.Equals,
  41         ops.NotEquals,
  42         ops.GreaterEqual,
  43         ops.Greater,
  44         ops.LessEqual,
  45         ops.Less,
  46         ops.IdenticalTo,
  47         ops.And,
  48         ops.Or,
  49         ops.Xor,
  50     }
  51 
  52 
  53 parenthesize = '({})'.format
  54 
  55 
  56 sql_type_names = {
  57     'int8': 'tinyint',
  58     'int16': 'smallint',
  59     'int32': 'int',
  60     'int64': 'bigint',
  61     'float': 'float',
  62     'float32': 'float',
  63     'double': 'double',
  64     'float64': 'double',
  65     'string': 'string',
  66     'boolean': 'boolean',
  67     'timestamp': 'timestamp',
  68     'decimal': 'decimal',
  69 }
  70 
  71 
  72 def type_to_sql_string(tval):
  73     if isinstance(tval, dt.Decimal):
  74         return f'decimal({tval.precision}, {tval.scale})'
  75     name = tval.name.lower()
  76     try:
  77         return sql_type_names[name]
  78     except KeyError:
  79         raise com.UnsupportedBackendType(name)
  80
  [end of ibis/backends/base/sql/registry/helpers.py]
  </code>
  
  I need you to solve this issue by generating a single patch file that I can apply directly to this repository using git apply. Please respond with a single patch file in the following format.
  <patch>
  diff --git a/file.py b/file.py
  --- a/file.py
  +++ b/file.py
  @@ -1,27 +1,35 @@
   def euclidean(a, b):
  -    while b:
  -        a, b = b, a % b
  -    return a
  +    if b == 0:
  +        return a
  +    return euclidean(b, a % b)
   
   
   def bresenham(x0, y0, x1, y1):
       points = []
       dx = abs(x1 - x0)
       dy = abs(y1 - y0)
  -    sx = 1 if x0 < x1 else -1
  -    sy = 1 if y0 < y1 else -1
  -    err = dx - dy
  +    x, y = x0, y0
  +    sx = -1 if x0 > x1 else 1
  +    sy = -1 if y0 > y1 else 1
   
  -    while True:
  -        points.append((x0, y0))
  -        if x0 == x1 and y0 == y1:
  -            break
  -        e2 = 2 * err
  -        if e2 > -dy:
  -            err -= dy
  -            x0 += sx
  -        if e2 < dx:
  -            err += dx
  -            y0 += sy
  +    if dx > dy:
  +        err = dx / 2.0
  +        while x != x1:
  +            points.append((x, y))
  +            err -= dy
  +            if err < 0:
  +                y += sy
  +                err += dx
  +            x += sx
  +    else:
  +        err = dy / 2.0
  +        while y != y1:
  +            points.append((x, y))
  +            err -= dx
  +            if err < 0:
  +                x += sx
  +                err += dy
  +            y += sy
  +
  +    points.append((x, y))
       return points
  
  </patch>
golden_diff: diff --git a/ibis/backends/base/sql/registry/helpers.py b/ibis/backends/base/sql/registry/helpers.py
  --- a/ibis/backends/base/sql/registry/helpers.py
  +++ b/ibis/backends/base/sql/registry/helpers.py
  @@ -22,32 +22,34 @@
           return name
   
   
  -def needs_parens(op):
  -    if isinstance(op, ir.Expr):
  -        op = op.op()
  -    op_klass = type(op)
  -    # function calls don't need parens
  -    return op_klass in {
  -        ops.Negate,
  -        ops.IsNull,
  -        ops.NotNull,
  -        ops.Add,
  -        ops.Subtract,
  -        ops.Multiply,
  -        ops.Divide,
  -        ops.Power,
  -        ops.Modulus,
  -        ops.Equals,
  -        ops.NotEquals,
  -        ops.GreaterEqual,
  -        ops.Greater,
  -        ops.LessEqual,
  -        ops.Less,
  -        ops.IdenticalTo,
  -        ops.And,
  -        ops.Or,
  -        ops.Xor,
  -    }
  +_NEEDS_PARENS_OPS = (
  +    ops.Negate,
  +    ops.IsNull,
  +    ops.NotNull,
  +    ops.Add,
  +    ops.Subtract,
  +    ops.Multiply,
  +    ops.Divide,
  +    ops.Power,
  +    ops.Modulus,
  +    ops.Equals,
  +    ops.NotEquals,
  +    ops.GreaterEqual,
  +    ops.Greater,
  +    ops.LessEqual,
  +    ops.Less,
  +    ops.IdenticalTo,
  +    ops.And,
  +    ops.Or,
  +    ops.Xor,
  +)
  +
  +
  +def needs_parens(expr: ir.Expr):
  +    op = expr.op()
  +    if isinstance(op, ops.Alias):
  +        op = op.arg.op()
  +    return isinstance(op, _NEEDS_PARENS_OPS)
   
   
   parenthesize = '({})'.format
  
verification_info: {"golden_diff": "diff --git a/ibis/backends/base/sql/registry/helpers.py b/ibis/backends/base/sql/registry/helpers.py\n--- a/ibis/backends/base/sql/registry/helpers.py\n+++ b/ibis/backends/base/sql/registry/helpers.py\n@@ -22,32 +22,34 @@\n         return name\n \n \n-def needs_parens(op):\n-    if isinstance(op, ir.Expr):\n-        op = op.op()\n-    op_klass = type(op)\n-    # function calls don't need parens\n-    return op_klass in {\n-        ops.Negate,\n-        ops.IsNull,\n-        ops.NotNull,\n-        ops.Add,\n-        ops.Subtract,\n-        ops.Multiply,\n-        ops.Divide,\n-        ops.Power,\n-        ops.Modulus,\n-        ops.Equals,\n-        ops.NotEquals,\n-        ops.GreaterEqual,\n-        ops.Greater,\n-        ops.LessEqual,\n-        ops.Less,\n-        ops.IdenticalTo,\n-        ops.And,\n-        ops.Or,\n-        ops.Xor,\n-    }\n+_NEEDS_PARENS_OPS = (\n+    ops.Negate,\n+    ops.IsNull,\n+    ops.NotNull,\n+    ops.Add,\n+    ops.Subtract,\n+    ops.Multiply,\n+    ops.Divide,\n+    ops.Power,\n+    ops.Modulus,\n+    ops.Equals,\n+    ops.NotEquals,\n+    ops.GreaterEqual,\n+    ops.Greater,\n+    ops.LessEqual,\n+    ops.Less,\n+    ops.IdenticalTo,\n+    ops.And,\n+    ops.Or,\n+    ops.Xor,\n+)\n+\n+\n+def needs_parens(expr: ir.Expr):\n+    op = expr.op()\n+    if isinstance(op, ops.Alias):\n+        op = op.arg.op()\n+    return isinstance(op, _NEEDS_PARENS_OPS)\n \n \n parenthesize = '({})'.format\n", "issue": "bug: comparing bool expr to bool literal generates invalid sql\nIt looks like one of the recent refactorings may have broken comparisons of boolean to boolean:\r\n\r\nThis test:\r\n\r\n```python\r\ndef test_bool_bool():\r\n    import ibis\r\n    from ibis.backends.base.sql.compiler import Compiler\r\n\r\n    t = ibis.table(\r\n        [('dest', 'string'), ('origin', 'string'), ('arrdelay', 'int32')],\r\n        'airlines',\r\n    )\r\n\r\n    x = ibis.literal(True)\r\n    top = t[(t.dest.cast('int64') == 0) == x]\r\n\r\n    result = Compiler.to_sql(top)\r\n    print(result)\r\n```\r\n\r\nproduces this SQL:\r\n\r\n```sql\r\nSELECT *\r\nFROM airlines\r\nWHERE CAST(`dest` AS bigint) = 0 = TRUE\r\n```\n", "before_files": [{"content": "import ibis.common.exceptions as com\nimport ibis.expr.datatypes as dt\nimport ibis.expr.operations as ops\nimport ibis.expr.types as ir\nfrom ibis.backends.base.sql.registry import identifiers\n\n\ndef format_call(translator, func, *args):\n    formatted_args = []\n    for arg in args:\n        fmt_arg = translator.translate(arg)\n        formatted_args.append(fmt_arg)\n\n    return '{}({})'.format(func, ', '.join(formatted_args))\n\n\ndef quote_identifier(name, quotechar='`', force=False):\n    \"\"\"Add quotes to the `name` identifier if needed.\"\"\"\n    if force or name.count(' ') or name in identifiers.base_identifiers:\n        return '{0}{1}{0}'.format(quotechar, name)\n    else:\n        return name\n\n\ndef needs_parens(op):\n    if isinstance(op, ir.Expr):\n        op = op.op()\n    op_klass = type(op)\n    # function calls don't need parens\n    return op_klass in {\n        ops.Negate,\n        ops.IsNull,\n        ops.NotNull,\n        ops.Add,\n        ops.Subtract,\n        ops.Multiply,\n        ops.Divide,\n        ops.Power,\n        ops.Modulus,\n        ops.Equals,\n        ops.NotEquals,\n        ops.GreaterEqual,\n        ops.Greater,\n        ops.LessEqual,\n        ops.Less,\n        ops.IdenticalTo,\n        ops.And,\n        ops.Or,\n        ops.Xor,\n    }\n\n\nparenthesize = '({})'.format\n\n\nsql_type_names = {\n    'int8': 'tinyint',\n    'int16': 'smallint',\n    'int32': 'int',\n    'int64': 'bigint',\n    'float': 'float',\n    'float32': 'float',\n    'double': 'double',\n    'float64': 'double',\n    'string': 'string',\n    'boolean': 'boolean',\n    'timestamp': 'timestamp',\n    'decimal': 'decimal',\n}\n\n\ndef type_to_sql_string(tval):\n    if isinstance(tval, dt.Decimal):\n        return f'decimal({tval.precision}, {tval.scale})'\n    name = tval.name.lower()\n    try:\n        return sql_type_names[name]\n    except KeyError:\n        raise com.UnsupportedBackendType(name)\n", "path": "ibis/backends/base/sql/registry/helpers.py"}]}