Errors in ADQL BNF

Walter Landry wlandry at caltech.edu
Fri Oct 21 19:54:07 CEST 2016


Hi Everyone,

I just ran the ADQL 2.0 BNF through the bnf checker at

  http://www.icosaedro.it/bnf_chk/bnf_chk-on-line.html

I took what was at

  http://wiki.ivoa.net/internal/IVOA/IvoaVOQL/adql-bnf-v2.0.htm

and converted it into a real EBNF.  That includes

1) Get rid of the angle brackets <> around the rule names
2) Change '::=' to '='.
3) Quote all of the characters and strings with double quotes ""
   except for <double_quote>, which become "\"".
4) Remove the comments
5) Change all instances of xyzzy... to {xyzzy}

The errors I found are below.  I am attaching the real, corrected EBNF
grammar.

Cheers,
Walter Landry


1)  <boolean_primary> ::=
     | <left_paren> <search_condition> <right_paren> 
       <predicate> 

  should be

    <boolean_primary> ::=
     | <left_paren> <search_condition> <right_paren> 
       <predicate> 

  (Honestly, you really do not need the parentheses anyway.)

2) <default_function_prefix> ::=
   !! The prefix is set by default to "udf_".
   !! It should be possible to change the default prefix to accommodate local preferences.

  This should be

   default_function_prefix = "udf_";

3) <newline> ::= 
   !! Implementation defined end of line indicator

  This should probably just be defined ar "\n"

4) <nondoublequote_character> ::= 
   !! See SQL92 syntax rules. But basically what it says.

   <nonquote_character> ::= 
  !! One ASCII character but not a single quote 

  These should be nailed down.  I define

  <SQL_language_character> ::= <alnum> | <SQL_special_character>

  and then the rule becomes
  
  <nondoublequote_character> ::= <SQL_language_character> - <double_quote>
  <nonquote_character> ::= <SQL_language_character> - <quote>;

5) <polygon> ::=
      POLYGON <left_paren> <coord_sys> 
                   <comma> <coordinates> 
                   <comma> <coordinates> 
                 { <comma> <coordinates> } ?
              <right_paren>

  It should not have the question mark '?'

6) <unqualified_schema name> ::= <identifier>

  should be

  <unqualified_schema_name> ::= <identifier>


-------------- next part --------------
ADQL_language_character =
      simple_Latin_letter
    | digit
    | SQL_special_character;

  ADQL_reserved_word =
      "ABS"
    | "ACOS"
    | "AREA"
    | "ASIN"
    | "ATAN"
    | "ATAN2"
    | "BOX"
    | "CEILING"
    | "CENTROID"
    | "CIRCLE"
    | "CONTAINS"
    | "COORD1"
    | "COORD2"
    | "COORDSYS"
    | "COS"
    | "DEGREES"
    | "DISTANCE"
    | "EXP"
    | "FLOOR"
    | "INTERSECTS"
    | "LOG"
    | "LOG10"
    | "MOD"
    | "PI"
    | "POINT"
    | "POLYGON"
    | "POWER"
    | "RADIANS"
    | "REGION"
    | "RAND"
    | "ROUND"
    | "SIN"
    | "SQRT"
    | "TOP"
    | "TAN"
    | "TRUNCATE";

  SQL_embedded_language_character =
      left_bracket
    | right_bracket;

  SQL_reserved_word =
     "ABSOLUTE" | "ACTION" | "ADD" | "ALL"
   | "ALLOCATE" | "ALTER" | "AND" 
   | "ANY" | "ARE" 
   | "AS" | "ASC" 
   | "ASSERTION" | "AT" 
   | "AUTHORIZATION" | "AVG" 
   | "BEGIN" | "BETWEEN" | "BIT" | "BIT_LENGTH"
   | "BOTH" | "BY" 
   | "CASCADE" | "CASCADED" | "CASE" | "CAST" 
   | "CATALOG" 
   | "CHAR" | "CHARACTER" | "CHAR_LENGTH"
   | "CHARACTER_LENGTH" | "CHECK" | "CLOSE" | "COALESCE" 
   | "COLLATE" | "COLLATION" 
   | "COLUMN" | "COMMIT" 
   | "CONNECT" 
   | "CONNECTION" | "CONSTRAINT" 
   | "CONSTRAINTS" | "CONTINUE" 
   | "CONVERT" | "CORRESPONDING" | "COUNT" | "CREATE" | "CROSS" 
   | "CURRENT" 
   | "CURRENT_DATE" | "CURRENT_TIME"
   | "CURRENT_TIMESTAMP" | "CURRENT_USER" | "CURSOR" 
   | "DATE" | "DAY" | "DEALLOCATE" 
   | "DECIMAL" | "DECLARE" | "DEFAULT" | "DEFERRABLE" 
   | "DEFERRED" | "DELETE" | "DESC" | "DESCRIBE" | "DESCRIPTOR" 
   | "DIAGNOSTICS" 
   | "DISCONNECT" | "DISTINCT" | "DOMAIN" | "DOUBLE" | "DROP" 
   | "ELSE" | "END" | "END-EXEC" | "ESCAPE" 
   | "EXCEPT" | "EXCEPTION" 
   | "EXEC" | "EXECUTE" | "EXISTS" 
   | "EXTERNAL" | "EXTRACT" 
   | "FALSE" | "FETCH" | "FIRST" | "FLOAT" | "FOR" 
   | "FOREIGN" | "FOUND" | "FROM" | "FULL" 
   | "GET" | "GLOBAL" | "GO" | "GOTO" 
   | "GRANT" | "GROUP" 
   | "HAVING" | "HOUR" 
   | "IDENTITY" | "IMMEDIATE" | "IN" | "INDICATOR" 
   | "INITIALLY" | "INNER" | "INPUT" 
   | "INSENSITIVE" | "INSERT" | "INT" | "INTEGER" | "INTERSECT" 
   | "INTERVAL" | "INTO" | "IS" 
   | "ISOLATION" 
   | "JOIN" 
   | "KEY" 
   | "LANGUAGE" | "LAST" | "LEADING" | "LEFT" 
   | "LEVEL" | "LIKE" | "LOCAL" | "LOWER" 
   | "MATCH" | "MAX" | "MIN" | "MINUTE" | "MODULE" 
   | "MONTH" 
   | "NAMES" | "NATIONAL" | "NATURAL" | "NCHAR" | "NEXT" | "NO" 
   | "NOT" | "NULL" 
   | "NULLIF" | "NUMERIC" 
   | "OCTET_LENGTH" | "OF" 
   | "ON" | "ONLY" | "OPEN" | "OPTION" | "OR" 
   | "ORDER" | "OUTER" 
   | "OUTPUT" | "OVERLAPS" 
   | "PAD" | "PARTIAL" | "POSITION" | "PRECISION" | "PREPARE" 
   | "PRESERVE" | "PRIMARY" 
   | "PRIOR" | "PRIVILEGES" | "PROCEDURE" | "PUBLIC" 
   | "READ" | "REAL" | "REFERENCES" | "RELATIVE" | "RESTRICT" 
   | "REVOKE" | "RIGHT" 
   | "ROLLBACK" | "ROWS" 
   | "SCHEMA" | "SCROLL" | "SECOND" | "SECTION" 
   | "SELECT" 
   | "SESSION" | "SESSION_USER" | "SET" 
   | "SIZE" | "SMALLINT" | "SOME" | "SPACE" | "SQL" | "SQLCODE" 
   | "SQLERROR" | "SQLSTATE" 
   | "SUBSTRING" | "SUM" | "SYSTEM_USER"
   | "TABLE" | "TEMPORARY" 
   | "THEN" | "TIME" | "TIMESTAMP" 
   | "TIMEZONE_HOUR" | "TIMEZONE_MINUTE"
   | "TO" | "TRAILING" | "TRANSACTION" 
   | "TRANSLATE" | "TRANSLATION" | "TRIM" | "TRUE" 
   | "UNION" | "UNIQUE" | "UNKNOWN" | "UPDATE" | "UPPER" | "USAGE" 
   | "USER" | "USING" 
   | "VALUE" | "VALUES" | "VARCHAR" | "VARYING" | "VIEW" 
   | "WHEN" | "WHENEVER" | "WHERE" | "WITH" | "WORK" | "WRITE" 
   | "YEAR" 
   | "ZONE";

  SQL_special_character =
     space
   | double_quote
   | percent
   | ampersand
   | quote
   | left_paren
   | right_paren
   | asterisk
   | plus_sign
   | comma
   | minus_sign
   | period
   | solidus
   | colon
   | semicolon
   | less_than_operator
   | equals_operator
   | greater_than_operator
   | question_mark
   | underscore
   | vertical_bar;

  ampersand = "&";

  approximate_numeric_literal = mantissa "E" exponent;

  area = "AREA" left_paren geometry_value_expression right_paren;

  as_clause = [ "AS" ] column_name;

  asterisk = "*";

  between_predicate =
     value_expression [ "NOT" ] "BETWEEN"
     value_expression "AND" value_expression;

  boolean_factor = [ "NOT" ] boolean_primary;

  boolean_primary =
       predicate
     | left_paren search_condition right_paren;

  boolean_term =
      boolean_factor
    | boolean_term AND boolean_factor;

  box = 
      "BOX" left_paren coord_sys
                     comma coordinates 
                     comma numeric_value_expression 
                     comma numeric_value_expression 
                right_paren;

  catalog_name = identifier;

  centroid = "CENTROID" left_paren geometry_value_expression right_paren;

  character_factor = character_primary;

  character_primary = 
      value_expression_primary
    | string_value_function;

  character_representation = nonquote_character | quote_symbol;

  character_string_literal =
     quote [ {character_representation} ] quote
     [ { {separator} quote [{character_representation}] quote } ];

  character_value_expression = concatenation | character_factor;

  circle = 
      "CIRCLE" left_paren coord_sys 
                  comma coordinates 
                  comma radius 
             right_paren;

  colon = ":";

  column_name = identifier;

  column_name_list = column_name { comma column_name };

  column_reference = [ qualifier period ] column_name;

  comma = ",";

  comment = comment_introducer [ {comment_character} ] newline;

  comment_character = nonquote_character | quote;

  comment_introducer = minus_sign minus_sign [{minus_sign}];

  comp_op =
      equals_operator
    | not_equals_operator
    | less_than_operator
    | greater_than_operator
    | less_than_or_equals_operator
    | greater_than_or_equals_operator;

  comparison_predicate =
      value_expression comp_op value_expression;

  concatenation = character_value_expression concatenation_operator character_factor;

  concatenation_operator = "||";

  contains = "CONTAINS" left_paren geometry_value_expression comma geometry_value_expression right_paren  ;

  coord1 = "COORD1" left_paren coord_value right_paren;

  coord2 = "COORD2" left_paren coord_value right_paren;

  coord_sys = string_value_expression;

  coord_value = point | column_reference;

  coordinate1 = numeric_value_expression;

  coordinate2 = numeric_value_expression;

  coordinates =  coordinate1  comma  coordinate2 ;

  correlation_name = identifier;

  correlation_specification = [ "AS" ] correlation_name;

  default_function_prefix = "udf_";

  delimited_identifier = double_quote delimited_identifier_body double_quote;

  delimited_identifier_body = {delimited_identifier_part};

  delimited_identifier_part = nondoublequote_character | double_quote_symbol;

  delimiter_token =
        character_string_literal
    |   delimited_identifier
    |   SQL_special_character
    |   not_equals_operator
    |   greater_than_or_equals_operator
    |   less_than_or_equals_operator
    |   concatenation_operator
    |   double_period
    |   left_bracket
    |   right_bracket;

  derived_column = value_expression [ as_clause ];

  derived_table = table_subquery;

  digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9";

  distance =     
     "DISTANCE" left_paren coord_value comma coord_value right_paren;

  double_period = "..";

  double_quote = "\"";

  double_quote_symbol = double_quote double_quote;

  equals_operator = "=";

  exact_numeric_literal =
      unsigned_integer [ period [ unsigned_integer ] ]
    | period unsigned_integer;

  exists_predicate = "EXISTS" table_subquery;

  exponent = signed_integer ;

  extract_coordsys = "COORDSYS" left_paren geometry_value_expression right_paren;

  factor = [ sign ] numeric_primary ;

  from_clause = "FROM" table_reference
     [ { comma table_reference } ];

  general_literal = character_string_literal;

  general_set_function =
     set_function_type left_paren [ set_quantifier ] value_expression right_paren;

  geometry_value_expression = value_expression_primary | geometry_value_function;

  geometry_value_function =
       box 
     | centroid 
     | circle 
     | point 
     | polygon 
     | region ;

  greater_than_operator = ">";

  greater_than_or_equals_operator = ">=";

  group_by_clause = "GROUP" "BY" grouping_column_reference_list;

  grouping_column_reference = column_reference;

  grouping_column_reference_list =
      grouping_column_reference [ { comma grouping_column_reference } ];

  having_clause = "HAVING" search_condition ;

  identifier = regular_identifier | delimited_identifier;

  in_predicate =
      value_expression [ "NOT" ] "IN" in_predicate_value;

  in_predicate_value =
     table_subquery | left_paren in_value_list right_paren;

  in_value_list =
      value_expression { comma value_expression };

  intersects = "INTERSECTS" left_paren geometry_value_expression comma geometry_value_expression right_paren;

  join_column_list = column_name_list;

  join_condition = "ON" search_condition;

  join_specification = join_condition | named_columns_join	;

  join_type =
     "INNER"
   | outer_join_type [ "OUTER" ];

  joined_table =
      qualified_join
    | left_paren joined_table right_paren;

  keyword = SQL_reserved_word | ADQL_reserved_word;

  left_bracket = "[";

  left_paren = "(";

  less_than_operator = "<";

  less_than_or_equals_operator = "<=";

  like_predicate =
      match_value [ "NOT" ] "LIKE" pattern;

  mantissa = exact_numeric_literal;

  match_value = character_value_expression;

  math_function =
      "ABS" left_paren numeric_value_expression right_paren 
	  | "CEILING" left_paren numeric_value_expression right_paren 
	  | "DEGREES" left_paren numeric_value_expression right_paren 
	  | "EXP" left_paren numeric_value_expression right_paren 
	  | "FLOOR" left_paren numeric_value_expression right_paren 
	  | "LOG" left_paren numeric_value_expression right_paren 
	  | "LOG10" left_paren numeric_value_expression right_paren 	  
	  | "MOD" left_paren numeric_value_expression comma numeric_value_expression right_paren 	  
	  | "PI" left_paren right_paren 
	  | "POWER" left_paren numeric_value_expression comma numeric_value_expression right_paren 
	  | "RADIANS" left_paren numeric_value_expression right_paren 
	  | "RAND" left_paren [ numeric_value_expression ] right_paren 
	  | "ROUND" left_paren numeric_value_expression [comma signed_integer] right_paren 
	  | "SQRT" left_paren numeric_value_expression right_paren 
	  | "TRUNCATE" left_paren numeric_value_expression [comma signed_integer] right_paren ;

  minor_radius = numeric_value_expression;

  minus_sign = "-";

  named_columns_join = "USING" left_paren join_column_list right_paren ;

  newline = "\n";

  non_predicate_geometry_function = 
     area
   | coord1
   | coord2 
   | distance;

  nondelimiter_token = 
      regular_identifier
    | keyword
    | unsigned_numeric_literal;


  SQL_language_character = alnum | SQL_special_character;
  nondoublequote_character = SQL_language_character except_symbol double_quote;

  nonquote_character = SQL_language_character except_symbol quote;

  not_equals_operator = not_equals_operator1 | not_equals_operator2;

  not_equals_operator1 = "<>";

  not_equals_operator2 = "!=";

  null_predicate = column_reference "IS" [ "NOT" ] "NULL";

  numeric_geometry_function =
      predicate_geometry_function | non_predicate_geometry_function;

  numeric_primary =
      value_expression_primary
    | numeric_value_function;

  numeric_value_expression =
      term
    | numeric_value_expression plus_sign term
    | numeric_value_expression minus_sign term;

  numeric_value_function = 
     trig_function 
   | math_function	
   | numeric_geometry_function
   | user_defined_function;

  order_by_clause = "ORDER" "BY" sort_specification_list;

  ordering_specification = "ASC" | "DESC";

  outer_join_type = "LEFT" | "RIGHT" | "FULL";

  pattern = character_value_expression;

  percent = "%";

  period = ".";

  plus_sign = "+";

  point = "POINT" left_paren coord_sys comma coordinates right_paren;

  polygon =
      "POLYGON" left_paren coord_sys 
                   comma coordinates 
                   comma coordinates 
                 { comma coordinates }
              right_paren;

  predicate =
     comparison_predicate
   | between_predicate
   | in_predicate
   | like_predicate
   | null_predicate
   | exists_predicate;


  predicate_geometry_function = contains | intersects;

  qualified_join =
      table_reference [ "NATURAL" ] [ join_type ] "JOIN"
      table_reference [ join_specification ];

  qualifier = table_name | correlation_name ;

  query_expression =
       query_specification
     | joined_table;

  query_specification =
      "SELECT" [ set_quantifier ] [ set_limit ] select_list table_expression;

  question_mark = "?";

  quote = "'";

  quote_symbol = quote quote;

  radius = numeric_value_expression;

  region = "REGION" left_paren string_value_expression right_paren;

  regular_identifier =
      {simple_Latin_letter} 
      [ { digit | simple_Latin_letter | underscore } ];

  right_bracket = "]";

  right_paren = ")";

  schema_name = [ catalog_name period ] unqualified_schema name;

  search_condition =
      boolean_term
    | search_condition "OR" boolean_term;

  select_list =
      asterisk
    | select_sublist [ { comma select_sublist } ];

  select_sublist = derived_column | qualifier period asterisk;

  semicolon = ";";

  separator = { comment | space | newline };

  set_function_specification =
      "COUNT" left_paren asterisk right_paren
    | general_set_function;

  set_function_type = "AVG" | "MAX" | "MIN" | "SUM" | "COUNT";

  set_limit = "TOP" unsigned_integer;

  set_quantifier = "DISTINCT" | "ALL";

  sign = plus_sign | minus_sign;

  signed_integer = [ sign ] unsigned_integer;

  simple_Latin_letter =
      simple_Latin_upper_case_letter
    | simple_Latin_lower_case_letter;

  simple_Latin_lower_case_letter =
      "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" | "j" | "k" | "l" | "m" | "n" | "o"
    | "p" | "q" | "r" | "s" | "t" | "u" | "v" | "w" | "x" | "y" | "z";

  simple_Latin_upper_case_letter =
      "A" | "B" | "C" | "D" | "E" | "F" | "G" | "H" | "I" | "J" | "K" | "L" | "M" | "N" | "O"
    | "P" | "Q" | "R" | "S" | "T" | "U" | "V" | "W" | "X" | "Y" | "Z";

  solidus = "/";

  sort_key = column_name | unsigned_integer;

  sort_specification =
      sort_key [ ordering_specification ];

  sort_specification_list =
      sort_specification [ { comma sort_specification } ];

  space =" ";

  string_geometry_function = extract_coordsys;

  string_value_expression =
      character_value_expression;

  string_value_function = string_geometry_function | user_defined_function;

  subquery = left_paren query_expression right_paren;

  table_expression =
      from_clause
      [ where_clause ]
      [ group_by_clause ]
      [ having_clause ]
      [ order_by_clause ];

  table_name = [ schema_name period ] identifier;

  table_reference =
     table_name [ correlation_specification ]
   | derived_table correlation_specification
   | joined_table;

  table_subquery = subquery;

  term =
      factor
    | term asterisk factor
    | term solidus factor;

  token = 
      nondelimiter_token
    | delimiter_token;

  trig_function =
      "ACOS" left_paren numeric_value_expression right_paren
    | "ASIN" left_paren numeric_value_expression right_paren
    | "ATAN" left_paren numeric_value_expression right_paren
    | "ATAN2" left_paren numeric_value_expression comma numeric_value_expression right_paren
    | "COS" left_paren numeric_value_expression right_paren
    | "COT" left_paren numeric_value_expression right_paren
    | "SIN" left_paren numeric_value_expression right_paren
    | "TAN" left_paren numeric_value_expression right_paren;

  underscore = "_";

  unqualified_schema_name = identifier;

  unsigned_integer = {digit};

  unsigned_literal = unsigned_numeric_literal | general_literal;

  unsigned_numeric_literal =
     exact_numeric_literal
   | approximate_numeric_literal;

  unsigned_value_specification = unsigned_literal;

  user_defined_function =
      user_defined_function_name 
          left_paren 
              [ user_defined_function_param [ { comma user_defined_function_param } ] ]
          right_paren ;

  user_defined_function_name =
       [ default_function_prefix ] regular_identifier;

  user_defined_function_param = value_expression;

  value_expression =
      numeric_value_expression
    | string_value_expression
    | geometry_value_expression;

  value_expression_primary =
      unsigned_value_specification
    | column_reference
    | set_function_specification
    | left_paren value_expression right_paren;

  vertical_bar = "|";

  where_clause = "WHERE" search_condition;


More information about the dal mailing list