This file contains a BNF definition of ADQL, the Astronomical
Data Query Language. The elements are arranged in alphabetical
order. ADQL is based upon a subset of SQL92 with extensions for
astronomical usage.

The definition reflects the ADQL spec version v2.0
The select statement is found at <query_specification>
For region and associated constructs, see...
<geometry_value_expression>,
<numeric_geometry_function>,
<string_geometry_function>
User defined function is found at <user_defined_function>
See SQL92 for a similar page describing SQL92 in full.

  <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> ::=
     | <left_paren> <search_condition> <right_paren> 
       <predicate> 

  <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>
  !! For information only, SQL92 supports <collate_clause>

  <character_primary> ::= 
      <value_expression_primary>
    | <string_value_function>

  <character_representation> ::= <nonquote_character> | <quote_symbol>
  !! A way of allowing a single quote to be escaped by a single quote.

  <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> ::=
   !! The prefix is set by default to "udf_".
   !! It should be possible to change the default prefix to accommodate local preferences.

  <delimited_identifier> ::= <double_quote> <delimited_identifier_body> <double_quote>
  !! These diagrams are somewhat difficult to follow through and understand immediately. 
  !! The idea is to allow any identifier to be quoted by enclosing within double quotes.
  !! This can allow the use of reserved words as identifiers, eg: "DATE" as a column name.  
  !! The identifier can also contain double quotes as long as they are escaped by double quotes. 
  !! For example: "Table""X" will be identifier Table"X

  <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>
  !! ADQL Note:
  !! For information, SQL92 has <general_literal>, and also supports
  !! <national_character_string_literal>, <bit_string_literal>, 
  !! <hex_string_literal>, <datetime_literal> and <interval_literal>
  !! Good to retain this as a place-holder, bearing in mind
  !! that we might need <bit_string_literal> and <hex_string_literal>
  !! at some point in the future?

  <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> 
  !! For information, SQL92 supports a <collate_clause>

  <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 ]
  !! For information, SQL92 also supports UNION

  <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> ::= 
  !! Implementation defined end of line indicator

  <non_predicate_geometry_function> ::= 
     <area>
   | <coord1>
   | <coord2> 
   | <distance>

  <nondelimiter_token> ::= 
      <regular_identifier>
    | <keyword>
    | <unsigned_numeric_literal>
   !! For information, SQL92 has some others. 
   !! (Jeff: Not sure I understand how this is used.)

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

  <nonquote_character> ::= 
  !! One ASCII character but not a single 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>
  !! For information, SQ92 also supports <position_expression>,
  !! <extract_expression> and <length_expression>

  <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>
  !! For information, SQL92 also supports the following predicates: 
  !! <quantified_comparison_predicate>, <unique_predicate>, 
  !! <match_predicate> and <overlaps_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>
   !! ADQL Note: SQL92 uses <non_join_query_expression> rather than <query_specification>

  <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> 
   !! For information, the use of <unsigned_integer> in <sort_key>is a deprecated feature of SQL92

  <sort_specification> ::=
      <sort_key> [ <ordering_specification> ]
  !! For information, SQL92 also supports <collate_clause>

  <sort_specification_list> ::=
      <sort_specification> [ { <comma> <sort_specification> }... ]

  <space> ::=
  !! Imagine there is a space character here

  <string_geometry_function> ::= <extract_coordsys>

  <string_value_expression> ::=
      <character_value_expression>
  !! For information, SQL92 also supports <bit_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> 
  !! ADQL Note:
  !! If metadata on a user defined function is available, this should be used.
  !! For example, function names and cardinality of arguments should be checked.

  <user_defined_function_name> ::=
       [ <default_function_prefix> ] <regular_identifier>
   !! Function names should be checked against metadata where available. 

  <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>
  !! For information, SQL92 supports <scalar_subquery>,
  !! <case_expression> and <cast_specification>

  <vertical_bar> ::= |

  <where_clause> ::= WHERE <search_condition>