Repository: tobymao/sqlglot

Issue:
IS NOT NULL works incorrectly for subquery
SQLGlot parses `IS NOT NULL` to `NOT ... IS NULL` without parentheses. For example SQLGlot should parse like `NOT (... IS NULL)`

```python
from sqlglot import Dialects, parse_one

sql = """
    SELECT name
    FROM data 
    WHERE (SELECT DISTINCT name FROM data) IS NOT NULL
"""

print(parse_one(sql, read=Dialects.CLICKHOUSE).sql(dialect=Dialects.CLICKHOUSE))
```

❌ Wrong output with the version SQLGlot v25.27.0
```sql
SELECT name FROM data WHERE NOT (SELECT DISTINCT name FROM data) IS NULL
```

✅ Expected correct output
```sql
SELECT name FROM data WHERE NOT ((SELECT DISTINCT name FROM data) IS NULL)
```

Discussion:

Solution patch:
diff --git a/sqlglot/dialects/clickhouse.py b/sqlglot/dialects/clickhouse.py
index c75a67caa9..85756d94a3 100644
--- a/sqlglot/dialects/clickhouse.py
+++ b/sqlglot/dialects/clickhouse.py
@@ -1212,3 +1212,12 @@ def replacepartition_sql(self, expression: exp.ReplacePartition) -> str:
 
         def projectiondef_sql(self, expression: exp.ProjectionDef) -> str:
             return f"PROJECTION {self.sql(expression.this)} {self.wrap(expression.expression)}"
+
+        def is_sql(self, expression: exp.Is) -> str:
+            is_sql = super().is_sql(expression)
+
+            if isinstance(expression.parent, exp.Not) and isinstance(expression.this, exp.Subquery):
+                # WHERE (SELECT ...) IS NOT NULL -> NOT ((SELECT ...) IS NULL)
+                is_sql = self.wrap(is_sql)
+
+            return is_sql


Test patch:
diff --git a/tests/dialects/test_clickhouse.py b/tests/dialects/test_clickhouse.py
index 9a1a7e36c8..33ff02c57f 100644
--- a/tests/dialects/test_clickhouse.py
+++ b/tests/dialects/test_clickhouse.py
@@ -526,6 +526,10 @@ def test_clickhouse(self):
             "SELECT * FROM ABC WHERE hasAny(COLUMNS('.*field') APPLY(toUInt64) APPLY(to), (SELECT groupUniqArray(toUInt64(field))))"
         )
         self.validate_identity("SELECT col apply", "SELECT col AS apply")
+        self.validate_identity(
+            "SELECT name FROM data WHERE (SELECT DISTINCT name FROM data) IS NOT NULL",
+            "SELECT name FROM data WHERE NOT ((SELECT DISTINCT name FROM data) IS NULL)",
+        )
 
     def test_clickhouse_values(self):
         values = exp.select("*").from_(