Commits

Kirill Simonov  committed 7d2e6fa

Updated bind error messages.

  • Participants
  • Parent commits ed8b514

Comments (0)

Files changed (9)

File src/htsql/tr/bind.py

 from ..adapter import Adapter, Protocol, adapts
 from ..domain import (BooleanDomain, IntegerDomain, DecimalDomain,
                       FloatDomain, UntypedDomain)
+from ..classify import relabel
 from .error import BindError
 from .syntax import (Syntax, QuerySyntax, SegmentSyntax, SelectorSyntax,
-                     ApplicationSyntax, OperatorSyntax, QuotientSyntax,
-                     SieveSyntax, LinkSyntax, HomeSyntax, AssignmentSyntax,
-                     SpecifierSyntax, FunctionSyntax, GroupSyntax,
+                     ApplicationSyntax, FunctionSyntax, MappingSyntax,
+                     OperatorSyntax, QuotientSyntax, SieveSyntax, LinkSyntax,
+                     HomeSyntax, AssignmentSyntax, SpecifierSyntax, GroupSyntax,
                      IdentifierSyntax, WildcardSyntax, ReferenceSyntax,
                      ComplementSyntax, StringSyntax, NumberSyntax)
 from .binding import (Binding, WrappingBinding, QueryBinding, SegmentBinding,
     def __call__(self):
         # FIXME: an empty segment syntax should not be generated.
         if self.syntax.branch is None:
-            raise BindError("empty segment", self.syntax.mark)
+            raise BindError("output columns are not specified",
+                            self.syntax.mark)
         # Bind the segment expression.
         seed = self.state.bind(self.syntax.branch)
         if lookup_command(seed) is not None:
         for binding in bindings:
             domain = coerce(binding.domain)
             if domain is None:
-                raise BindError("invalid element type", binding.mark)
+                raise BindError("output column must be a scalar value",
+                                binding.mark)
             element = CastBinding(binding, domain, binding.syntax)
             elements.append(element)
         # Complain on an empty selector.
         # FIXME: an empty selector should be valid.
         if not elements:
-            raise BindError("empty selector", self.syntax.mark)
+            raise BindError("output columns are not specified",
+                            self.syntax.mark)
         # Generate a binding node.
         return SegmentBinding(self.state.scope, seed, elements, self.syntax)
 
             binding = self.state.bind(branch)
             # Handle in-selector assignments.
             if isinstance(binding, AssignmentBinding):
-                if len(binding.terms) != 1 or binding.parameters is not None:
-                    raise BindError("invalid selector assignment",
+                if len(binding.terms) != 1:
+                    raise BindError("qualified definition is not allowed"
+                                    " for an in-selector assignment",
+                                    binding.mark)
+                if binding.parameters is not None:
+                    raise BindError("parameterized definition is not allowed"
+                                    " for an in-selector assignment",
                                     binding.mark)
                 name, is_reference = binding.terms[0]
                 if is_reference:
         for element in elements:
             domain = coerce(element.domain)
             if domain is None:
-                raise BindError("invalid element type", element.mark)
+                raise BindError("quotient column must be a scalar value",
+                                element.mark)
             kernel = CastBinding(element, domain, element.syntax)
             kernels.append(kernel)
         # Generate the quotient scope.
             target_images.append(binding)
         # Correlate origin and target images.
         if len(origin_images) != len(target_images):
-            raise BindError("unbalanced link", self.syntax.mark)
+            raise BindError("unbalanced origin and target columns",
+                            self.syntax.mark)
         images = []
         for origin_image, target_image in zip(origin_images, target_images):
             domain = coerce(origin_image.domain, target_image.domain)
             if domain is None:
-                raise BindError("incompatible images", self.syntax.mark)
+                raise BindError("cannot convert origin and target columns"
+                                " to a common type", self.syntax.mark)
             origin_image = CastBinding(origin_image, domain,
                                        origin_image.syntax)
             target_image = CastBinding(target_image, domain,
         # Get all public columns in the current lookup scope.
         recipies = expand(self.state.scope)
         if recipies is None:
-            raise BindError("unable to resolve a wildcard",
-                            self.syntax.mark)
+            raise BindError("cannot expand '*' since output columns"
+                            " are not defined", self.syntax.mark)
         # If a position is given, extract a specific element.
         if self.syntax.index is not None:
             try:
                 index = int(self.syntax.index.value)
             except ValueError:
-                raise BindError("an integer value is expected",
+                raise BindError("an integer value is required",
                                 self.syntax.mark)
             index -= 1
             if not (0 <= index < len(recipies)):
-                raise BindError("index is out of range",
-                                self.syntax.mark)
+                raise BindError("value in range 1-%s is required"
+                                % len(recipies), self.syntax.mark)
             syntax, recipe = recipies[index]
             syntax = syntax.clone(mark=self.syntax.mark)
             return self.state.use(recipe, syntax)
         recipe = lookup_reference(self.state.scope,
                                   self.syntax.identifier.value)
         if recipe is None:
-            raise BindError("unable to resolve a reference: %s"
+            raise BindError("unrecognized reference '%s'"
                             % self.syntax, self.syntax.mark)
         return self.state.use(recipe, self.syntax)
 
         # Look for a complement, complain if not found.
         recipe = lookup_complement(self.state.scope)
         if recipe is None:
-            raise BindError("expected a quotient context", self.syntax.mark)
+            raise BindError("'^' could only be used in a quotient scope",
+                            self.syntax.mark)
         return self.state.use(recipe, self.syntax)
 
 
 
     def __call__(self):
         # The default implementation; override in subclasses.
-        if isinstance(self.syntax, ApplicationSyntax):
-            raise BindError("unknown function %r" % self.name.encode('utf-8'),
+        if isinstance(self.syntax, (FunctionSyntax, MappingSyntax)):
+            raise BindError("unrecognized function '%s'"
+                            % self.syntax.identifier,
+                            self.syntax.mark)
+        if isinstance(self.syntax, OperatorSyntax):
+            raise BindError("unrecognized operator '%s'"
+                            % self.syntax.symbol.encode('utf-8'),
                             self.syntax.mark)
         if isinstance(self.syntax, IdentifierSyntax):
-            raise BindError("unknown attribute %r" % self.name.encode('utf-8'),
+            raise BindError("unrecognized attribute '%s'" % self.syntax,
                             self.syntax.mark)
 
 
                 arity = len(self.recipe.parameters)
             recipe = lookup_attribute(self.recipe.base, self.syntax.value)
             if recipe is None:
-                raise BindError("unknown attribute %r" % self.syntax,
+                raise BindError("unrecognized attribute '%s'" % self.syntax,
                                 self.syntax.mark)
             binding = self.state.use(recipe, self.syntax)
             # Check if the term is a reference.
     adapts(AmbiguousRecipe)
 
     def __call__(self):
-        raise BindError("ambiguous name", self.syntax.mark)
+        syntax = self.syntax
+        if isinstance(self.syntax, (FunctionSyntax, MappingSyntax)):
+            syntax = self.syntax.identifier
+        hint = None
+        if self.recipe.alternatives:
+            alternatives = self.recipe.alternatives
+            choices = ["try "]
+            if len(alternatives) == 1:
+                choices.append(repr(alternatives[0].encode('utf-8')))
+            else:
+                choices.extend(", ".join(repr(alternative.encode('utf-8'))
+                                         for alternative in alternatives[:-1]))
+                choices.append(" or ")
+                choices.append(repr(alternatives[-1].encode('utf-8')))
+            hint = "".join(choices)
+        raise BindError("ambiguous name '%s'" % self.syntax,
+                        self.syntax.mark, hint=hint)
 
 
 def bind(syntax, state=None, scope=None):

File src/htsql/tr/binding.py

     Generates an "ambiguous name" error when applied.
     """
 
+    def __init__(self, alternatives=None):
+        assert isinstance(alternatives, maybe(listof(unicode)))
+        super(AmbiguousRecipe, self).__init__()
+        self.alternatives = alternatives
 
+

File src/htsql/tr/lookup.py

 from ..adapter import Adapter, adapts, adapts_many
 from ..model import (HomeNode, TableNode, Arc, TableArc, ChainArc, ColumnArc,
                      SyntaxArc, AmbiguousArc)
-from ..classify import classify, normalize
+from ..classify import classify, relabel, normalize
 from .syntax import IdentifierSyntax
 from .binding import (Binding, ScopingBinding, ChainingBinding, WrappingBinding,
                       SegmentBinding, HomeBinding, RootBinding, TableBinding,
     adapts(AmbiguousArc)
 
     def __call__(self):
-        return AmbiguousRecipe()
+        alternatives = []
+        for arc in self.arc.alternatives:
+            labels = relabel(arc)
+            if labels:
+                alternatives.append(labels[0].name)
+        return AmbiguousRecipe(alternatives)
 
 
 class Lookup(Adapter):

File test/input/error.yaml

   - uri: /{count(school))
     expect: 400
 
+- title: Bind Errors
+  tests:
+  # empty selector
+  - uri: /retrieve(/)
+    expect: 400
+  - uri: /{}
+    expect: 400
+  # invalid output column
+  - uri: /department{school, code}
+    expect: 400
+  # invalid in-selector assignment
+  - uri: /school{code, num_dept():=count(department)}
+    expect: 400
+  - uri: /school{code, department.num_course:=count(course)}
+    expect: 400
+  # invalid quotient column
+  - uri: /department^school
+    expect: 400
+  - uri: /department^(num_course:=count(course))
+    expect: 400
+  # unbalanced columns
+  - uri: /program.{school_code,code}->school{code}
+    expect: 400
+  # invalid pairs
+  - uri: /program.{code}->course{no}
+    expect: 400
+  # invalid assignments
+  - uri: /define((school).num_prog:=count(program)).true()
+    expect: 400
+  - uri: /define(true().school.num_prog:=count(program)).true()
+    expect: 400
+  - uri: /define(school.num_prog(1):=count(program)).true()
+    expect: 400
+  - uri: /define(school.(num_prog):=count(program)).true()
+    expect: 400
+  # invalid wildcard
+  - uri: /{*}
+    expect: 400
+  - uri: /school?*1.5
+    expect: 400
+  - uri: /school?*5
+    expect: 400
+  # invalid reference
+  - uri: /school?$code='art'
+    expect: 400
+  # invalid complement
+  - uri: /school{code, count(^)}
+    expect: 400
+  # invalid names
+  - uri: /invalid
+    expect: 400
+  - uri: /invalid()
+    expect: 400
+  - uri: /school :invalid
+    expect: 400
+  - uri: /define(invalid.value:=true()).invalid{value}
+    expect: 400
+  # ambiguous name
+  - uri: /program.program
+    expect: 400
 
+

File test/output/mssql.yaml

           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: ambiguous name:
+            bind error: ambiguous name 'program':
                 /(program?school_code='la'&code='uengl').program
                                                          ^^^^^^^
+            (try 'part_of' or 'program_via_part_of')
         - uri: /(program?school_code='la'&code='uengl').part_of
           status: 200 OK
           headers:
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: ambiguous name:
+            bind error: ambiguous name 'prerequisite':
                 /(course?department_code='lang'&no=345).prerequisite
                                                         ^^^^^^^^^^^^
+            (try 'prerequisite_via_on_course' or 'prerequisite_via_of_course')
         - uri: /(course?department_code='lang'&no=345).prerequisite_via_on_course
           status: 200 OK
           headers:
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: ambiguous name:
+            bind error: ambiguous name 'course':
                 /(prerequisite?of_department_code='astro'&of_course_no=230 &on_department_code='phys'&on_course_no=130).course
                                                                                                                         ^^^^^^
+            (try 'on_course' or 'of_course')
         - uri: /(prerequisite?of_department_code='astro'&of_course_no=230 &on_department_code='phys'&on_course_no=130).of_course
           status: 200 OK
           headers:
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: ambiguous name:
+            bind error: ambiguous name 'classification':
                 /(classification?code='math').classification
                                               ^^^^^^^^^^^^^^
+            (try 'part_of' or 'classification_via_part_of')
         - uri: /(classification?code='math').part_of
           status: 200 OK
           headers:
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: unknown attribute 'level':
+            bind error: unrecognized attribute 'level':
                 /department.define(course(level) := course?no>=level*100 &no<(level+1)*100) {name, count(course(1)), count(course(2)), count(course(3)), count(course(4))}
                                                                ^^^^^
         - uri: /department.define(course($level) := course?no>=$level*100 &no<($level+1)*100)
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: unknown attribute 'instructor':
+            bind error: unrecognized attribute 'instructor':
                 /student.instructor
                          ^^^^^^^^^^
         - uri: /school?code='mus'
             headers:
             - [Content-Type, text/plain; charset=UTF-8]
             body: |
-              bind error: empty selector:
+              bind error: output columns are not specified:
                   /home()
                   ^^^^^^^
           - uri: /home(){2+2}
             headers:
             - [Content-Type, text/plain; charset=UTF-8]
             body: |
-              bind error: empty selector:
+              bind error: output columns are not specified:
                   /{}
                   ^^^
           - uri: /school{}
             headers:
             - [Content-Type, text/plain; charset=UTF-8]
             body: |
-              bind error: empty selector:
+              bind error: output columns are not specified:
                   /school{}
                   ^^^^^^^^^
         - id: assignments
             headers:
             - [Content-Type, text/plain; charset=UTF-8]
             body: |
-              bind error: unable to resolve a reference: $year:
+              bind error: unrecognized reference '$year':
                   /school.define(student_by_year($year) := program.student?year(dob)=$year) {code, student_by_year(1990).$year}
                                                                                                                          ^^^^^
           - uri: /define(f($x) := $x*2){{$x, f($x)} :where $x := 21}
             headers:
             - [Content-Type, text/plain; charset=UTF-8]
             body: |
-              bind error: invalid selector assignment:
+              bind error: qualified definition is not allowed for an in-selector assignment:
                   /school{code, program.num_stud := count(student)}
                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
         - id: projections
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: empty selector:
+            bind error: output columns are not specified:
                 /{}
                 ^^^
         - uri: /school{}
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: empty selector:
+            bind error: output columns are not specified:
                 /school{}
                 ^^^^^^^^^
         - uri: /school.true()
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: unknown attribute 'name':
+            bind error: unrecognized attribute 'name':
                 /department^school_code{school_code.name, name}
                                                     ^^^^
         - uri: /program.part_of.*
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: unknown function 'unknown':
+            bind error: unrecognized function 'unknown':
                 /school/:unknown
                 ^^^^^^^^^^^^^^^^
       - id: format-selection-by-`accept`
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: unknown attribute 'schema':
+            bind error: unrecognized attribute 'schema':
                 /meta(/schema)
                        ^^^^^^
         - uri: /meta(table)
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: unknown attribute 'department':
+            bind error: unrecognized attribute 'department':
                 /avg(school.count(department))
                                   ^^^^^^^^^^
         - uri: /avg(school.count(program))
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: unknown attribute 'department':
+            bind error: unrecognized attribute 'department':
                 /avg(school.count(department))
                                   ^^^^^^^^^^
         - uri: /avg(school.count(program))
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: unknown attribute 'department':
+            bind error: unrecognized attribute 'department':
                 /avg(school.count(department))
                                   ^^^^^^^^^^
         - uri: /count(program)
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: unknown attribute 'student':
+            bind error: unrecognized attribute 'student':
                 /count(student)
                        ^^^^^^^
         - uri: /school{code, count(department)}
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: unknown attribute 'enrollment':
+            bind error: unrecognized attribute 'enrollment':
                 /student{name, count(enrollment)}
                                      ^^^^^^^^^^
         - uri: /max(confidential.pay_grade)
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: unknown attribute 'ssn':
+            bind error: unrecognized attribute 'ssn':
                 /confidential.ssn
                               ^^^
         - uri: /student{name, dob, school.code, program.code, exists(instructor)}.limit(1)
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: unknown attribute 'classification':
+            bind error: unrecognized attribute 'classification':
                 /classification
                  ^^^^^^^^^^^^^^
         - uri: /active_students().limit(10)
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: unknown attribute 'active_students':
+            bind error: unrecognized attribute 'active_students':
                 /active_students
                  ^^^^^^^^^^^^^^^
         - uri: /active_students(2010)
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: unknown function 'active_students':
+            bind error: unrecognized function 'active_students':
                 /active_students(2010)
                  ^^^^^^^^^^^^^^^^^^^^^
         - uri: /students_by_year
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: unknown attribute 'students_by_year':
+            bind error: unrecognized attribute 'students_by_year':
                 /students_by_year
                  ^^^^^^^^^^^^^^^^
         - uri: /students_by_year()
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: unknown function 'students_by_year':
+            bind error: unrecognized function 'students_by_year':
                 /students_by_year()
                  ^^^^^^^^^^^^^^^^^^
         - uri: /program?exists(includes)
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: unknown attribute 'program_via_part_of':
+            bind error: unrecognized attribute 'program_via_part_of':
                 /program?exists(program_via_part_of)
                                 ^^^^^^^^^^^^^^^^^^^
         - uri: /student?count(class)>55
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: unknown attribute 'name':
+            bind error: unrecognized attribute 'name':
                 /student.name
                          ^^^^
         - uri: /(program?code='gart').active_students()
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: unknown attribute 'active_students':
+            bind error: unrecognized attribute 'active_students':
                 /program.active_students
                          ^^^^^^^^^^^^^^^
         - uri: /program.active_students(2010)
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: unknown function 'active_students':
+            bind error: unrecognized function 'active_students':
                 /program.active_students(2010)
                          ^^^^^^^^^^^^^^^^^^^^^
         - uri: /program.students_by_year
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: unknown attribute 'students_by_year':
+            bind error: unrecognized attribute 'students_by_year':
                 /program.students_by_year
                          ^^^^^^^^^^^^^^^^
         - uri: /program.students_by_year()
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: unknown function 'students_by_year':
+            bind error: unrecognized function 'students_by_year':
                 /program.students_by_year()
                          ^^^^^^^^^^^^^^^^^^
         - uri: /active_students{name, gender, start_date}.limit(5)
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: unknown function 'active_students':
+            bind error: unrecognized function 'active_students':
                 /active_students(2009, 'm', 'phd')
                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
         - uri: /(program?code='gart').active_students{name, gender, start_date}
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: unknown function 'active_students':
+            bind error: unrecognized function 'active_students':
                 /(program?code='gart').active_students(2009, 'm', 'phd')
                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
         - uri: /student{name}?count(class)>55
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: unknown attribute 'enrollment':
+            bind error: unrecognized attribute 'enrollment':
                 /enrollment
                  ^^^^^^^^^^
         - uri: /student.enrollment
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: unknown attribute 'enrollment':
+            bind error: unrecognized attribute 'enrollment':
                 /student.enrollment
                          ^^^^^^^^^^
         - uri: /student.id
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: unknown attribute 'id':
+            bind error: unrecognized attribute 'id':
                 /student.id
                          ^^
         - uri: /(student{name, dob}?date(start_date)>curr_date).limit(10)
             parse error: cannot find a matching '}':
                 /{count(school))
                  ^^^^^^^^^^^^^^
+      - id: bind-errors
+        tests:
+        - uri: /retrieve(/)
+          status: 400 Bad Request
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |
+            bind error: output columns are not specified:
+                /retrieve(/)
+                          ^
+        - uri: /{}
+          status: 400 Bad Request
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |
+            bind error: output columns are not specified:
+                /{}
+                ^^^
+        - uri: /department{school, code}
+          status: 400 Bad Request
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |
+            bind error: output column must be a scalar value:
+                /department{school, code}
+                            ^^^^^^
+        - uri: /school{code, num_dept():=count(department)}
+          status: 400 Bad Request
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |
+            bind error: parameterized definition is not allowed for an in-selector assignment:
+                /school{code, num_dept():=count(department)}
+                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+        - uri: /school{code, department.num_course:=count(course)}
+          status: 400 Bad Request
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |
+            bind error: qualified definition is not allowed for an in-selector assignment:
+                /school{code, department.num_course:=count(course)}
+                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+        - uri: /department^school
+          status: 400 Bad Request
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |
+            bind error: quotient column must be a scalar value:
+                /department^school
+                            ^^^^^^
+        - uri: /department^(num_course:=count(course))
+          status: 400 Bad Request
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |
+            bind error: quotient column must be a scalar value:
+                /department^(num_course:=count(course))
+                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+        - uri: /program.{school_code,code}->school{code}
+          status: 400 Bad Request
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |
+            bind error: unbalanced origin and target columns:
+                /program.{school_code,code}->school{code}
+                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+        - uri: /program.{code}->course{no}
+          status: 400 Bad Request
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |
+            bind error: cannot convert origin and target columns to a common type:
+                /program.{code}->course{no}
+                 ^^^^^^^^^^^^^^^^^^^^^^^^^^
+        - uri: /define((school).num_prog:=count(program)).true()
+          status: 400 Bad Request
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |
+            bind error: an identifier is expected:
+                /define((school).num_prog:=count(program)).true()
+                        ^^^^^^^^
+        - uri: /define(true().school.num_prog:=count(program)).true()
+          status: 400 Bad Request
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |
+            bind error: an identifier is expected:
+                /define(true().school.num_prog:=count(program)).true()
+                        ^^^^^^
+        - uri: /define(school.num_prog(1):=count(program)).true()
+          status: 400 Bad Request
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |
+            bind error: an identifier is expected:
+                /define(school.num_prog(1):=count(program)).true()
+                                        ^
+        - uri: /define(school.(num_prog):=count(program)).true()
+          status: 400 Bad Request
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |
+            bind error: an identifier is expected:
+                /define(school.(num_prog):=count(program)).true()
+                               ^^^^^^^^^^
+        - uri: /{*}
+          status: 400 Bad Request
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |
+            bind error: output columns are not specified:
+                /{*}
+                ^^^^
+        - uri: /school?*1.5
+          status: 400 Bad Request
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |
+            bind error: an integer value is required:
+                /school?*1.5
+                        ^^^^
+        - uri: /school?*5
+          status: 400 Bad Request
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |
+            bind error: value in range 1-3 is required:
+                /school?*5
+                        ^^
+        - uri: /school?$code='art'
+          status: 400 Bad Request
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |
+            bind error: unrecognized reference '$code':
+                /school?$code='art'
+                        ^^^^^
+        - uri: /school{code, count(^)}
+          status: 400 Bad Request
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |
+            bind error: '^' could only be used in a quotient scope:
+                /school{code, count(^)}
+                                    ^
+        - uri: /invalid
+          status: 400 Bad Request
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |
+            bind error: unrecognized attribute 'invalid':
+                /invalid
+                 ^^^^^^^
+        - uri: /invalid()
+          status: 400 Bad Request
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |
+            bind error: unrecognized function 'invalid':
+                /invalid()
+                 ^^^^^^^^^
+        - uri: /school :invalid
+          status: 400 Bad Request
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |
+            bind error: unrecognized function 'invalid':
+                /school :invalid
+                 ^^^^^^^^^^^^^^^
+        - uri: /define(invalid.value:=true()).invalid{value}
+          status: 400 Bad Request
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |
+            bind error: unrecognized attribute 'invalid':
+                /define(invalid.value:=true()).invalid{value}
+                                               ^^^^^^^
+        - uri: /program.program
+          status: 400 Bad Request
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |
+            bind error: ambiguous name 'program':
+                /program.program
+                         ^^^^^^^
+            (try 'part_of' or 'program_via_part_of')

File test/output/mysql.yaml

           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: ambiguous name:
+            bind error: ambiguous name 'program':
                 /(program?school_code='la'&code='uengl').program
                                                          ^^^^^^^
+            (try 'part_of' or 'program_via_part_of')
         - uri: /(program?school_code='la'&code='uengl').part_of
           status: 200 OK
           headers:
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: ambiguous name:
+            bind error: ambiguous name 'prerequisite':
                 /(course?department_code='lang'&no=345).prerequisite
                                                         ^^^^^^^^^^^^
+            (try 'prerequisite_via_of_course' or 'prerequisite_via_on_course')
         - uri: /(course?department_code='lang'&no=345).prerequisite_via_on_course
           status: 200 OK
           headers:
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: ambiguous name:
+            bind error: ambiguous name 'course':
                 /(prerequisite?of_department_code='astro'&of_course_no=230 &on_department_code='phys'&on_course_no=130).course
                                                                                                                         ^^^^^^
+            (try 'of_course' or 'on_course')
         - uri: /(prerequisite?of_department_code='astro'&of_course_no=230 &on_department_code='phys'&on_course_no=130).of_course
           status: 200 OK
           headers:
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: ambiguous name:
+            bind error: ambiguous name 'classification':
                 /(classification?code='math').classification
                                               ^^^^^^^^^^^^^^
+            (try 'part_of' or 'classification_via_part_of')
         - uri: /(classification?code='math').part_of
           status: 200 OK
           headers:
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: unknown attribute 'level':
+            bind error: unrecognized attribute 'level':
                 /department.define(course(level) := course?no>=level*100 &no<(level+1)*100) {name, count(course(1)), count(course(2)), count(course(3)), count(course(4))}
                                                                ^^^^^
         - uri: /department.define(course($level) := course?no>=$level*100 &no<($level+1)*100)
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: unknown attribute 'instructor':
+            bind error: unrecognized attribute 'instructor':
                 /student.instructor
                          ^^^^^^^^^^
         - uri: /school?code='mus'
             headers:
             - [Content-Type, text/plain; charset=UTF-8]
             body: |
-              bind error: empty selector:
+              bind error: output columns are not specified:
                   /home()
                   ^^^^^^^
           - uri: /home(){2+2}
             headers:
             - [Content-Type, text/plain; charset=UTF-8]
             body: |
-              bind error: empty selector:
+              bind error: output columns are not specified:
                   /{}
                   ^^^
           - uri: /school{}
             headers:
             - [Content-Type, text/plain; charset=UTF-8]
             body: |
-              bind error: empty selector:
+              bind error: output columns are not specified:
                   /school{}
                   ^^^^^^^^^
         - id: assignments
             headers:
             - [Content-Type, text/plain; charset=UTF-8]
             body: |
-              bind error: unable to resolve a reference: $year:
+              bind error: unrecognized reference '$year':
                   /school.define(student_by_year($year) := program.student?year(dob)=$year) {code, student_by_year(1990).$year}
                                                                                                                          ^^^^^
           - uri: /define(f($x) := $x*2){{$x, f($x)} :where $x := 21}
             headers:
             - [Content-Type, text/plain; charset=UTF-8]
             body: |
-              bind error: invalid selector assignment:
+              bind error: qualified definition is not allowed for an in-selector assignment:
                   /school{code, program.num_stud := count(student)}
                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
         - id: projections
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: empty selector:
+            bind error: output columns are not specified:
                 /{}
                 ^^^
         - uri: /school{}
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: empty selector:
+            bind error: output columns are not specified:
                 /school{}
                 ^^^^^^^^^
         - uri: /school.true()
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: unknown attribute 'name':
+            bind error: unrecognized attribute 'name':
                 /department^school_code{school_code.name, name}
                                                     ^^^^
         - uri: /program.part_of.*
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: unknown function 'unknown':
+            bind error: unrecognized function 'unknown':
                 /school/:unknown
                 ^^^^^^^^^^^^^^^^
       - id: format-selection-by-`accept`
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: unknown attribute 'schema':
+            bind error: unrecognized attribute 'schema':
                 /meta(/schema)
                        ^^^^^^
         - uri: /meta(table)
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: unknown attribute 'department':
+            bind error: unrecognized attribute 'department':
                 /avg(school.count(department))
                                   ^^^^^^^^^^
         - uri: /avg(school.count(program))
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: unknown attribute 'department':
+            bind error: unrecognized attribute 'department':
                 /avg(school.count(department))
                                   ^^^^^^^^^^
         - uri: /avg(school.count(program))
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: unknown attribute 'department':
+            bind error: unrecognized attribute 'department':
                 /avg(school.count(department))
                                   ^^^^^^^^^^
         - uri: /school{code, count(department)}
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: unknown attribute 'enrollment':
+            bind error: unrecognized attribute 'enrollment':
                 /student{name, count(enrollment)}
                                      ^^^^^^^^^^
         - uri: /max(confidential.pay_grade)
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: unknown attribute 'ssn':
+            bind error: unrecognized attribute 'ssn':
                 /confidential.ssn
                               ^^^
         - uri: /student{name, dob, school.code, program.code, exists(instructor)}.limit(1)
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: unknown attribute 'classification':
+            bind error: unrecognized attribute 'classification':
                 /classification
                  ^^^^^^^^^^^^^^
         - uri: /active_students().limit(10)
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: unknown attribute 'active_students':
+            bind error: unrecognized attribute 'active_students':
                 /active_students
                  ^^^^^^^^^^^^^^^
         - uri: /active_students(2010)
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: unknown function 'active_students':
+            bind error: unrecognized function 'active_students':
                 /active_students(2010)
                  ^^^^^^^^^^^^^^^^^^^^^
         - uri: /students_by_year
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: unknown attribute 'students_by_year':
+            bind error: unrecognized attribute 'students_by_year':
                 /students_by_year
                  ^^^^^^^^^^^^^^^^
         - uri: /students_by_year()
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: unknown function 'students_by_year':
+            bind error: unrecognized function 'students_by_year':
                 /students_by_year()
                  ^^^^^^^^^^^^^^^^^^
         - uri: /program?exists(includes)
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: unknown attribute 'program_via_part_of':
+            bind error: unrecognized attribute 'program_via_part_of':
                 /program?exists(program_via_part_of)
                                 ^^^^^^^^^^^^^^^^^^^
         - uri: /student?count(class)>55
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: unknown attribute 'name':
+            bind error: unrecognized attribute 'name':
                 /student.name
                          ^^^^
         - uri: /(program?code='gart').active_students()
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: unknown attribute 'active_students':
+            bind error: unrecognized attribute 'active_students':
                 /program.active_students
                          ^^^^^^^^^^^^^^^
         - uri: /program.active_students(2010)
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: unknown function 'active_students':
+            bind error: unrecognized function 'active_students':
                 /program.active_students(2010)
                          ^^^^^^^^^^^^^^^^^^^^^
         - uri: /program.students_by_year
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: unknown attribute 'students_by_year':
+            bind error: unrecognized attribute 'students_by_year':
                 /program.students_by_year
                          ^^^^^^^^^^^^^^^^
         - uri: /program.students_by_year()
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: unknown function 'students_by_year':
+            bind error: unrecognized function 'students_by_year':
                 /program.students_by_year()
                          ^^^^^^^^^^^^^^^^^^
         - uri: /active_students{name, gender, start_date}.limit(5)
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: unknown function 'active_students':
+            bind error: unrecognized function 'active_students':
                 /active_students(2009, 'm', 'phd')
                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
         - uri: /(program?code='gart').active_students{name, gender, start_date}
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: unknown function 'active_students':
+            bind error: unrecognized function 'active_students':
                 /(program?code='gart').active_students(2009, 'm', 'phd')
                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
         - uri: /student{name}?count(class)>55
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: unknown attribute 'enrollment':
+            bind error: unrecognized attribute 'enrollment':
                 /enrollment
                  ^^^^^^^^^^
         - uri: /student.enrollment
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: unknown attribute 'enrollment':
+            bind error: unrecognized attribute 'enrollment':
                 /student.enrollment
                          ^^^^^^^^^^
         - uri: /student.id
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: unknown attribute 'id':
+            bind error: unrecognized attribute 'id':
                 /student.id
                          ^^
         - uri: /(student{name, dob}?date(start_date)>curr_date).limit(10)
             parse error: cannot find a matching '}':
                 /{count(school))
                  ^^^^^^^^^^^^^^
+      - id: bind-errors
+        tests:
+        - uri: /retrieve(/)
+          status: 400 Bad Request
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |
+            bind error: output columns are not specified:
+                /retrieve(/)
+                          ^
+        - uri: /{}
+          status: 400 Bad Request
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |
+            bind error: output columns are not specified:
+                /{}
+                ^^^
+        - uri: /department{school, code}
+          status: 400 Bad Request
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |
+            bind error: output column must be a scalar value:
+                /department{school, code}
+                            ^^^^^^
+        - uri: /school{code, num_dept():=count(department)}
+          status: 400 Bad Request
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |
+            bind error: parameterized definition is not allowed for an in-selector assignment:
+                /school{code, num_dept():=count(department)}
+                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+        - uri: /school{code, department.num_course:=count(course)}
+          status: 400 Bad Request
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |
+            bind error: qualified definition is not allowed for an in-selector assignment:
+                /school{code, department.num_course:=count(course)}
+                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+        - uri: /department^school
+          status: 400 Bad Request
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |
+            bind error: quotient column must be a scalar value:
+                /department^school
+                            ^^^^^^
+        - uri: /department^(num_course:=count(course))
+          status: 400 Bad Request
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |
+            bind error: quotient column must be a scalar value:
+                /department^(num_course:=count(course))
+                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+        - uri: /program.{school_code,code}->school{code}
+          status: 400 Bad Request
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |
+            bind error: unbalanced origin and target columns:
+                /program.{school_code,code}->school{code}
+                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+        - uri: /program.{code}->course{no}
+          status: 400 Bad Request
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |
+            bind error: cannot convert origin and target columns to a common type:
+                /program.{code}->course{no}
+                 ^^^^^^^^^^^^^^^^^^^^^^^^^^
+        - uri: /define((school).num_prog:=count(program)).true()
+          status: 400 Bad Request
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |
+            bind error: an identifier is expected:
+                /define((school).num_prog:=count(program)).true()
+                        ^^^^^^^^
+        - uri: /define(true().school.num_prog:=count(program)).true()
+          status: 400 Bad Request
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |
+            bind error: an identifier is expected:
+                /define(true().school.num_prog:=count(program)).true()
+                        ^^^^^^
+        - uri: /define(school.num_prog(1):=count(program)).true()
+          status: 400 Bad Request
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |
+            bind error: an identifier is expected:
+                /define(school.num_prog(1):=count(program)).true()
+                                        ^
+        - uri: /define(school.(num_prog):=count(program)).true()
+          status: 400 Bad Request
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |
+            bind error: an identifier is expected:
+                /define(school.(num_prog):=count(program)).true()
+                               ^^^^^^^^^^
+        - uri: /{*}
+          status: 400 Bad Request
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |
+            bind error: output columns are not specified:
+                /{*}
+                ^^^^
+        - uri: /school?*1.5
+          status: 400 Bad Request
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |
+            bind error: an integer value is required:
+                /school?*1.5
+                        ^^^^
+        - uri: /school?*5
+          status: 400 Bad Request
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |
+            bind error: value in range 1-3 is required:
+                /school?*5
+                        ^^
+        - uri: /school?$code='art'
+          status: 400 Bad Request
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |
+            bind error: unrecognized reference '$code':
+                /school?$code='art'
+                        ^^^^^
+        - uri: /school{code, count(^)}
+          status: 400 Bad Request
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |
+            bind error: '^' could only be used in a quotient scope:
+                /school{code, count(^)}
+                                    ^
+        - uri: /invalid
+          status: 400 Bad Request
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |
+            bind error: unrecognized attribute 'invalid':
+                /invalid
+                 ^^^^^^^
+        - uri: /invalid()
+          status: 400 Bad Request
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |
+            bind error: unrecognized function 'invalid':
+                /invalid()
+                 ^^^^^^^^^
+        - uri: /school :invalid
+          status: 400 Bad Request
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |
+            bind error: unrecognized function 'invalid':
+                /school :invalid
+                 ^^^^^^^^^^^^^^^
+        - uri: /define(invalid.value:=true()).invalid{value}
+          status: 400 Bad Request
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |
+            bind error: unrecognized attribute 'invalid':
+                /define(invalid.value:=true()).invalid{value}
+                                               ^^^^^^^
+        - uri: /program.program
+          status: 400 Bad Request
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |
+            bind error: ambiguous name 'program':
+                /program.program
+                         ^^^^^^^
+            (try 'part_of' or 'program_via_part_of')

File test/output/oracle.yaml

           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: ambiguous name:
+            bind error: ambiguous name 'program':
                 /(program?school_code='la'&code='uengl').program
                                                          ^^^^^^^
+            (try 'part_of' or 'program_via_part_of')
         - uri: /(program?school_code='la'&code='uengl').part_of
           status: 200 OK
           headers:
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: ambiguous name:
+            bind error: ambiguous name 'prerequisite':
                 /(course?department_code='lang'&no=345).prerequisite
                                                         ^^^^^^^^^^^^
+            (try 'prerequisite_via_of_course' or 'prerequisite_via_on_course')
         - uri: /(course?department_code='lang'&no=345).prerequisite_via_on_course
           status: 200 OK
           headers:
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: ambiguous name:
+            bind error: ambiguous name 'course':
                 /(prerequisite?of_department_code='astro'&of_course_no=230 &on_department_code='phys'&on_course_no=130).course
                                                                                                                         ^^^^^^
+            (try 'of_course' or 'on_course')
         - uri: /(prerequisite?of_department_code='astro'&of_course_no=230 &on_department_code='phys'&on_course_no=130).of_course
           status: 200 OK
           headers:
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: ambiguous name:
+            bind error: ambiguous name 'classification':
                 /(classification?code='math').classification
                                               ^^^^^^^^^^^^^^
+            (try 'part_of' or 'classification_via_part_of')
         - uri: /(classification?code='math').part_of
           status: 200 OK
           headers:
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: unknown attribute 'level':
+            bind error: unrecognized attribute 'level':
                 /department.define(course(level) := course?no>=level*100 &no<(level+1)*100) {name, count(course(1)), count(course(2)), count(course(3)), count(course(4))}
                                                                ^^^^^
         - uri: /department.define(course($level) := course?no>=$level*100 &no<($level+1)*100)
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: unknown attribute 'instructor':
+            bind error: unrecognized attribute 'instructor':
                 /student.instructor
                          ^^^^^^^^^^
         - uri: /school?code='mus'
             headers:
             - [Content-Type, text/plain; charset=UTF-8]
             body: |
-              bind error: empty selector:
+              bind error: output columns are not specified:
                   /home()
                   ^^^^^^^
           - uri: /home(){2+2}
             headers:
             - [Content-Type, text/plain; charset=UTF-8]
             body: |
-              bind error: empty selector:
+              bind error: output columns are not specified:
                   /{}
                   ^^^
           - uri: /school{}
             headers:
             - [Content-Type, text/plain; charset=UTF-8]
             body: |
-              bind error: empty selector:
+              bind error: output columns are not specified:
                   /school{}
                   ^^^^^^^^^
         - id: assignments
             headers:
             - [Content-Type, text/plain; charset=UTF-8]
             body: |
-              bind error: unable to resolve a reference: $year:
+              bind error: unrecognized reference '$year':
                   /school.define(student_by_year($year) := program.student?year(dob)=$year) {code, student_by_year(1990).$year}
                                                                                                                          ^^^^^
           - uri: /define(f($x) := $x*2){{$x, f($x)} :where $x := 21}
             headers:
             - [Content-Type, text/plain; charset=UTF-8]
             body: |
-              bind error: invalid selector assignment:
+              bind error: qualified definition is not allowed for an in-selector assignment:
                   /school{code, program.num_stud := count(student)}
                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
         - id: projections
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: empty selector:
+            bind error: output columns are not specified:
                 /{}
                 ^^^
         - uri: /school{}
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: empty selector:
+            bind error: output columns are not specified:
                 /school{}
                 ^^^^^^^^^
         - uri: /school.true()
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: unknown attribute 'name':
+            bind error: unrecognized attribute 'name':
                 /department^school_code{school_code.name, name}
                                                     ^^^^
         - uri: /program.part_of.*
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: unknown function 'unknown':
+            bind error: unrecognized function 'unknown':
                 /school/:unknown
                 ^^^^^^^^^^^^^^^^
       - id: format-selection-by-`accept`
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: unknown attribute 'schema':
+            bind error: unrecognized attribute 'schema':
                 /meta(/schema)
                        ^^^^^^
         - uri: /meta(table)
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: unknown attribute 'department':
+            bind error: unrecognized attribute 'department':
                 /avg(school.count(department))
                                   ^^^^^^^^^^
         - uri: /avg(school.count(program))
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: unknown attribute 'department':
+            bind error: unrecognized attribute 'department':
                 /avg(school.count(department))
                                   ^^^^^^^^^^
         - uri: /avg(school.count(program))
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: unknown attribute 'department':
+            bind error: unrecognized attribute 'department':
                 /avg(school.count(department))
                                   ^^^^^^^^^^
         - uri: /school{code, count(department)}
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: unknown attribute 'enrollment':
+            bind error: unrecognized attribute 'enrollment':
                 /student{name, count(enrollment)}
                                      ^^^^^^^^^^
         - uri: /max(confidential.pay_grade)
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: unknown attribute 'ssn':
+            bind error: unrecognized attribute 'ssn':
                 /confidential.ssn
                               ^^^
         - uri: /student{name, dob, school.code, program.code, exists(instructor)}.limit(1)
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: unknown attribute 'classification':
+            bind error: unrecognized attribute 'classification':
                 /classification
                  ^^^^^^^^^^^^^^
         - uri: /active_students().limit(10)
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: unknown attribute 'active_students':
+            bind error: unrecognized attribute 'active_students':
                 /active_students
                  ^^^^^^^^^^^^^^^
         - uri: /active_students(2010)
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: unknown function 'active_students':
+            bind error: unrecognized function 'active_students':
                 /active_students(2010)
                  ^^^^^^^^^^^^^^^^^^^^^
         - uri: /students_by_year
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: unknown attribute 'students_by_year':
+            bind error: unrecognized attribute 'students_by_year':
                 /students_by_year
                  ^^^^^^^^^^^^^^^^
         - uri: /students_by_year()
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: unknown function 'students_by_year':
+            bind error: unrecognized function 'students_by_year':
                 /students_by_year()
                  ^^^^^^^^^^^^^^^^^^
         - uri: /program?exists(includes)
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: unknown attribute 'program_via_part_of':
+            bind error: unrecognized attribute 'program_via_part_of':
                 /program?exists(program_via_part_of)
                                 ^^^^^^^^^^^^^^^^^^^
         - uri: /student?count(class)>55
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: unknown attribute 'name':
+            bind error: unrecognized attribute 'name':
                 /student.name
                          ^^^^
         - uri: /(program?code='gart').active_students()
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: unknown attribute 'active_students':
+            bind error: unrecognized attribute 'active_students':
                 /program.active_students
                          ^^^^^^^^^^^^^^^
         - uri: /program.active_students(2010)
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: unknown function 'active_students':
+            bind error: unrecognized function 'active_students':
                 /program.active_students(2010)
                          ^^^^^^^^^^^^^^^^^^^^^
         - uri: /program.students_by_year
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: unknown attribute 'students_by_year':
+            bind error: unrecognized attribute 'students_by_year':
                 /program.students_by_year
                          ^^^^^^^^^^^^^^^^
         - uri: /program.students_by_year()
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: unknown function 'students_by_year':
+            bind error: unrecognized function 'students_by_year':
                 /program.students_by_year()
                          ^^^^^^^^^^^^^^^^^^
         - uri: /active_students{name, gender, start_date}.limit(5)
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: unknown function 'active_students':
+            bind error: unrecognized function 'active_students':
                 /active_students(2009, 'm', 'phd')
                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
         - uri: /(program?code='gart').active_students{name, gender, start_date}
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: unknown function 'active_students':
+            bind error: unrecognized function 'active_students':
                 /(program?code='gart').active_students(2009, 'm', 'phd')
                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
         - uri: /student{name}?count(class)>55
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: unknown attribute 'enrollment':
+            bind error: unrecognized attribute 'enrollment':
                 /enrollment
                  ^^^^^^^^^^
         - uri: /student.enrollment
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: unknown attribute 'enrollment':
+            bind error: unrecognized attribute 'enrollment':
                 /student.enrollment
                          ^^^^^^^^^^
         - uri: /student.id
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: unknown attribute 'id':
+            bind error: unrecognized attribute 'id':
                 /student.id
                          ^^
         - uri: /(student{name, dob}?date(start_date)>curr_date).limit(10)
             parse error: cannot find a matching '}':
                 /{count(school))
                  ^^^^^^^^^^^^^^
+      - id: bind-errors
+        tests:
+        - uri: /retrieve(/)
+          status: 400 Bad Request
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |
+            bind error: output columns are not specified:
+                /retrieve(/)
+                          ^
+        - uri: /{}
+          status: 400 Bad Request
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |
+            bind error: output columns are not specified:
+                /{}
+                ^^^
+        - uri: /department{school, code}
+          status: 400 Bad Request
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |
+            bind error: output column must be a scalar value:
+                /department{school, code}
+                            ^^^^^^
+        - uri: /school{code, num_dept():=count(department)}
+          status: 400 Bad Request
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |
+            bind error: parameterized definition is not allowed for an in-selector assignment:
+                /school{code, num_dept():=count(department)}
+                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+        - uri: /school{code, department.num_course:=count(course)}
+          status: 400 Bad Request
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |
+            bind error: qualified definition is not allowed for an in-selector assignment:
+                /school{code, department.num_course:=count(course)}
+                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+        - uri: /department^school
+          status: 400 Bad Request
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |
+            bind error: quotient column must be a scalar value:
+                /department^school
+                            ^^^^^^
+        - uri: /department^(num_course:=count(course))
+          status: 400 Bad Request
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |
+            bind error: quotient column must be a scalar value:
+                /department^(num_course:=count(course))
+                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+        - uri: /program.{school_code,code}->school{code}
+          status: 400 Bad Request
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |
+            bind error: unbalanced origin and target columns:
+                /program.{school_code,code}->school{code}
+                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+        - uri: /program.{code}->course{no}
+          status: 400 Bad Request
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |
+            bind error: cannot convert origin and target columns to a common type:
+                /program.{code}->course{no}
+                 ^^^^^^^^^^^^^^^^^^^^^^^^^^
+        - uri: /define((school).num_prog:=count(program)).true()
+          status: 400 Bad Request
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |
+            bind error: an identifier is expected:
+                /define((school).num_prog:=count(program)).true()
+                        ^^^^^^^^
+        - uri: /define(true().school.num_prog:=count(program)).true()
+          status: 400 Bad Request
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |
+            bind error: an identifier is expected:
+                /define(true().school.num_prog:=count(program)).true()
+                        ^^^^^^
+        - uri: /define(school.num_prog(1):=count(program)).true()
+          status: 400 Bad Request
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |
+            bind error: an identifier is expected:
+                /define(school.num_prog(1):=count(program)).true()
+                                        ^
+        - uri: /define(school.(num_prog):=count(program)).true()
+          status: 400 Bad Request
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |
+            bind error: an identifier is expected:
+                /define(school.(num_prog):=count(program)).true()
+                               ^^^^^^^^^^
+        - uri: /{*}
+          status: 400 Bad Request
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |
+            bind error: output columns are not specified:
+                /{*}
+                ^^^^
+        - uri: /school?*1.5
+          status: 400 Bad Request
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |
+            bind error: an integer value is required:
+                /school?*1.5
+                        ^^^^
+        - uri: /school?*5
+          status: 400 Bad Request
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |
+            bind error: value in range 1-3 is required:
+                /school?*5
+                        ^^
+        - uri: /school?$code='art'
+          status: 400 Bad Request
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |
+            bind error: unrecognized reference '$code':
+                /school?$code='art'
+                        ^^^^^
+        - uri: /school{code, count(^)}
+          status: 400 Bad Request
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |
+            bind error: '^' could only be used in a quotient scope:
+                /school{code, count(^)}
+                                    ^
+        - uri: /invalid
+          status: 400 Bad Request
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |
+            bind error: unrecognized attribute 'invalid':
+                /invalid
+                 ^^^^^^^
+        - uri: /invalid()
+          status: 400 Bad Request
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |
+            bind error: unrecognized function 'invalid':
+                /invalid()
+                 ^^^^^^^^^
+        - uri: /school :invalid
+          status: 400 Bad Request
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |
+            bind error: unrecognized function 'invalid':
+                /school :invalid
+                 ^^^^^^^^^^^^^^^
+        - uri: /define(invalid.value:=true()).invalid{value}
+          status: 400 Bad Request
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |
+            bind error: unrecognized attribute 'invalid':
+                /define(invalid.value:=true()).invalid{value}
+                                               ^^^^^^^
+        - uri: /program.program
+          status: 400 Bad Request
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |
+            bind error: ambiguous name 'program':
+                /program.program
+                         ^^^^^^^
+            (try 'part_of' or 'program_via_part_of')

File test/output/pgsql.yaml

           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: ambiguous name:
+            bind error: ambiguous name 'program':
                 /(program?school_code='la'&code='uengl').program
                                                          ^^^^^^^
+            (try 'part_of' or 'program_via_part_of')
         - uri: /(program?school_code='la'&code='uengl').part_of
           status: 200 OK
           headers:
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: ambiguous name:
+            bind error: ambiguous name 'prerequisite':
                 /(course?department_code='lang'&no=345).prerequisite
                                                         ^^^^^^^^^^^^
+            (try 'prerequisite_via_on_course' or 'prerequisite_via_of_course')
         - uri: /(course?department_code='lang'&no=345).prerequisite_via_on_course
           status: 200 OK
           headers:
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: ambiguous name:
+            bind error: ambiguous name 'course':
                 /(prerequisite?of_department_code='astro'&of_course_no=230 &on_department_code='phys'&on_course_no=130).course
                                                                                                                         ^^^^^^
+            (try 'on_course' or 'of_course')
         - uri: /(prerequisite?of_department_code='astro'&of_course_no=230 &on_department_code='phys'&on_course_no=130).of_course
           status: 200 OK
           headers:
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: ambiguous name:
+            bind error: ambiguous name 'classification':
                 /(classification?code='math').classification
                                               ^^^^^^^^^^^^^^
+            (try 'part_of' or 'classification_via_part_of')
         - uri: /(classification?code='math').part_of
           status: 200 OK
           headers:
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: unknown attribute 'level':
+            bind error: unrecognized attribute 'level':
                 /department.define(course(level) := course?no>=level*100 &no<(level+1)*100) {name, count(course(1)), count(course(2)), count(course(3)), count(course(4))}
                                                                ^^^^^
         - uri: /department.define(course($level) := course?no>=$level*100 &no<($level+1)*100)
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: unknown attribute 'instructor':
+            bind error: unrecognized attribute 'instructor':
                 /student.instructor
                          ^^^^^^^^^^
         - uri: /school?code='mus'
             headers:
             - [Content-Type, text/plain; charset=UTF-8]
             body: |
-              bind error: empty selector:
+              bind error: output columns are not specified:
                   /home()
                   ^^^^^^^
           - uri: /home(){2+2}
             headers:
             - [Content-Type, text/plain; charset=UTF-8]
             body: |
-              bind error: empty selector:
+              bind error: output columns are not specified:
                   /{}
                   ^^^
           - uri: /school{}
             headers:
             - [Content-Type, text/plain; charset=UTF-8]
             body: |
-              bind error: empty selector:
+              bind error: output columns are not specified:
                   /school{}
                   ^^^^^^^^^
         - id: assignments
             headers:
             - [Content-Type, text/plain; charset=UTF-8]
             body: |
-              bind error: unable to resolve a reference: $year:
+              bind error: unrecognized reference '$year':
                   /school.define(student_by_year($year) := program.student?year(dob)=$year) {code, student_by_year(1990).$year}
                                                                                                                          ^^^^^
           - uri: /define(f($x) := $x*2){{$x, f($x)} :where $x := 21}
             headers:
             - [Content-Type, text/plain; charset=UTF-8]
             body: |
-              bind error: invalid selector assignment:
+              bind error: qualified definition is not allowed for an in-selector assignment:
                   /school{code, program.num_stud := count(student)}
                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
         - id: projections
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: empty selector:
+            bind error: output columns are not specified:
                 /{}
                 ^^^
         - uri: /school{}
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: empty selector:
+            bind error: output columns are not specified:
                 /school{}
                 ^^^^^^^^^
         - uri: /school.true()
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: unknown attribute 'name':
+            bind error: unrecognized attribute 'name':
                 /department^school_code{school_code.name, name}
                                                     ^^^^
         - uri: /program.part_of.*
           headers:
           - [Content-Type, text/plain; charset=UTF-8]
           body: |
-            bind error: unknown function 'unknown':
+            bind error: unrecognized function 'unknown':
                 /school/:unknown
                 ^^^^^^^^^^^^^^^^
       - id: format-selection-by-`accept`
           headers: