Repository: edgedb/edgedb

Issue:
`constraint expression on` causes InternalServerError: NotImplementedError 
<!-- Please search existing issues to avoid creating duplicates. -->

<!--
For the EdgeDB Version: run `edgedb query 'select sys::get_version_as_str()'` from your project directory (or run `select sys::get_version_as_str();` in the EdgeDB interactive shell).
For the EdgeDB CLI Version: Run `edgedb --version` from anywhere
-->

- EdgeDB Version: 5.3+cc878d8
- EdgeDB CLI Version: 5.1.0+7c5764f
- OS Version: Ubuntu 22.04.4 (Linux 5.15.146.1-microsoft-standard-WSL2) running on Windows 11 with WSL2 (2.1.5.0)

Steps to Reproduce:

```bash
edgedb migration create 
```

Basically, I'm using the `constraint expression on` clause to create a constraint that the length of the `orderid` must be greater than 0.

Stack trace:

```bash
edgedb error: InternalServerError: NotImplementedError: do not know how to trace <edb.edgeql.ast.Parameter object at 0x7f67035811f0>
  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:
      Traceback (most recent call last):
        File "/home/mikko/.local/share/edgedb/portable/5.3/lib/python3.12/site-packages/edb/server/compiler_pool/worker.py", line 178, in compile
          units, cstate = COMPILER.compile_request(
                          ^^^^^^^^^^^^^^^^^^^^^^^^^
        File "/home/mikko/.local/share/edgedb/portable/5.3/lib/python3.12/site-packages/edb/server/compiler/compiler.py", line 858, in compile_request
          units, cstate = self.compile(
                          ^^^^^^^^^^^^^
        File "/home/mikko/.local/share/edgedb/portable/5.3/lib/python3.12/site-packages/edb/server/compiler/compiler.py", line 938, in compile
          unit_group = compile(ctx=ctx, source=source)
                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        File "/home/mikko/.local/share/edgedb/portable/5.3/lib/python3.12/site-packages/edb/server/compiler/compiler.py", line 2589, in compile
          return _try_compile(ctx=ctx, source=source)
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        File "/home/mikko/.local/share/edgedb/portable/5.3/lib/python3.12/site-packages/edb/server/compiler/compiler.py", line 2667, in _try_compile
          comp, capabilities = _compile_dispatch_ql(
                               ^^^^^^^^^^^^^^^^^^^^^
        File "/home/mikko/.local/share/edgedb/portable/5.3/lib/python3.12/site-packages/edb/server/compiler/compiler.py", line 2494, in _compile_dispatch_ql
          query = ddl.compile_dispatch_ql_migration(
                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        File "/home/mikko/.local/share/edgedb/portable/5.3/lib/python3.12/site-packages/edb/server/compiler/ddl.py", line 386, in compile_dispatch_ql_migration
          return _start_migration(ctx, ql, in_script)
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        File "/home/mikko/.local/share/edgedb/portable/5.3/lib/python3.12/site-packages/edb/server/compiler/ddl.py", line 466, in _start_migration
          target_schema = s_ddl.apply_sdl(
                          ^^^^^^^^^^^^^^^^
        File "/home/mikko/.local/share/edgedb/portable/5.3/lib/python3.12/site-packages/edb/schema/ddl.py", line 591, in apply_sdl
          ddl_stmts = s_decl.sdl_to_ddl(target_schema, documents)
                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        File "/home/mikko/.local/share/edgedb/portable/5.3/lib/python3.12/site-packages/edb/edgeql/declarative.py", line 451, in sdl_to_ddl
          trace_dependencies(decl_ast, ctx=tracectx)
        File "/home/mikko/.local/share/edgedb/portable/5.3/lib/python3.12/functools.py", line 909, in wrapper
          return dispatch(args[0].__class__)(*args, **kw)
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        File "/home/mikko/.local/share/edgedb/portable/5.3/lib/python3.12/site-packages/edb/edgeql/declarative.py", line 1090, in trace_default
          _register_item(node, ctx=ctx)
        File "/home/mikko/.local/share/edgedb/portable/5.3/lib/python3.12/site-packages/edb/edgeql/declarative.py", line 1222, in _register_item
          trace_dependencies(cmd, ctx=ctx)
        File "/home/mikko/.local/share/edgedb/portable/5.3/lib/python3.12/functools.py", line 909, in wrapper
          return dispatch(args[0].__class__)(*args, **kw)
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        File "/home/mikko/.local/share/edgedb/portable/5.3/lib/python3.12/site-packages/edb/edgeql/declarative.py", line 1000, in trace_ConcretePointer
          _register_item(
        File "/home/mikko/.local/share/edgedb/portable/5.3/lib/python3.12/site-packages/edb/edgeql/declarative.py", line 1222, in _register_item
          trace_dependencies(cmd, ctx=ctx)
        File "/home/mikko/.local/share/edgedb/portable/5.3/lib/python3.12/functools.py", line 909, in wrapper
          return dispatch(args[0].__class__)(*args, **kw)
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        File "/home/mikko/.local/share/edgedb/portable/5.3/lib/python3.12/site-packages/edb/edgeql/declarative.py", line 879, in trace_ConcreteConstraint
          _register_item(
        File "/home/mikko/.local/share/edgedb/portable/5.3/lib/python3.12/site-packages/edb/edgeql/declarative.py", line 1248, in _register_item
          strong_tdeps, weak_tdeps = qltracer.trace_refs(
                                     ^^^^^^^^^^^^^^^^^^^^
        File "/home/mikko/.local/share/edgedb/portable/5.3/lib/python3.12/site-packages/edb/edgeql/tracer.py", line 365, in trace_refs
          trace(qltree, ctx=ctx)
        File "/home/mikko/.local/share/edgedb/portable/5.3/lib/python3.12/functools.py", line 909, in wrapper
          return dispatch(args[0].__class__)(*args, **kw)
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        File "/home/mikko/.local/share/edgedb/portable/5.3/lib/python3.12/site-packages/edb/edgeql/tracer.py", line 620, in trace_BinOp
          trace(node.left, ctx=ctx)
        File "/home/mikko/.local/share/edgedb/portable/5.3/lib/python3.12/functools.py", line 909, in wrapper
          return dispatch(args[0].__class__)(*args, **kw)
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        File "/home/mikko/.local/share/edgedb/portable/5.3/lib/python3.12/site-packages/edb/edgeql/tracer.py", line 688, in trace_FunctionCall
          trace(arg, ctx=ctx)
        File "/home/mikko/.local/share/edgedb/portable/5.3/lib/python3.12/functools.py", line 909, in wrapper
          return dispatch(args[0].__class__)(*args, **kw)
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        File "/home/mikko/.local/share/edgedb/portable/5.3/lib/python3.12/site-packages/edb/edgeql/tracer.py", line 652, in trace_TypeCast
          trace(node.expr, ctx=ctx)
        File "/home/mikko/.local/share/edgedb/portable/5.3/lib/python3.12/functools.py", line 909, in wrapper
          return dispatch(args[0].__class__)(*args, **kw)
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        File "/home/mikko/.local/share/edgedb/portable/5.3/lib/python3.12/site-packages/edb/edgeql/tracer.py", line 581, in trace
          raise NotImplementedError(f"do not know how to trace {node!r}")
      NotImplementedError: do not know how to trace <edb.edgeql.ast.Parameter object at 0x7f67035811f0> 
```

<!-- If the issue is about a query error, please also provide your schema -->

Schema:

```edgegl
module default {
    type OrderLine {
        required orderid: str {
            constraint expression on (len(<str>$orderid) > 0);
            constraint max_len_value(255);
            constraint exclusive;
        }
        required qty: int32 {
            constraint min_value(0);
        }
        sku: str {
            constraint max_len_value(255);
        }
    }
    type Batch {
        required reference: str {
            constraint max_len_value(255);
            constraint exclusive;
        }
        required purchased_quantity: int32 {
            constraint min_value(0);
        }
        sku: str {
            constraint max_len_value(255);
        }
        eta: cal::local_date;
    }

    type Allocation {
        required multi orderid: OrderLine;
        required multi batchid: Batch;
    }
}
```



Discussion:
Try `__subject__` instead of `<str>$orderid`. (Or, use `min_len_value`).

Getting an ISE instead of a proper error message about nonexisting params is a bug, though. I think the tracer should just ignore the Parameter and let the compiler error on it later.




> Try `__subject__` instead of `<str>$orderid`. (Or, use `min_len_value`).
> 
> Getting an ISE instead of a proper error message about nonexisting params is a bug, though. I think the tracer should just ignore the Parameter and let the compiler error on it later.

Okay, thanks! Using `__subject__` or `min_len_value(1)` does the work. `<str>$orderid` is got from Ask AI when asking about this.

Resolving patch:
diff --git a/edb/edgeql/tracer.py b/edb/edgeql/tracer.py
--- a/edb/edgeql/tracer.py
+++ b/edb/edgeql/tracer.py
@@ -27,6 +27,7 @@
 import functools
 
 from contextlib import contextmanager
+from edb import errors
 from edb.schema import links as s_links
 from edb.schema import name as sn
 from edb.schema import objects as so
@@ -591,6 +592,14 @@ def trace_Constant(node: qlast.BaseConstant, *, ctx: TracerContext) -> None:
     pass
 
 
+@trace.register
+def trace_Parameter(node: qlast.Parameter, *, ctx: TracerContext) -> None:
+    raise errors.SchemaError(
+        'query parameters are not allowed in schemas',
+        span=node.span,
+    )
+
+
 @trace.register
 def trace_Array(node: qlast.Array, *, ctx: TracerContext) -> None:
     for el in node.elements:


Test patch:
diff --git a/tests/test_schema.py b/tests/test_schema.py
--- a/tests/test_schema.py
+++ b/tests/test_schema.py
@@ -2962,6 +2962,24 @@ def test_schema_incompatible_union_03(self):
         }
         """
 
+    @tb.must_fail(
+        errors.SchemaError,
+        "query parameters are not allowed in schemas",
+    )
+    def test_schema_query_parameter_01(self):
+        """
+        type Foo { foo := <int64>$0 }
+        """
+
+    @tb.must_fail(
+        errors.SchemaError,
+        "query parameters are not allowed in schemas",
+    )
+    def test_schema_query_parameter_02(self):
+        """
+        global foo := <int64>$0
+        """
+
 
 class TestGetMigration(tb.BaseSchemaLoadTest):
     """Test migration deparse consistency.