Repository: edgedb/edgedb

Issue:
ISE in `foo IN array_unpack(<double-array-cast>)`
```
edgedb> select 1n in array_unpack(<array<bigint>><array<str>>to_json('["1"]'));
edgedb error: InternalServerError: syntax error at or near "ANY"
  Hint: This is most likely a bug in EdgeDB. Please consider opening an issue ticket at https://github.com/edgedb/edgedb/issues/new?template=bug_report.md
  Server traceback:
      edb.errors.InternalServerError: syntax error at or near "ANY"
```



Discussion:

Resolving patch:
diff --git a/edb/pgsql/compiler/relgen.py b/edb/pgsql/compiler/relgen.py
--- a/edb/pgsql/compiler/relgen.py
+++ b/edb/pgsql/compiler/relgen.py
@@ -1369,16 +1369,19 @@ def process_set_as_membership_expr(
         newctx.expr_exposed = False
         left_out = dispatch.compile(left_arg, ctx=newctx)
 
-        right_arg = irutils.unwrap_set(right_arg)
+        orig_right_arg = right_arg
+        unwrapped_right_arg = irutils.unwrap_set(right_arg)
         # If the right operand of [NOT] IN is an array_unpack call,
         # then use the ANY/ALL array comparison operator directly,
         # since that has a higher chance of using the indexes.
-        right_expr = right_arg.expr
+        right_expr = unwrapped_right_arg.expr
         needs_coalesce = False
+
         if (
             isinstance(right_expr, irast.FunctionCall)
             and str(right_expr.func_shortname) == 'std::array_unpack'
             and not right_expr.args[0].cardinality.is_multi()
+            and (not expr.sql_operator or len(expr.sql_operator) <= 1)
         ):
             is_array_unpack = True
             right_arg = right_expr.args[0].expr
@@ -1389,6 +1392,11 @@ def process_set_as_membership_expr(
         left_is_row_expr = astutils.is_row_expr(left_out)
 
         with newctx.subrel() as _, _.newscope() as subctx:
+            if is_array_unpack:
+                relctx.update_scope(orig_right_arg, subctx.rel, ctx=subctx)
+                relctx.update_scope(
+                    unwrapped_right_arg, subctx.rel, ctx=subctx)
+
             dispatch.compile(right_arg, ctx=subctx)
             right_rel = subctx.rel
             right_out = pathctx.get_path_value_var(


Test patch:
diff --git a/tests/test_edgeql_functions.py b/tests/test_edgeql_functions.py
--- a/tests/test_edgeql_functions.py
+++ b/tests/test_edgeql_functions.py
@@ -537,6 +537,19 @@ async def test_edgeql_functions_array_unpack_06(self):
             [True],
         )
 
+        await self.assert_query_result(
+            r'''SELECT 1n IN array_unpack([1n]);''',
+            [True],
+        )
+
+        await self.assert_query_result(
+            r'''
+                select 1n in array_unpack(
+                    <array<bigint>><array<str>>to_json('["1"]'))
+            ''',
+            [True],
+        )
+
     async def test_edgeql_functions_enumerate_01(self):
         await self.assert_query_result(
             r'''SELECT [10, 20];''',
diff --git a/tests/test_edgeql_sql_codegen.py b/tests/test_edgeql_sql_codegen.py
--- a/tests/test_edgeql_sql_codegen.py
+++ b/tests/test_edgeql_sql_codegen.py
@@ -205,3 +205,15 @@ def test_codegen_group_simple(self):
             "uuid_generate", group_sql,
             "group has unnecessary uuid_generate",
         )
+
+    def test_codegen_in_array_unpack_no_dupe(self):
+        sql = self._compile('''
+            select 1 in array_unpack(
+                <array<int64>><array<str>>to_json('["1"]'))
+        ''')
+
+        count = sql.count('["1"]')
+        self.assertEqual(
+            count,
+            1,
+            f"argument needlessly duplicated")