Skip to content
Snippets Groups Projects
Commit e4366686 authored by Grégory Mantelet's avatar Grégory Mantelet
Browse files

[ADQL] Add examples of ADQL parsing.

parent deba2e14
No related branches found
No related tags found
No related merge requests found
package vollt_examples.adql.parse;
import adql.parser.ADQLParser;
import adql.parser.grammar.ParseException;
import adql.query.ADQLQuery;
/**
* Minimal lines required to parse an ADQL query.
*
* @author Grégory Mantelet (CDS)
* @version 08/2019
*/
public class A_SimpleQueryParsing {
public static void main(final String[] args) {
// Input query:
final String QUERY = "Select name, ra || ' - ' || dec as \"Position\"\nFrom data\nWhere Contains(Point('ICRS', ra, dec), Circle('ICRS', 10, 5, 1)) = 1\nOrder By name;";
System.out.println("\n " + QUERY.replaceAll("\n", "\n "));
try {
// 1. CREATE A PARSER:
ADQLParser parser = new ADQLParser();
/*
* To create a parser of a specific version of the ADQL grammar:
*
* import adql.parser.ADQLParser.ADQLVersion;
* [...]
* ADQLParser parser = new ADQLParser(ADQLVersion.V2_0);
*
*/
// 2. PARSE AN ADQL QUERY:
ADQLQuery query = parser.parseQuery(QUERY);
System.out.println("\n((i)) Correct ADQL query ((i))");
System.out.println("\n((i)) As interpreted: ((i))\n " + query.toADQL().replaceAll("\n", "\n "));
}
// 3. EVENTUALLY DEAL WITH ERRORS:
catch(ParseException ex) {
System.out.println("\n((X)) INCORRECT QUERY! " + ex.getClass().getSimpleName() + " ((X))\n" + ex.getMessage());
}
}
}
package vollt_examples.adql.parse;
import adql.parser.ADQLParser;
import adql.parser.grammar.ParseException;
import adql.query.ClauseConstraints;
/**
* Minimal lines required to parse an ADQL clause (here: <code>WHERE</code>).
*
* @author Gr&eacute;gory Mantelet (CDS)
* @version 08/2019
*/
public class B_SimpleClauseParsing {
public static void main(final String[] args) {
// Input ADQL expression:
final String CLAUSE = "Where Contains(Point('ICRS', ra, dec), Circle('ICRS', 10, 5, 1)) = 1";
System.out.println("\n " + CLAUSE);
try {
// 1. CREATE A PARSER:
ADQLParser parser = new ADQLParser();
/*
* To create a parser of a specific version of the ADQL grammar:
*
* import adql.parser.ADQLParser.ADQLVersion;
* [...]
* ADQLParser parser = new ADQLParser(ADQLVersion.V2_0);
*
*/
// 2. PARSE A SPECIFIC ADQL CLAUSE:
ClauseConstraints constraints = parser.parseWhere(CLAUSE);
System.out.println("\n((i)) Correct WHERE clause ((i))");
System.out.println("\n((i)) As interpreted: `" + constraints.toADQL() + "` ((i))");
}
// 3. EVENTUALLY DEAL WITH ERRORS:
catch(ParseException ex) {
System.out.println("\n((X)) INCORRECT CLAUSE! " + ex.getClass().getSimpleName() + " ((X))\n" + ex.getPosition() + " " + ex.getMessage());
}
}
}
package vollt_examples.adql.parse;
import java.util.HashSet;
import adql.db.DBChecker;
import adql.db.DBTable;
import adql.db.exception.UnresolvedIdentifiersException;
import adql.parser.ADQLParser;
import adql.parser.ADQLParser.ADQLVersion;
import adql.parser.feature.FeatureSet;
import adql.parser.grammar.ParseException;
import adql.query.TextPosition;
/**
* Examples and explanations on how to handle with different kinds of parsing
* error.
*
* @author Gr&eacute;gory Mantelet (CDS)
* @version 08/2019
*/
public class C_HandleParseException {
public static void main(final String[] args) {
////////////////////////////////////////////////////////////////////////
// CASE 1/3: Simple error //
////////////////////////////////////////////////////////////////////////
// Input query (i.e. SELECT keyword missing):
String QUERY = "name, ra || ' - ' || dec as \"Position\"\nFrom data\nWhere Contains(Point('ICRS', ra, dec), Circle('ICRS', 10, 5, 1)) = 1\nOrder By name;";
System.out.println("\n##### QUERY #1 #####\n\n " + QUERY.replaceAll("\n", "\n "));
try {
// Parse the query:
(new ADQLParser()).parseQuery(QUERY);
System.err.println("((X)) This message should never be visible! ((X)");
} catch(ParseException ex) {
// Full name of the caught exception:
final String CLASS = ex.getClass().getName();
/*
* NOTES:
* ParseException is the root type of all possible exceptions that
* can possibly be generated by an ADQLParser. Special types of
* ParseException are going to be demonstrated with other examples
* below.
*/
// Position of the error inside the input ADQL query:
final TextPosition POSITION = ex.getPosition();
/*
* NOTES:
* A TextPosition keeps the begin and end line and column numbers.
* They can be got individually directly with the attributes:
* - TextPosition.beginLine
* - TextPosition.endLine
* - TextPosition.beginColumn
* - TextPosition.endColumn
*
* TextPosition.toString() will conveniently print all these
* information in a string like: `[l.1 c.5 - l.1 c.9]`.
*/
// Error message
final String MESSAGE = ex.getMessage();
/*
* NOTES:
* A ParseException is still an error. So a message with
* a human description of the error is also available.
*/
System.out.println("\n((X)) INCORRECT QUERY! " + CLASS + " ((X))\n" + POSITION + " " + MESSAGE);
}
////////////////////////////////////////////////////////////////////////
// CASE 2/3: Unresolved identifiers //
////////////////////////////////////////////////////////////////////////
// Input query (i.e. SELECT keyword missing):
QUERY = "SELECT name, ra || ' - ' || dec as \"Position\"\nFrom data\nWhere Contains(Point('ICRS', ra, dec), Circle('ICRS', 10, 5, 1)) = 1\nOrder By name;";
System.out.println("\n##### QUERY #2 #####\n\n " + QUERY.replaceAll("\n", "\n "));
try {
/* Parse the query (with an empty list of DB tables
* => no table/column can be resolved in any parsed query): */
(new ADQLParser(null, new DBChecker(new HashSet<DBTable>(0)), null, null)).parseQuery(QUERY);
System.err.println("\n((X)) This message should never be visible! ((X)");
} catch(UnresolvedIdentifiersException ex) {
/*
* NOTES:
* UnresolvedIdentifiersException is the only extension of
* ParseException able to represent more than one error at a time.
*
* It is possible to count and to list these errors with:
*
* - UnresolvedIdentifiersException.getNbErrors()
*
* - UnresolvedIdentifiersException.getErrors()
* or UnresolvedIdentifiersException.iterator()
*
* As suggested by its name, this exception is very often used to
* list unresolved table/column names.
*/
System.out.println("\n((X))) INCORRECT QUERY! Cause: " + ex.getNbErrors() + " unresolved identifiers! ((X))");
for(ParseException pe : ex) {
System.out.println(" - " + pe.getPosition() + " " + pe.getMessage());
}
} catch(ParseException ex) {
System.out.println("\n((X)) INCORRECT QUERY! " + ex.getClass().getSimpleName() + " ((X))\n" + ex.getPosition() + " " + ex.getMessage());
}
////////////////////////////////////////////////////////////////////////
// CASE 3/3: Unsupported features //
////////////////////////////////////////////////////////////////////////
// Input query:
QUERY = "Select LOWER(name), MY_UDF('foo')\nFrom data;";
System.out.println("\n##### QUERY #3 #####\n\n " + QUERY.replaceAll("\n", "\n "));
try {
/* Parse the query (as above, with an empty list of DB tables
* BUT ALSO with absolutely no optional feature supported): */
(new ADQLParser(ADQLVersion.V2_1, new DBChecker(new HashSet<DBTable>(0)), null, new FeatureSet(false, false))).parseQuery(QUERY);
System.err.println("\n((X)) This message should never be visible! ((X)");
} catch(UnresolvedIdentifiersException ex) {
/*
* NOTES:
* Since ADQL-2.1, there is the notion of optional language
* features.
*
* Because several unsupported features may be used in a same
* ADQL query, UnresolvedIdentifiersException is now also used to
* list all of them.
*
* However, unresolved identifiers and unsupported features can
* not be raised in the same time. First, supported features are
* tested. If no unsupported features are detected, then,
* identifiers resolution are tested. So, if unsupported features
* are detected, an UnresolvedIdentifiersException listing all of
* them is immediately thrown, which prevent testing the
* identifiers.
*
* So, errors about support of language features always have the
* priority (as illustrated in this example).
*/
System.out.println("\n((X))) INCORRECT QUERY! Cause: " + ex.getNbErrors() + " unsupported features! ((X))");
for(ParseException pe : ex) {
System.out.println(" - " + pe.getPosition() + " " + pe.getMessage());
}
} catch(ParseException ex) {
System.out.println("\n((X)) INCORRECT QUERY! " + ex.getClass().getSimpleName() + " ((X))\n" + ex.getPosition() + " " + ex.getMessage());
}
}
}
package vollt_examples.adql.parse;
import adql.db.exception.UnresolvedIdentifiersException;
import adql.parser.ADQLParser;
import adql.parser.ADQLParser.ADQLVersion;
import adql.parser.feature.FeatureSet;
import adql.parser.feature.LanguageFeature;
import adql.parser.grammar.ParseException;
import adql.query.operand.function.string.LowerFunction;
/**
* Example on how to support/unsupport some optional language features while
* parsing an ADQL query.
*
* @author Gr&eacute;gory Mantelet (CDS)
* @version 08/2019
*/
public class D_DeclareOptionalFeatures {
public static void main(final String[] args) throws Throwable {
// Input query:
final String QUERY = "Select LOWER(name), ra || ' - ' || dec as \"Position\"\nFrom data;";
System.out.println("\n " + QUERY.replaceAll("\n", "\n "));
try {
// Create a parser (supporting the notion of optional features):
ADQLParser parser = new ADQLParser(ADQLVersion.V2_1);
/*
* NOTES:
* If none is specified in parameter of the constructor,
* ADQLParser internally creates a default set of supported
* features.
*
* This default may change in function of the ADQL grammar
* version. But generally, all features described in the version
* of an ADQL grammar are by default all supported by ADQLParser.
*
* See ADQLParser.setDefaultFeatures() to know the exact content
* of the default features set created by ADQLParser.
*
* To customize the list of supported features, you have 3
* possibilities:
*
* 1. Create an instance of FeatureSet and its support(...)
* and unsupport(...) functions to specify which features
* are supported or not.
* Then, give this FeatureSet in parameter when creating
* an ADQLParser.
*
* 2. As in 1., create a custom FeatureSet and set it to an
* existing ADQLParser instance using the function
* ADQLParser.setSupportedFeatures().
*
* 3. Get the FeatureSet of an already created ADQLParser with
* ADQLParser.getSupportedFeatures().
* Then, customize it as in 1. and 2. (with support(...) and
* unsupport(...) functions).
*
* The functions FeatureSet.support(...) and
* FeatureSet.unsupport(...) take an instance of LanguageFeature
* in parameter. You DO NOT NEED to create a new one for each
* feature you want to support/unsupport. All ADQLObject
* extensions have a public static attribute named `FEATURE` of
* type LanguageFeature. So if you know the name of the class
* corresponding to your feature, you just have to use its
* attribute FEATURE (as illustrated below).
*/
// Create an empty set of language features:
FeatureSet features = new FeatureSet(false, false);
// Support all available features:
features.supportAll();
// Just get the LanguageFeature for LOWER (DO NOT CREATE IT):
final LanguageFeature lowerFeature = LowerFunction.FEATURE;
// Ensures LOWER is now supported:
if (!parser.getSupportedFeatures().isSupporting(lowerFeature))
throw new Error("This example can not work properly. LOWER seems to be NOT supported in the default FeatureSet of ADQLParser. To fix this example, pick a different optional features.");
// BUT for our example, now un-support it:
parser.getSupportedFeatures().unsupport(lowerFeature);
// Parse the query:
parser.parseQuery(QUERY);
System.err.println("\n((X)) This message should never be visible! ((X)");
} catch(UnresolvedIdentifiersException ex) {
System.out.println("\n((X))) INCORRECT QUERY! Cause: " + ex.getNbErrors() + " unsupported features! ((X))");
for(ParseException pe : ex) {
System.out.println(" - " + pe.getPosition() + " " + pe.getMessage());
}
} catch(ParseException ex) {
System.out.println("\n((X)) INCORRECT QUERY! " + ex.getClass().getSimpleName() + " ((X))\n" + ex.getPosition() + " " + ex.getMessage());
}
}
}
package vollt_examples.adql.parse;
import adql.db.FunctionDef;
import adql.parser.ADQLParser;
import adql.parser.feature.FeatureSet;
import adql.parser.grammar.ParseException;
import adql.query.ADQLQuery;
/**
* Examples and explanations about how to declare UDF.
*
* @author Gr&eacute;gory Mantelet (CDS)
* @version 08/2019
*/
public class E_DeclareUDF {
public static void main(final String[] args) {
// Input query:
final String QUERY = "Select MY_UDF(name)\nFrom data";
////////////////////////////////////////////////////////////////////////
// CASE 1/3: Default = any undeclared UDF allowed //
////////////////////////////////////////////////////////////////////////
System.out.println("\n##### DEFAULT = ANY UNDECLARED UDF ALLOWED #####\n\n " + QUERY.replaceAll("\n", "\n "));
try {
// Create the parser:
ADQLParser parser = new ADQLParser();
// Parse the query:
ADQLQuery query = parser.parseQuery(QUERY);
System.out.println("\n((i)) Correct ADQL query ((i))");
System.out.println("\n((i)) As interpreted: ((i))\n " + query.toADQL().replaceAll("\n", "\n "));
}
// 3. EVENTUALLY DEAL WITH ERRORS:
catch(ParseException ex) {
System.out.println("\n((X)) INCORRECT QUERY! " + ex.getClass().getSimpleName() + " ((X))\n" + ex.getMessage());
}
////////////////////////////////////////////////////////////////////////
// CASE 2/3: No undeclared UDF allowed //
////////////////////////////////////////////////////////////////////////
System.out.println("\n##### NO UNDECLARED UDF ALLOWED #####\n\n " + QUERY.replaceAll("\n", "\n "));
try {
// Create the parser:
ADQLParser parser = new ADQLParser();
// FORBID ALL UNDECLARED UDF:
parser.getSupportedFeatures().allowAnyUdf(false);
// Parse the query:
ADQLQuery query = parser.parseQuery(QUERY);
System.out.println("\n((i)) Correct ADQL query ((i))");
System.out.println("\n((i)) As interpreted: ((i))\n " + query.toADQL().replaceAll("\n", "\n "));
}
// 3. EVENTUALLY DEAL WITH ERRORS:
catch(ParseException ex) {
System.out.println("\n((X)) INCORRECT QUERY! " + ex.getClass().getSimpleName() + " ((X))\n" + ex.getMessage());
}
////////////////////////////////////////////////////////////////////////
// CASE 3/3: Declare a UDF //
////////////////////////////////////////////////////////////////////////
System.out.println("\n##### DECLARE A UDF #####\n\n " + QUERY.replaceAll("\n", "\n "));
try {
// Create the parser:
ADQLParser parser = new ADQLParser();
// FORBID ALL UNDECLARED UDF:
FeatureSet features = parser.getSupportedFeatures();
features.allowAnyUdf(false);
// DECLARE A UDF:
// ...define this function:
FunctionDef myUdf = FunctionDef.parse("my_udf(param1 VARCHAR) -> VARCHAR", parser.getADQLVersion());
// ...now add it to the supported features:
if (!features.support(myUdf.toLanguageFeature()))
throw new Error("Impossible to support the UDF `" + myUdf + "`! This is the important point of this example file.");
// Parse the query:
ADQLQuery query = parser.parseQuery(QUERY);
System.out.println("\n((i)) Correct ADQL query ((i))");
System.out.println("\n((i)) As interpreted: ((i))\n " + query.toADQL().replaceAll("\n", "\n "));
}
// 3. EVENTUALLY DEAL WITH ERRORS:
catch(ParseException ex) {
System.out.println("\n((X)) INCORRECT QUERY! " + ex.getClass().getSimpleName() + " ((X))\n" + ex.getMessage());
}
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment