diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml
index f26891bd..2b8ef4b6 100644
--- a/.github/workflows/gradle.yml
+++ b/.github/workflows/gradle.yml
@@ -37,10 +37,12 @@ jobs:
- name: build and test cadc-tap-server-oracle
run: cd cadc-tap-server-oracle && ../gradlew --info clean build javadoc install
-
+
- name: build and test cadc-test-tap
run: cd cadc-test-tap && ../gradlew --info clean build javadoc install
- name: build example-tap
run: cd example-tap && ../gradlew --info clean build
-
+
+ - name: build and test cadc-tap-server-bigquery
+ run: cd cadc-tap-server-bigquery && ../gradlew --info clean build javadoc checkstyleMain install
diff --git a/cadc-tap-server-bigquery/README.md b/cadc-tap-server-bigquery/README.md
new file mode 100644
index 00000000..2d2bcf94
--- /dev/null
+++ b/cadc-tap-server-bigquery/README.md
@@ -0,0 +1,3 @@
+# cadc-tap-server-bigquery 1.0.0
+
+Offers BigQuery support to handle datatype conversions in ADQL.
\ No newline at end of file
diff --git a/cadc-tap-server-bigquery/build.gradle b/cadc-tap-server-bigquery/build.gradle
new file mode 100644
index 00000000..f153c2f1
--- /dev/null
+++ b/cadc-tap-server-bigquery/build.gradle
@@ -0,0 +1,33 @@
+plugins {
+ id "java"
+ id "maven"
+ id 'maven-publish'
+ id 'checkstyle'
+}
+
+repositories {
+ mavenCentral()
+ mavenLocal()
+}
+
+apply from: '../opencadc.gradle'
+
+sourceCompatibility = 1.8
+
+group = 'org.opencadc'
+
+version = '1.0.5'
+
+description = 'OpenCADC TAP-1.1 tap server plugin (BigQuery)'
+def git_url = 'https://github.com/opencadc/tap'
+
+dependencies {
+ implementation 'org.opencadc:cadc-tap-schema:[1.1.22,)'
+ implementation 'org.opencadc:cadc-tap-server:[1.1.7,)'
+ implementation 'org.opencadc:cadc-adql:[1.1.10,)'
+ implementation 'org.opencadc:cadc-jsqlparser-compat:[0.6.4,)'
+
+ testImplementation 'junit:junit:[4.0,5.0)'
+ testImplementation 'org.opencadc:cadc-util:[1.6,)'
+ testImplementation 'xerces:xercesImpl:[2.0,)'
+}
diff --git a/cadc-tap-server-bigquery/src/main/java/ca/nrc/cadc/tap/expression/BqColumnAliasSelectItem.java b/cadc-tap-server-bigquery/src/main/java/ca/nrc/cadc/tap/expression/BqColumnAliasSelectItem.java
new file mode 100644
index 00000000..2e971be3
--- /dev/null
+++ b/cadc-tap-server-bigquery/src/main/java/ca/nrc/cadc/tap/expression/BqColumnAliasSelectItem.java
@@ -0,0 +1,92 @@
+
+/*
+ ************************************************************************
+ ******************* CANADIAN ASTRONOMY DATA CENTRE *******************
+ ************** CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES **************
+ *
+ * (c) 2019. (c) 2019.
+ * Government of Canada Gouvernement du Canada
+ * National Research Council Conseil national de recherches
+ * Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6
+ * All rights reserved Tous droits réservés
+ *
+ * NRC disclaims any warranties, Le CNRC dénie toute garantie
+ * expressed, implied, or énoncée, implicite ou légale,
+ * statutory, of any kind with de quelque nature que ce
+ * respect to the software, soit, concernant le logiciel,
+ * including without limitation y compris sans restriction
+ * any warranty of merchantability toute garantie de valeur
+ * or fitness for a particular marchande ou de pertinence
+ * purpose. NRC shall not be pour un usage particulier.
+ * liable in any event for any Le CNRC ne pourra en aucun cas
+ * damages, whether direct or être tenu responsable de tout
+ * indirect, special or general, dommage, direct ou indirect,
+ * consequential or incidental, particulier ou général,
+ * arising from the use of the accessoire ou fortuit, résultant
+ * software. Neither the name de l'utilisation du logiciel. Ni
+ * of the National Research le nom du Conseil National de
+ * Council of Canada nor the Recherches du Canada ni les noms
+ * names of its contributors may de ses participants ne peuvent
+ * be used to endorse or promote être utilisés pour approuver ou
+ * products derived from this promouvoir les produits dérivés
+ * software without specific prior de ce logiciel sans autorisation
+ * written permission. préalable et particulière
+ * par écrit.
+ *
+ * This file is part of the Ce fichier fait partie du projet
+ * OpenCADC project. OpenCADC.
+ *
+ * OpenCADC is free software: OpenCADC est un logiciel libre ;
+ * you can redistribute it and/or vous pouvez le redistribuer ou le
+ * modify it under the terms of modifier suivant les termes de
+ * the GNU Affero General Public la “GNU Affero General Public
+ * License as published by the License” telle que publiée
+ * Free Software Foundation, par la Free Software Foundation
+ * either version 3 of the : soit la version 3 de cette
+ * License, or (at your option) licence, soit (à votre gré)
+ * any later version. toute version ultérieure.
+ *
+ * OpenCADC is distributed in the OpenCADC est distribué
+ * hope that it will be useful, dans l’espoir qu’il vous
+ * but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE
+ * without even the implied GARANTIE : sans même la garantie
+ * warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ
+ * or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF
+ * PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence
+ * General Public License for Générale Publique GNU Affero
+ * more details. pour plus de détails.
+ *
+ * You should have received Vous devriez avoir reçu une
+ * a copy of the GNU Affero copie de la Licence Générale
+ * General Public License along Publique GNU Affero avec
+ * with OpenCADC. If not, see OpenCADC ; si ce n’est
+ * . pas le cas, consultez :
+ * .
+ *
+ *
+ ************************************************************************
+ */
+
+package ca.nrc.cadc.tap.expression;
+
+import net.sf.jsqlparser.statement.select.SelectExpressionItem;
+import net.sf.jsqlparser.statement.select.SelectItemVisitor;
+
+public class BqColumnAliasSelectItem extends SelectExpressionItem {
+ public BqColumnAliasSelectItem(SelectExpressionItem selectExpressionItem) {
+ super();
+ setExpression(selectExpressionItem.getExpression());
+ setAlias(selectExpressionItem.getAlias());
+ }
+
+ @Override
+ public void accept(SelectItemVisitor selectItemVisitor) {
+ selectItemVisitor.visit(this);
+ }
+
+ @Override
+ public String toString() {
+ String alias = getAlias();
+ return (alias == null) ? getExpression() + "" : alias;
+ }
+}
diff --git a/cadc-tap-server-bigquery/src/main/java/ca/nrc/cadc/tap/expression/BqExpressionDeParser.java b/cadc-tap-server-bigquery/src/main/java/ca/nrc/cadc/tap/expression/BqExpressionDeParser.java
new file mode 100644
index 00000000..027e9d02
--- /dev/null
+++ b/cadc-tap-server-bigquery/src/main/java/ca/nrc/cadc/tap/expression/BqExpressionDeParser.java
@@ -0,0 +1,83 @@
+
+/*
+ ************************************************************************
+ ******************* CANADIAN ASTRONOMY DATA CENTRE *******************
+ ************** CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES **************
+ *
+ * (c) 2018. (c) 2018.
+ * Government of Canada Gouvernement du Canada
+ * National Research Council Conseil national de recherches
+ * Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6
+ * All rights reserved Tous droits réservés
+ *
+ * NRC disclaims any warranties, Le CNRC dénie toute garantie
+ * expressed, implied, or énoncée, implicite ou légale,
+ * statutory, of any kind with de quelque nature que ce
+ * respect to the software, soit, concernant le logiciel,
+ * including without limitation y compris sans restriction
+ * any warranty of merchantability toute garantie de valeur
+ * or fitness for a particular marchande ou de pertinence
+ * purpose. NRC shall not be pour un usage particulier.
+ * liable in any event for any Le CNRC ne pourra en aucun cas
+ * damages, whether direct or être tenu responsable de tout
+ * indirect, special or general, dommage, direct ou indirect,
+ * consequential or incidental, particulier ou général,
+ * arising from the use of the accessoire ou fortuit, résultant
+ * software. Neither the name de l'utilisation du logiciel. Ni
+ * of the National Research le nom du Conseil National de
+ * Council of Canada nor the Recherches du Canada ni les noms
+ * names of its contributors may de ses participants ne peuvent
+ * be used to endorse or promote être utilisés pour approuver ou
+ * products derived from this promouvoir les produits dérivés
+ * software without specific prior de ce logiciel sans autorisation
+ * written permission. préalable et particulière
+ * par écrit.
+ *
+ * This file is part of the Ce fichier fait partie du projet
+ * OpenCADC project. OpenCADC.
+ *
+ * OpenCADC is free software: OpenCADC est un logiciel libre ;
+ * you can redistribute it and/or vous pouvez le redistribuer ou le
+ * modify it under the terms of modifier suivant les termes de
+ * the GNU Affero General Public la “GNU Affero General Public
+ * License as published by the License” telle que publiée
+ * Free Software Foundation, par la Free Software Foundation
+ * either version 3 of the : soit la version 3 de cette
+ * License, or (at your option) licence, soit (à votre gré)
+ * any later version. toute version ultérieure.
+ *
+ * OpenCADC is distributed in the OpenCADC est distribué
+ * hope that it will be useful, dans l’espoir qu’il vous
+ * but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE
+ * without even the implied GARANTIE : sans même la garantie
+ * warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ
+ * or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF
+ * PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence
+ * General Public License for Générale Publique GNU Affero
+ * more details. pour plus de détails.
+ *
+ * You should have received Vous devriez avoir reçu une
+ * a copy of the GNU Affero copie de la Licence Générale
+ * General Public License along Publique GNU Affero avec
+ * with OpenCADC. If not, see OpenCADC ; si ce n’est
+ * . pas le cas, consultez :
+ * .
+ *
+ *
+ ************************************************************************
+ */
+
+package ca.nrc.cadc.tap.expression;
+
+import ca.nrc.cadc.tap.parser.BaseExpressionDeParser;
+import net.sf.jsqlparser.statement.select.SelectVisitor;
+
+public class BqExpressionDeParser extends BaseExpressionDeParser {
+ public BqExpressionDeParser(SelectVisitor selectVisitor, StringBuffer buffer) {
+ super(selectVisitor, buffer);
+ }
+
+ void visit(BqKeywordExpression expression) {
+ buffer.append(expression.toString());
+ }
+}
diff --git a/cadc-tap-server-bigquery/src/main/java/ca/nrc/cadc/tap/expression/BqKeywordExpression.java b/cadc-tap-server-bigquery/src/main/java/ca/nrc/cadc/tap/expression/BqKeywordExpression.java
new file mode 100644
index 00000000..9abad06f
--- /dev/null
+++ b/cadc-tap-server-bigquery/src/main/java/ca/nrc/cadc/tap/expression/BqKeywordExpression.java
@@ -0,0 +1,116 @@
+
+/*
+ ************************************************************************
+ ******************* CANADIAN ASTRONOMY DATA CENTRE *******************
+ ************** CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES **************
+ *
+ * (c) 2018. (c) 2018.
+ * Government of Canada Gouvernement du Canada
+ * National Research Council Conseil national de recherches
+ * Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6
+ * All rights reserved Tous droits réservés
+ *
+ * NRC disclaims any warranties, Le CNRC dénie toute garantie
+ * expressed, implied, or énoncée, implicite ou légale,
+ * statutory, of any kind with de quelque nature que ce
+ * respect to the software, soit, concernant le logiciel,
+ * including without limitation y compris sans restriction
+ * any warranty of merchantability toute garantie de valeur
+ * or fitness for a particular marchande ou de pertinence
+ * purpose. NRC shall not be pour un usage particulier.
+ * liable in any event for any Le CNRC ne pourra en aucun cas
+ * damages, whether direct or être tenu responsable de tout
+ * indirect, special or general, dommage, direct ou indirect,
+ * consequential or incidental, particulier ou général,
+ * arising from the use of the accessoire ou fortuit, résultant
+ * software. Neither the name de l'utilisation du logiciel. Ni
+ * of the National Research le nom du Conseil National de
+ * Council of Canada nor the Recherches du Canada ni les noms
+ * names of its contributors may de ses participants ne peuvent
+ * be used to endorse or promote être utilisés pour approuver ou
+ * products derived from this promouvoir les produits dérivés
+ * software without specific prior de ce logiciel sans autorisation
+ * written permission. préalable et particulière
+ * par écrit.
+ *
+ * This file is part of the Ce fichier fait partie du projet
+ * OpenCADC project. OpenCADC.
+ *
+ * OpenCADC is free software: OpenCADC est un logiciel libre ;
+ * you can redistribute it and/or vous pouvez le redistribuer ou le
+ * modify it under the terms of modifier suivant les termes de
+ * the GNU Affero General Public la “GNU Affero General Public
+ * License as published by the License” telle que publiée
+ * Free Software Foundation, par la Free Software Foundation
+ * either version 3 of the : soit la version 3 de cette
+ * License, or (at your option) licence, soit (à votre gré)
+ * any later version. toute version ultérieure.
+ *
+ * OpenCADC is distributed in the OpenCADC est distribué
+ * hope that it will be useful, dans l’espoir qu’il vous
+ * but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE
+ * without even the implied GARANTIE : sans même la garantie
+ * warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ
+ * or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF
+ * PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence
+ * General Public License for Générale Publique GNU Affero
+ * more details. pour plus de détails.
+ *
+ * You should have received Vous devriez avoir reçu une
+ * a copy of the GNU Affero copie de la Licence Générale
+ * General Public License along Publique GNU Affero avec
+ * with OpenCADC. If not, see OpenCADC ; si ce n’est
+ * . pas le cas, consultez :
+ * .
+ *
+ *
+ ************************************************************************
+ */
+
+package ca.nrc.cadc.tap.expression;
+
+import net.sf.jsqlparser.expression.Expression;
+import net.sf.jsqlparser.expression.ExpressionVisitor;
+
+
+public class BqKeywordExpression implements Expression {
+
+ private final String keyword;
+
+ public BqKeywordExpression(String keyword) {
+ this.keyword = keyword;
+ }
+
+ @Override
+ public void accept(ExpressionVisitor expressionVisitor) {
+ if (expressionVisitor instanceof BqExpressionDeParser) {
+ ((BqExpressionDeParser) expressionVisitor).visit(this);
+ }
+ }
+
+ /**
+ * Returns a string representation of the object. In general, the
+ * {@code toString} method returns a string that
+ * "textually represents" this object. The result should
+ * be a concise but informative representation that is easy for a
+ * person to read.
+ * It is recommended that all subclasses override this method.
+ *
+ *
The {@code toString} method for class {@code Object}
+ * returns a string consisting of the name of the class of which the
+ * object is an instance, the at-sign character `{@code @}', and
+ * the unsigned hexadecimal representation of the hash code of the
+ * object. In other words, this method returns a string equal to the
+ * value of:
+ *
+ *
+ * @return a string representation of the object.
+ */
+ @Override
+ public String toString() {
+ return keyword;
+ }
+}
diff --git a/cadc-tap-server-bigquery/src/main/java/ca/nrc/cadc/tap/parser/BqQuerySelectDeParser.java b/cadc-tap-server-bigquery/src/main/java/ca/nrc/cadc/tap/parser/BqQuerySelectDeParser.java
new file mode 100644
index 00000000..b20aba09
--- /dev/null
+++ b/cadc-tap-server-bigquery/src/main/java/ca/nrc/cadc/tap/parser/BqQuerySelectDeParser.java
@@ -0,0 +1,100 @@
+
+/*
+ ************************************************************************
+ ******************* CANADIAN ASTRONOMY DATA CENTRE *******************
+ ************** CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES **************
+ *
+ * (c) 2019. (c) 2019.
+ * Government of Canada Gouvernement du Canada
+ * National Research Council Conseil national de recherches
+ * Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6
+ * All rights reserved Tous droits réservés
+ *
+ * NRC disclaims any warranties, Le CNRC dénie toute garantie
+ * expressed, implied, or énoncée, implicite ou légale,
+ * statutory, of any kind with de quelque nature que ce
+ * respect to the software, soit, concernant le logiciel,
+ * including without limitation y compris sans restriction
+ * any warranty of merchantability toute garantie de valeur
+ * or fitness for a particular marchande ou de pertinence
+ * purpose. NRC shall not be pour un usage particulier.
+ * liable in any event for any Le CNRC ne pourra en aucun cas
+ * damages, whether direct or être tenu responsable de tout
+ * indirect, special or general, dommage, direct ou indirect,
+ * consequential or incidental, particulier ou général,
+ * arising from the use of the accessoire ou fortuit, résultant
+ * software. Neither the name de l'utilisation du logiciel. Ni
+ * of the National Research le nom du Conseil National de
+ * Council of Canada nor the Recherches du Canada ni les noms
+ * names of its contributors may de ses participants ne peuvent
+ * be used to endorse or promote être utilisés pour approuver ou
+ * products derived from this promouvoir les produits dérivés
+ * software without specific prior de ce logiciel sans autorisation
+ * written permission. préalable et particulière
+ * par écrit.
+ *
+ * This file is part of the Ce fichier fait partie du projet
+ * OpenCADC project. OpenCADC.
+ *
+ * OpenCADC is free software: OpenCADC est un logiciel libre ;
+ * you can redistribute it and/or vous pouvez le redistribuer ou le
+ * modify it under the terms of modifier suivant les termes de
+ * the GNU Affero General Public la “GNU Affero General Public
+ * License as published by the License” telle que publiée
+ * Free Software Foundation, par la Free Software Foundation
+ * either version 3 of the : soit la version 3 de cette
+ * License, or (at your option) licence, soit (à votre gré)
+ * any later version. toute version ultérieure.
+ *
+ * OpenCADC is distributed in the OpenCADC est distribué
+ * hope that it will be useful, dans l’espoir qu’il vous
+ * but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE
+ * without even the implied GARANTIE : sans même la garantie
+ * warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ
+ * or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF
+ * PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence
+ * General Public License for Générale Publique GNU Affero
+ * more details. pour plus de détails.
+ *
+ * You should have received Vous devriez avoir reçu une
+ * a copy of the GNU Affero copie de la Licence Générale
+ * General Public License along Publique GNU Affero avec
+ * with OpenCADC. If not, see OpenCADC ; si ce n’est
+ * . pas le cas, consultez :
+ * .
+ *
+ *
+ ************************************************************************
+ */
+
+package ca.nrc.cadc.tap.parser;
+
+import ca.nrc.cadc.tap.expression.BqColumnAliasSelectItem;
+import net.sf.jsqlparser.expression.Expression;
+import net.sf.jsqlparser.schema.Column;
+import net.sf.jsqlparser.statement.select.PlainSelect;
+import net.sf.jsqlparser.statement.select.SelectExpressionItem;
+
+
+public class BqQuerySelectDeParser extends QuerySelectDeParser {
+ @Override
+ public void visit(PlainSelect plainSelect) {
+ super.visit(plainSelect);
+ }
+
+ @Override
+ public void visit(SelectExpressionItem selectExpressionItem) {
+ Expression selectExpression = selectExpressionItem.getExpression();
+
+ if (selectExpression instanceof Column) {
+ String normalizedColumnName = ((Column) selectExpression).getColumnName().replaceAll("\"", "");
+ ((Column) selectExpression).setColumnName(normalizedColumnName);
+ }
+
+ if (selectExpressionItem instanceof BqColumnAliasSelectItem) {
+ getBuffer().append(selectExpressionItem);
+ } else {
+ super.visit(selectExpressionItem);
+ }
+ }
+}
diff --git a/cadc-tap-server-bigquery/src/main/java/ca/nrc/cadc/tap/parser/converter/BqRegionConverter.java b/cadc-tap-server-bigquery/src/main/java/ca/nrc/cadc/tap/parser/converter/BqRegionConverter.java
new file mode 100644
index 00000000..16a92f60
--- /dev/null
+++ b/cadc-tap-server-bigquery/src/main/java/ca/nrc/cadc/tap/parser/converter/BqRegionConverter.java
@@ -0,0 +1,472 @@
+
+/*
+ ************************************************************************
+ ******************* CANADIAN ASTRONOMY DATA CENTRE *******************
+ ************** CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES **************
+ *
+ * (c) 2019. (c) 2019.
+ * Government of Canada Gouvernement du Canada
+ * National Research Council Conseil national de recherches
+ * Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6
+ * All rights reserved Tous droits réservés
+ *
+ * NRC disclaims any warranties, Le CNRC dénie toute garantie
+ * expressed, implied, or énoncée, implicite ou légale,
+ * statutory, of any kind with de quelque nature que ce
+ * respect to the software, soit, concernant le logiciel,
+ * including without limitation y compris sans restriction
+ * any warranty of merchantability toute garantie de valeur
+ * or fitness for a particular marchande ou de pertinence
+ * purpose. NRC shall not be pour un usage particulier.
+ * liable in any event for any Le CNRC ne pourra en aucun cas
+ * damages, whether direct or être tenu responsable de tout
+ * indirect, special or general, dommage, direct ou indirect,
+ * consequential or incidental, particulier ou général,
+ * arising from the use of the accessoire ou fortuit, résultant
+ * software. Neither the name de l'utilisation du logiciel. Ni
+ * of the National Research le nom du Conseil National de
+ * Council of Canada nor the Recherches du Canada ni les noms
+ * names of its contributors may de ses participants ne peuvent
+ * be used to endorse or promote être utilisés pour approuver ou
+ * products derived from this promouvoir les produits dérivés
+ * software without specific prior de ce logiciel sans autorisation
+ * written permission. préalable et particulière
+ * par écrit.
+ *
+ * This file is part of the Ce fichier fait partie du projet
+ * OpenCADC project. OpenCADC.
+ *
+ * OpenCADC is free software: OpenCADC est un logiciel libre ;
+ * you can redistribute it and/or vous pouvez le redistribuer ou le
+ * modify it under the terms of modifier suivant les termes de
+ * the GNU Affero General Public la “GNU Affero General Public
+ * License as published by the License” telle que publiée
+ * Free Software Foundation, par la Free Software Foundation
+ * either version 3 of the : soit la version 3 de cette
+ * License, or (at your option) licence, soit (à votre gré)
+ * any later version. toute version ultérieure.
+ *
+ * OpenCADC is distributed in the OpenCADC est distribué
+ * hope that it will be useful, dans l’espoir qu’il vous
+ * but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE
+ * without even the implied GARANTIE : sans même la garantie
+ * warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ
+ * or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF
+ * PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence
+ * General Public License for Générale Publique GNU Affero
+ * more details. pour plus de détails.
+ *
+ * You should have received Vous devriez avoir reçu une
+ * a copy of the GNU Affero copie de la Licence Générale
+ * General Public License along Publique GNU Affero avec
+ * with OpenCADC. If not, see OpenCADC ; si ce n’est
+ * . pas le cas, consultez :
+ * .
+ *
+ *
+ ************************************************************************
+ */
+
+package ca.nrc.cadc.tap.parser.converter;
+
+import ca.nrc.cadc.tap.parser.ParserUtil;
+import ca.nrc.cadc.tap.parser.RegionFinder;
+import ca.nrc.cadc.tap.parser.navigator.ExpressionNavigator;
+import ca.nrc.cadc.tap.parser.navigator.FromItemNavigator;
+import ca.nrc.cadc.tap.parser.navigator.ReferenceNavigator;
+import ca.nrc.cadc.tap.parser.region.function.BqCircle;
+import ca.nrc.cadc.tap.parser.region.function.BqPoint;
+import ca.nrc.cadc.tap.parser.region.function.BqPolygon;
+import net.sf.jsqlparser.expression.*;
+import net.sf.jsqlparser.expression.operators.relational.EqualsTo;
+import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
+import net.sf.jsqlparser.expression.operators.relational.GreaterThanEquals;
+import net.sf.jsqlparser.expression.operators.relational.MinorThanEquals;
+import org.apache.log4j.Logger;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+public class BqRegionConverter extends RegionFinder {
+
+ private static final Logger LOGGER = Logger.getLogger(BqRegionConverter.class);
+
+ private static final String CONTAINS_FUNCTION_NAME = "ST_CONTAINS";
+ private static final String NOT_FUNCTION_NAME = "NOT";
+ private static final String DWITHIN_FUNCTION_NAME = "ST_DWITHIN";
+ private static final String INTERSECTS_FUNCTION_NAME = "ST_INTERSECTS";
+ private static final String ST_AREA_FUNCTION_NAME = "ST_AREA";
+ private static final String ST_DISTANCE_FUNCTION_NAME = "ST_DISTANCE";
+ private static final String ST_MAXDISTANCE_FUNCTION_NAME = "ST_MAXDISTANCE";
+ private static final List MEASURE_FUNCTIONS = Arrays.asList(ST_DISTANCE_FUNCTION_NAME, ST_MAXDISTANCE_FUNCTION_NAME, ST_AREA_FUNCTION_NAME);
+ private static final double DEGREE_ARC_SECONDS = 3600;
+ private static final double ARC_SECOND_METERS = 30.8874796235;
+ private static final String SAFE_DIVIDE = "SAFE_DIVIDE";
+ private static final String SAFE_MULTIPLY = "SAFE_MULTIPLY";
+
+ public BqRegionConverter(ExpressionNavigator en, ReferenceNavigator rn,
+ FromItemNavigator fn) {
+ super(en, rn, fn);
+ }
+
+ @Override
+ public Expression convertToImplementation(Function func) {
+ return super.convertToImplementation(func);
+ }
+
+ /**
+ * This method is called when a REGION PREDICATE function is one of the arguments in a binary expression,
+ * and after the direct function conversion.
+ *
+ *
Supported functions: CONTAINS
+ *
+ *
Examples:
+ *
+ *
CONTAINS() = 0
+ * CONTAINS() = 1
+ * 1 = CONTAINS()
+ * 0 = CONTAINS()
+ */
+ @Override
+ protected Expression handleRegionPredicate(BinaryExpression binaryExpression) {
+ LOGGER.debug("handleRegionPredicate(" + binaryExpression.getClass().getSimpleName() + "): " + binaryExpression);
+
+ binaryExpression = convertToMeters(binaryExpression);
+
+ Expression left = binaryExpression.getLeftExpression();
+ Expression right = binaryExpression.getRightExpression();
+
+ if (!(binaryExpression instanceof EqualsTo)) {
+ return binaryExpression;
+ }
+
+ Expression binaryValueExpression = null;
+ Expression containsExpression = null;
+
+ if ((isFunction(left) || isBinaryExpression(left)) && ParserUtil.isBinaryValue(right)) {
+ containsExpression = left;
+ binaryValueExpression = right;
+ }
+
+ if (ParserUtil.isBinaryValue(left) && (isFunction(right) || isBinaryExpression(right))) {
+ containsExpression = right;
+ binaryValueExpression = left;
+ }
+
+ if (containsExpression == null) {
+ return binaryExpression;
+ }
+
+ boolean isTrueExpression = binaryValueExpression.toString().equals("1");
+ if (!isTrueExpression) {
+ Expression notBinaryExpression = handleNotExpression(containsExpression);
+ return notBinaryExpression;
+ }
+
+ return containsExpression;
+ }
+
+ /**
+ * This method is called when a CONTAINS is found outside of a predicate.
+ * This could occur if the query had CONTAINS(...) in the select list or as
+ * part of an arithmetic expression or aggregate function (since CONTAINS
+ * returns a numeric value).
+ * In Bq, we need to switch the arguments.
+ */
+ @Override
+ protected Expression handleContains(Expression left, Expression right) {
+ if (isCircle(left)) {
+ if (isContainsPolygon(right)) {
+ return polygonContainsCircle(right, left);
+ }
+
+ return circleIntersects(left, right, true);
+ }
+
+ if (isCircle(right)) {
+ if (isContainsPolygon(left)) {
+ return circleContainsPolygon(left, right);
+ }
+
+ return circleIntersects(left, right, true);
+ }
+
+ Function containsFunction = new Function();
+ containsFunction.setName(CONTAINS_FUNCTION_NAME);
+ List paramList = Arrays.asList(right, left);
+
+ ExpressionList parameters = new ExpressionList(paramList);
+ containsFunction.setParameters(parameters);
+
+ return containsFunction;
+ }
+
+ private Function handleNotExpression(Expression containsFunction) {
+ Function notFunction = new Function();
+ ExpressionList parameters = new ExpressionList(Arrays.asList(containsFunction));
+
+ notFunction.setName(NOT_FUNCTION_NAME);
+ notFunction.setParameters(parameters);
+
+ return notFunction;
+ }
+
+ /**
+ * This method is called when a POINT geometry value is found.
+ */
+ @Override
+ protected Expression handlePoint(Expression coordsys, Expression ra, Expression dec) {
+ return new BqPoint(ra, dec);
+ }
+
+ /**
+ * This method is called when a POLYGON geometry value is found.
+ */
+ @Override
+ protected Expression handlePolygon(List expressions) {
+ return new BqPolygon(expressions);
+ }
+
+ /**
+ * This method is called when a CIRCLE geometry value is found.
+ */
+ @Override
+ protected Expression handleCircle(Expression coordsys, Expression ra, Expression dec, Expression radiusExpression) {
+
+ if (isNumberValue((radiusExpression))) {
+ double radius = getDoubleValue(radiusExpression).getValue();
+
+ if (radius > 0.0D) {
+ return new BqCircle(ra, dec, radiusExpression);
+ }
+ }
+
+ LOGGER.debug("Radius is missing or is 0.0. Returning a POINT instead.");
+ return handlePoint(coordsys, ra, dec);
+ }
+
+ /**
+ * This method is called when a INTERSECTS is found outside of a predicate.
+ * This could occur if the query had INTERSECTS(...) in the select list or as
+ * part of an arithmetic expression or aggregate function (since INTERSECTS
+ * returns a numeric value).
+ */
+ @Override
+ protected Expression handleIntersects(Expression left, Expression right) {
+ if (isContainsCircle(left, right)) {
+ return circleIntersects(left, right, false);
+ }
+
+ Function intersectsFunction = new Function();
+ ExpressionList parameters = new ExpressionList(Arrays.asList(right, left));
+
+ intersectsFunction.setName(INTERSECTS_FUNCTION_NAME);
+ intersectsFunction.setParameters(parameters);
+
+ return intersectsFunction;
+ }
+
+ @Override
+ protected Expression handleArea(Function areaFunction) {
+ areaFunction.setName(ST_AREA_FUNCTION_NAME);
+
+ return metersToDegreeFunction(areaFunction);
+ }
+
+ private BinaryExpression convertToMeters(BinaryExpression binaryExpression) {
+ Expression left = binaryExpression.getLeftExpression();
+ Expression right = binaryExpression.getRightExpression();
+
+ if (isFunction(right)) {
+ Expression measureFunction = getInternalMeasureFunction(right);
+ if (measureFunction != null) {
+ right = measureFunction;
+ binaryExpression.setRightExpression(right);
+
+ if (isNumberValue(left)) {
+ DoubleValue leftNormalized = getDoubleValue(left);
+ DoubleValue leftInMeters = getArchDistanceInMetersFromExpression(leftNormalized);
+ binaryExpression.setLeftExpression(leftInMeters);
+ }
+ }
+ }
+
+ if (isFunction(left)) {
+ Expression measureFunction = getInternalMeasureFunction(left);
+ if (measureFunction != null) {
+ left = measureFunction;
+ binaryExpression.setLeftExpression(left);
+
+ if (isNumberValue(right)) {
+ DoubleValue rightNormalized = getDoubleValue(right);
+ DoubleValue rightInMeters = getArchDistanceInMetersFromExpression(rightNormalized);
+ binaryExpression.setRightExpression(rightInMeters);
+ }
+ }
+ }
+
+ return binaryExpression;
+ }
+
+ private Expression getInternalMeasureFunction(Expression expression) {
+ List measureFunctionParams = ((Function) expression).getParameters().getExpressions();
+
+ return measureFunctionParams
+ .stream()
+ .filter(exp -> isFunction(exp) && MEASURE_FUNCTIONS.contains(((Function) exp).getName()))
+ .findAny()
+ .orElse(null);
+ }
+
+ private Function handleDistance(Expression left, Expression right, String distanceFunctionName) {
+ Function distanceFunction = new Function();
+ ExpressionList parameters = new ExpressionList(Arrays.asList(right, left));
+
+ distanceFunction.setName(distanceFunctionName);
+ distanceFunction.setParameters(parameters);
+
+ return distanceFunction;
+ }
+
+ private Expression metersToDegreeFunction(Function measuresFunction) {
+ Function multiplyFunction = new Function();
+ multiplyFunction.setName(SAFE_MULTIPLY);
+ ExpressionList multiplyFunctionParameters = new ExpressionList(
+ Arrays.asList(
+ new DoubleValue(Double.toString(DEGREE_ARC_SECONDS)),
+ new DoubleValue(Double.toString(ARC_SECOND_METERS))
+ )
+ );
+ multiplyFunction.setParameters(multiplyFunctionParameters);
+
+ Function divideFunction = new Function();
+ divideFunction.setName(SAFE_DIVIDE);
+ ExpressionList divideFunctionParameters = new ExpressionList(Arrays.asList(measuresFunction, multiplyFunction));
+ divideFunction.setParameters(divideFunctionParameters);
+
+ return divideFunction;
+ }
+
+ /**
+ * This method is called when DISTANCE function is found.
+ */
+ @Override
+ protected Expression handleDistance(Expression left, Expression right) {
+ Function distanceFunction = handleDistance(left, right, ST_DISTANCE_FUNCTION_NAME);
+ return metersToDegreeFunction(distanceFunction);
+ }
+
+ private DoubleValue getDoubleValue(Expression expression) {
+ return isDoubleValue(expression) ?
+ (DoubleValue) expression :
+ new DoubleValue(((Long) ((LongValue) expression).getValue()).toString());
+ }
+
+ private boolean isDoubleValue(Expression expression) {
+ return (expression instanceof DoubleValue);
+ }
+
+ private boolean isLongValue(Expression expression) {
+ return (expression instanceof LongValue);
+ }
+
+ private boolean isNumberValue(Expression expression) {
+ return isDoubleValue(expression) || isLongValue(expression);
+ }
+
+ private boolean isFunction(Expression expression) {
+ return (expression instanceof Function);
+ }
+
+ private boolean isBinaryExpression(Expression expression) {
+ return (expression instanceof BinaryExpression);
+ }
+
+ private boolean isCircle(Expression expression) {
+ return expression.toString().toLowerCase().contains("circle");
+ }
+
+ private boolean isContainsCircle(Expression left, Expression right) {
+ return isCircle(left) || isCircle(right);
+ }
+
+ private DoubleValue getRadius(Expression expression) {
+ Expression radiusExpression = (Expression) ((Function) expression).getParameters().getExpressions().get(1);
+
+ double radius = getDoubleValue(radiusExpression).getValue();
+ double archDistanceInMeters = getArchDistanceInMeters(radius);
+
+ return new DoubleValue(Double.toString(archDistanceInMeters));
+ }
+
+ private DoubleValue getArchDistanceInMetersFromExpression(Expression expression) {
+ double measurement = ((DoubleValue) expression).getValue();
+ double measurementInMeters = getArchDistanceInMeters(measurement);
+ return new DoubleValue(Double.toString(measurementInMeters));
+ }
+
+ private double getArchDistanceInMeters(double measurement) {
+ return measurement * DEGREE_ARC_SECONDS * ARC_SECOND_METERS;
+ }
+
+ private Expression getCircleCenterPoint(Expression expression) {
+ return (Expression) ((Function) expression).getParameters().getExpressions().get(0);
+ }
+
+ private List circleDataParams(Expression left, Expression right, boolean isContains) {
+ if (isCircle(left)) {
+ DoubleValue radius = right.toString().toLowerCase().contains("point") && isContains ?
+ new DoubleValue("0") :
+ getRadius(left);
+
+ return new ArrayList<>(Arrays.asList(right, getCircleCenterPoint(left), radius));
+ }
+
+ return new ArrayList<>(Arrays.asList(getCircleCenterPoint(right), left, getRadius(right)));
+ }
+
+ private Expression shapeContainsShape(Expression left, Expression right, String distanceFunctionName, BinaryExpression binaryExpression) {
+ List paramList = circleDataParams(left, right, true);
+
+ int lastIndex = paramList.size() - 1;
+ Expression radius = paramList.get(lastIndex);
+ paramList.remove(lastIndex);
+
+ Expression containsFunction = handleDistance(paramList.get(0), paramList.get(1), distanceFunctionName);
+ binaryExpression.setLeftExpression(containsFunction);
+ binaryExpression.setRightExpression(radius);
+
+ return binaryExpression;
+ }
+
+ private Expression circleContainsPolygon(Expression left, Expression right) {
+ MinorThanEquals minorThanEquals = new MinorThanEquals();
+ Expression containsExpression = shapeContainsShape(left, right, ST_MAXDISTANCE_FUNCTION_NAME, minorThanEquals);
+
+ return containsExpression;
+ }
+
+ private Expression polygonContainsCircle(Expression left, Expression right) {
+ GreaterThanEquals greaterThanEquals = new GreaterThanEquals();
+ Expression containsExpression = shapeContainsShape(left, right, ST_DISTANCE_FUNCTION_NAME, greaterThanEquals);
+
+ return containsExpression;
+ }
+
+ private Function circleIntersects(Expression left, Expression right, boolean isContains) {
+ Function intersectsFunction = new Function();
+
+ intersectsFunction.setName(DWITHIN_FUNCTION_NAME);
+ List paramList = circleDataParams(left, right, isContains);
+
+ ExpressionList parameters = new ExpressionList(paramList);
+ intersectsFunction.setParameters(parameters);
+
+ return intersectsFunction;
+ }
+
+ private boolean isContainsPolygon(Expression expression) {
+ return expression.toString().toLowerCase().contains("polygon");
+ }
+}
diff --git a/cadc-tap-server-bigquery/src/main/java/ca/nrc/cadc/tap/parser/region/function/BqCircle.java b/cadc-tap-server-bigquery/src/main/java/ca/nrc/cadc/tap/parser/region/function/BqCircle.java
new file mode 100644
index 00000000..4a2e82d3
--- /dev/null
+++ b/cadc-tap-server-bigquery/src/main/java/ca/nrc/cadc/tap/parser/region/function/BqCircle.java
@@ -0,0 +1,86 @@
+
+/*
+ ************************************************************************
+ ******************* CANADIAN ASTRONOMY DATA CENTRE *******************
+ ************** CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES **************
+ *
+ * (c) 2019. (c) 2019.
+ * Government of Canada Gouvernement du Canada
+ * National Research Council Conseil national de recherches
+ * Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6
+ * All rights reserved Tous droits réservés
+ *
+ * NRC disclaims any warranties, Le CNRC dénie toute garantie
+ * expressed, implied, or énoncée, implicite ou légale,
+ * statutory, of any kind with de quelque nature que ce
+ * respect to the software, soit, concernant le logiciel,
+ * including without limitation y compris sans restriction
+ * any warranty of merchantability toute garantie de valeur
+ * or fitness for a particular marchande ou de pertinence
+ * purpose. NRC shall not be pour un usage particulier.
+ * liable in any event for any Le CNRC ne pourra en aucun cas
+ * damages, whether direct or être tenu responsable de tout
+ * indirect, special or general, dommage, direct ou indirect,
+ * consequential or incidental, particulier ou général,
+ * arising from the use of the accessoire ou fortuit, résultant
+ * software. Neither the name de l'utilisation du logiciel. Ni
+ * of the National Research le nom du Conseil National de
+ * Council of Canada nor the Recherches du Canada ni les noms
+ * names of its contributors may de ses participants ne peuvent
+ * be used to endorse or promote être utilisés pour approuver ou
+ * products derived from this promouvoir les produits dérivés
+ * software without specific prior de ce logiciel sans autorisation
+ * written permission. préalable et particulière
+ * par écrit.
+ *
+ * This file is part of the Ce fichier fait partie du projet
+ * OpenCADC project. OpenCADC.
+ *
+ * OpenCADC is free software: OpenCADC est un logiciel libre ;
+ * you can redistribute it and/or vous pouvez le redistribuer ou le
+ * modify it under the terms of modifier suivant les termes de
+ * the GNU Affero General Public la “GNU Affero General Public
+ * License as published by the License” telle que publiée
+ * Free Software Foundation, par la Free Software Foundation
+ * either version 3 of the : soit la version 3 de cette
+ * License, or (at your option) licence, soit (à votre gré)
+ * any later version. toute version ultérieure.
+ *
+ * OpenCADC is distributed in the OpenCADC est distribué
+ * hope that it will be useful, dans l’espoir qu’il vous
+ * but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE
+ * without even the implied GARANTIE : sans même la garantie
+ * warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ
+ * or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF
+ * PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence
+ * General Public License for Générale Publique GNU Affero
+ * more details. pour plus de détails.
+ *
+ * You should have received Vous devriez avoir reçu une
+ * a copy of the GNU Affero copie de la Licence Générale
+ * General Public License along Publique GNU Affero avec
+ * with OpenCADC. If not, see OpenCADC ; si ce n’est
+ * . pas le cas, consultez :
+ * .
+ *
+ *
+ ************************************************************************
+ */
+
+package ca.nrc.cadc.tap.parser.region.function;
+
+import net.sf.jsqlparser.expression.Expression;
+import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
+
+
+public class BqCircle extends BqGeometricFunction {
+ public BqCircle(Expression ra, Expression dec, Expression radius) {
+ super(ra, dec, radius);
+ }
+
+ @Override
+ String mapValues(ExpressionList parameterList) {
+ // Do nothing.
+ return null;
+ }
+}
diff --git a/cadc-tap-server-bigquery/src/main/java/ca/nrc/cadc/tap/parser/region/function/BqGeometricFunction.java b/cadc-tap-server-bigquery/src/main/java/ca/nrc/cadc/tap/parser/region/function/BqGeometricFunction.java
new file mode 100644
index 00000000..d0efaa05
--- /dev/null
+++ b/cadc-tap-server-bigquery/src/main/java/ca/nrc/cadc/tap/parser/region/function/BqGeometricFunction.java
@@ -0,0 +1,156 @@
+
+/*
+ ************************************************************************
+ ******************* CANADIAN ASTRONOMY DATA CENTRE *******************
+ ************** CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES **************
+ *
+ * (c) 2019. (c) 2019.
+ * Government of Canada Gouvernement du Canada
+ * National Research Council Conseil national de recherches
+ * Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6
+ * All rights reserved Tous droits réservés
+ *
+ * NRC disclaims any warranties, Le CNRC dénie toute garantie
+ * expressed, implied, or énoncée, implicite ou légale,
+ * statutory, of any kind with de quelque nature que ce
+ * respect to the software, soit, concernant le logiciel,
+ * including without limitation y compris sans restriction
+ * any warranty of merchantability toute garantie de valeur
+ * or fitness for a particular marchande ou de pertinence
+ * purpose. NRC shall not be pour un usage particulier.
+ * liable in any event for any Le CNRC ne pourra en aucun cas
+ * damages, whether direct or être tenu responsable de tout
+ * indirect, special or general, dommage, direct ou indirect,
+ * consequential or incidental, particulier ou général,
+ * arising from the use of the accessoire ou fortuit, résultant
+ * software. Neither the name de l'utilisation du logiciel. Ni
+ * of the National Research le nom du Conseil National de
+ * Council of Canada nor the Recherches du Canada ni les noms
+ * names of its contributors may de ses participants ne peuvent
+ * be used to endorse or promote être utilisés pour approuver ou
+ * products derived from this promouvoir les produits dérivés
+ * software without specific prior de ce logiciel sans autorisation
+ * written permission. préalable et particulière
+ * par écrit.
+ *
+ * This file is part of the Ce fichier fait partie du projet
+ * OpenCADC project. OpenCADC.
+ *
+ * OpenCADC is free software: OpenCADC est un logiciel libre ;
+ * you can redistribute it and/or vous pouvez le redistribuer ou le
+ * modify it under the terms of modifier suivant les termes de
+ * the GNU Affero General Public la “GNU Affero General Public
+ * License as published by the License” telle que publiée
+ * Free Software Foundation, par la Free Software Foundation
+ * either version 3 of the : soit la version 3 de cette
+ * License, or (at your option) licence, soit (à votre gré)
+ * any later version. toute version ultérieure.
+ *
+ * OpenCADC is distributed in the OpenCADC est distribué
+ * hope that it will be useful, dans l’espoir qu’il vous
+ * but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE
+ * without even the implied GARANTIE : sans même la garantie
+ * warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ
+ * or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF
+ * PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence
+ * General Public License for Générale Publique GNU Affero
+ * more details. pour plus de détails.
+ *
+ * You should have received Vous devriez avoir reçu une
+ * a copy of the GNU Affero copie de la Licence Générale
+ * General Public License along Publique GNU Affero avec
+ * with OpenCADC. If not, see OpenCADC ; si ce n’est
+ * . pas le cas, consultez :
+ * .
+ *
+ *
+ ************************************************************************
+ */
+
+package ca.nrc.cadc.tap.parser.region.function;
+
+import ca.nrc.cadc.tap.expression.BqKeywordExpression;
+import net.sf.jsqlparser.expression.Expression;
+import net.sf.jsqlparser.expression.Function;
+import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * Abstract class for an Bq Geometric Function.
+ */
+abstract class BqGeometricFunction extends Function {
+
+ private static final String POINT_FUNCTION_NAME = "ST_GEOGPOINT";
+ private static final String CIRCLE_FUNCTION_NAME = "CIRCLE";
+ private static final String POLYGON_FUNCTION_NAME = "ST_MAKEPOLYGON";
+ private static final String LINE_FUNCTION_NAME = "ST_MAKELINE";
+ private static final String ARRAY = "ARRAY";
+
+ final List vertices = new ArrayList<>();
+
+ BqGeometricFunction(Expression ra, Expression dec) {
+ setName(POINT_FUNCTION_NAME);
+
+ ExpressionList parameters = new ExpressionList(new ArrayList<>());
+ parameters.getExpressions().add(ra);
+ parameters.getExpressions().add(dec);
+
+ setParameters(parameters);
+ }
+
+ BqGeometricFunction(Expression ra, Expression dec, Expression radius) {
+ setName(CIRCLE_FUNCTION_NAME);
+
+ Function pointFunction = new Function();
+ pointFunction.setName(POINT_FUNCTION_NAME);
+ pointFunction.setParameters(new ExpressionList(Arrays.asList(ra, dec)));
+
+ ExpressionList parameters = new ExpressionList(new ArrayList<>());
+ parameters.getExpressions().add(pointFunction);
+ parameters.getExpressions().add(radius);
+
+ setParameters(parameters);
+ }
+
+ BqGeometricFunction(List verticeExpressions) {
+ if (verticeExpressions != null) {
+ List verticeValues = verticeExpressions.stream().skip(1).collect(Collectors.toList());
+ vertices.addAll(verticeValues);
+ }
+ }
+
+ private Function getMakeLineFunction() {
+ Function makeLineFunction = new Function();
+ makeLineFunction.setName(LINE_FUNCTION_NAME);
+
+ return makeLineFunction;
+ }
+
+ /**
+ * For Polygon shapes (i.e. non-point shapes), convert the values to be used as function parameters. Point
+ * Functions can omit this call.
+ */
+ void processVerticesParameters() {
+ setName(POLYGON_FUNCTION_NAME);
+
+ Function makeLineFunction = getMakeLineFunction();
+
+ ExpressionList verticesArrayFunctionParameters = new ExpressionList(new ArrayList<>());
+ String geoText = String.format("%s%s", ARRAY, mapValues(verticesArrayFunctionParameters));
+
+ makeLineFunction.setParameters(new ExpressionList(Arrays.asList(new BqKeywordExpression(geoText))));
+
+ setParameters(new ExpressionList(Arrays.asList(makeLineFunction)));
+ }
+
+ /**
+ * Map this shape's values to BQ function parameters.
+ *
+ * @param parameterList The ExpressionList to add parameters to.
+ */
+ abstract String mapValues(ExpressionList parameterList);
+}
diff --git a/cadc-tap-server-bigquery/src/main/java/ca/nrc/cadc/tap/parser/region/function/BqPoint.java b/cadc-tap-server-bigquery/src/main/java/ca/nrc/cadc/tap/parser/region/function/BqPoint.java
new file mode 100644
index 00000000..11c6cad9
--- /dev/null
+++ b/cadc-tap-server-bigquery/src/main/java/ca/nrc/cadc/tap/parser/region/function/BqPoint.java
@@ -0,0 +1,86 @@
+
+/*
+ ************************************************************************
+ ******************* CANADIAN ASTRONOMY DATA CENTRE *******************
+ ************** CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES **************
+ *
+ * (c) 2019. (c) 2019.
+ * Government of Canada Gouvernement du Canada
+ * National Research Council Conseil national de recherches
+ * Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6
+ * All rights reserved Tous droits réservés
+ *
+ * NRC disclaims any warranties, Le CNRC dénie toute garantie
+ * expressed, implied, or énoncée, implicite ou légale,
+ * statutory, of any kind with de quelque nature que ce
+ * respect to the software, soit, concernant le logiciel,
+ * including without limitation y compris sans restriction
+ * any warranty of merchantability toute garantie de valeur
+ * or fitness for a particular marchande ou de pertinence
+ * purpose. NRC shall not be pour un usage particulier.
+ * liable in any event for any Le CNRC ne pourra en aucun cas
+ * damages, whether direct or être tenu responsable de tout
+ * indirect, special or general, dommage, direct ou indirect,
+ * consequential or incidental, particulier ou général,
+ * arising from the use of the accessoire ou fortuit, résultant
+ * software. Neither the name de l'utilisation du logiciel. Ni
+ * of the National Research le nom du Conseil National de
+ * Council of Canada nor the Recherches du Canada ni les noms
+ * names of its contributors may de ses participants ne peuvent
+ * be used to endorse or promote être utilisés pour approuver ou
+ * products derived from this promouvoir les produits dérivés
+ * software without specific prior de ce logiciel sans autorisation
+ * written permission. préalable et particulière
+ * par écrit.
+ *
+ * This file is part of the Ce fichier fait partie du projet
+ * OpenCADC project. OpenCADC.
+ *
+ * OpenCADC is free software: OpenCADC est un logiciel libre ;
+ * you can redistribute it and/or vous pouvez le redistribuer ou le
+ * modify it under the terms of modifier suivant les termes de
+ * the GNU Affero General Public la “GNU Affero General Public
+ * License as published by the License” telle que publiée
+ * Free Software Foundation, par la Free Software Foundation
+ * either version 3 of the : soit la version 3 de cette
+ * License, or (at your option) licence, soit (à votre gré)
+ * any later version. toute version ultérieure.
+ *
+ * OpenCADC is distributed in the OpenCADC est distribué
+ * hope that it will be useful, dans l’espoir qu’il vous
+ * but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE
+ * without even the implied GARANTIE : sans même la garantie
+ * warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ
+ * or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF
+ * PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence
+ * General Public License for Générale Publique GNU Affero
+ * more details. pour plus de détails.
+ *
+ * You should have received Vous devriez avoir reçu une
+ * a copy of the GNU Affero copie de la Licence Générale
+ * General Public License along Publique GNU Affero avec
+ * with OpenCADC. If not, see OpenCADC ; si ce n’est
+ * . pas le cas, consultez :
+ * .
+ *
+ *
+ ************************************************************************
+ */
+
+package ca.nrc.cadc.tap.parser.region.function;
+
+import net.sf.jsqlparser.expression.Expression;
+import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
+
+
+public class BqPoint extends BqGeometricFunction {
+ public BqPoint(Expression ra, Expression dec) {
+ super(ra, dec);
+ }
+
+ @Override
+ String mapValues(ExpressionList parameterList) {
+ // Do nothing.
+ return null;
+ }
+}
diff --git a/cadc-tap-server-bigquery/src/main/java/ca/nrc/cadc/tap/parser/region/function/BqPolygon.java b/cadc-tap-server-bigquery/src/main/java/ca/nrc/cadc/tap/parser/region/function/BqPolygon.java
new file mode 100644
index 00000000..d7d4427f
--- /dev/null
+++ b/cadc-tap-server-bigquery/src/main/java/ca/nrc/cadc/tap/parser/region/function/BqPolygon.java
@@ -0,0 +1,115 @@
+
+/*
+ ************************************************************************
+ ******************* CANADIAN ASTRONOMY DATA CENTRE *******************
+ ************** CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES **************
+ *
+ * (c) 2019. (c) 2019.
+ * Government of Canada Gouvernement du Canada
+ * National Research Council Conseil national de recherches
+ * Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6
+ * All rights reserved Tous droits réservés
+ *
+ * NRC disclaims any warranties, Le CNRC dénie toute garantie
+ * expressed, implied, or énoncée, implicite ou légale,
+ * statutory, of any kind with de quelque nature que ce
+ * respect to the software, soit, concernant le logiciel,
+ * including without limitation y compris sans restriction
+ * any warranty of merchantability toute garantie de valeur
+ * or fitness for a particular marchande ou de pertinence
+ * purpose. NRC shall not be pour un usage particulier.
+ * liable in any event for any Le CNRC ne pourra en aucun cas
+ * damages, whether direct or être tenu responsable de tout
+ * indirect, special or general, dommage, direct ou indirect,
+ * consequential or incidental, particulier ou général,
+ * arising from the use of the accessoire ou fortuit, résultant
+ * software. Neither the name de l'utilisation du logiciel. Ni
+ * of the National Research le nom du Conseil National de
+ * Council of Canada nor the Recherches du Canada ni les noms
+ * names of its contributors may de ses participants ne peuvent
+ * be used to endorse or promote être utilisés pour approuver ou
+ * products derived from this promouvoir les produits dérivés
+ * software without specific prior de ce logiciel sans autorisation
+ * written permission. préalable et particulière
+ * par écrit.
+ *
+ * This file is part of the Ce fichier fait partie du projet
+ * OpenCADC project. OpenCADC.
+ *
+ * OpenCADC is free software: OpenCADC est un logiciel libre ;
+ * you can redistribute it and/or vous pouvez le redistribuer ou le
+ * modify it under the terms of modifier suivant les termes de
+ * the GNU Affero General Public la “GNU Affero General Public
+ * License as published by the License” telle que publiée
+ * Free Software Foundation, par la Free Software Foundation
+ * either version 3 of the : soit la version 3 de cette
+ * License, or (at your option) licence, soit (à votre gré)
+ * any later version. toute version ultérieure.
+ *
+ * OpenCADC is distributed in the OpenCADC est distribué
+ * hope that it will be useful, dans l’espoir qu’il vous
+ * but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE
+ * without even the implied GARANTIE : sans même la garantie
+ * warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ
+ * or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF
+ * PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence
+ * General Public License for Générale Publique GNU Affero
+ * more details. pour plus de détails.
+ *
+ * You should have received Vous devriez avoir reçu une
+ * a copy of the GNU Affero copie de la Licence Générale
+ * General Public License along Publique GNU Affero avec
+ * with OpenCADC. If not, see OpenCADC ; si ce n’est
+ * . pas le cas, consultez :
+ * .
+ *
+ *
+ ************************************************************************
+ */
+
+package ca.nrc.cadc.tap.parser.region.function;
+
+import net.sf.jsqlparser.expression.Expression;
+import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
+
+import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+
+public class BqPolygon extends BqGeometricFunction {
+
+ public BqPolygon(List verticeExpressions) {
+ super(verticeExpressions);
+
+ if (!vertices.isEmpty()) {
+ processVerticesParameters();
+ }
+ }
+
+ /**
+ * Map this shape's values to BQ function parameters.
+ *
+ * @param parameterList The ExpressionList to add parameters to.
+ */
+ @Override
+ String mapValues(ExpressionList parameterList) {
+ ExpressionList points = new ExpressionList(
+ IntStream
+ .range(0, vertices.size())
+ .filter(i -> i % 2 == 0)
+ .mapToObj(i -> pointBuilder(i))
+ .collect(Collectors.toList())
+ );
+
+ points.getExpressions().add(pointBuilder(0));
+
+ return points.getExpressions().toString();
+ }
+
+ private BqPoint pointBuilder(int i) {
+ Expression ra = vertices.get(i);
+ Expression dec = vertices.get(i + 1);
+
+ return new BqPoint(ra, dec);
+ }
+}
diff --git a/cadc-tap-server-bigquery/src/main/java/ca/nrc/cadc/tap/writer/format/BqFormatFactory.java b/cadc-tap-server-bigquery/src/main/java/ca/nrc/cadc/tap/writer/format/BqFormatFactory.java
new file mode 100644
index 00000000..8a2dc0a1
--- /dev/null
+++ b/cadc-tap-server-bigquery/src/main/java/ca/nrc/cadc/tap/writer/format/BqFormatFactory.java
@@ -0,0 +1,91 @@
+
+/*
+ ************************************************************************
+ ******************* CANADIAN ASTRONOMY DATA CENTRE *******************
+ ************** CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES **************
+ *
+ * (c) 2018. (c) 2018.
+ * Government of Canada Gouvernement du Canada
+ * National Research Council Conseil national de recherches
+ * Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6
+ * All rights reserved Tous droits réservés
+ *
+ * NRC disclaims any warranties, Le CNRC dénie toute garantie
+ * expressed, implied, or énoncée, implicite ou légale,
+ * statutory, of any kind with de quelque nature que ce
+ * respect to the software, soit, concernant le logiciel,
+ * including without limitation y compris sans restriction
+ * any warranty of merchantability toute garantie de valeur
+ * or fitness for a particular marchande ou de pertinence
+ * purpose. NRC shall not be pour un usage particulier.
+ * liable in any event for any Le CNRC ne pourra en aucun cas
+ * damages, whether direct or être tenu responsable de tout
+ * indirect, special or general, dommage, direct ou indirect,
+ * consequential or incidental, particulier ou général,
+ * arising from the use of the accessoire ou fortuit, résultant
+ * software. Neither the name de l'utilisation du logiciel. Ni
+ * of the National Research le nom du Conseil National de
+ * Council of Canada nor the Recherches du Canada ni les noms
+ * names of its contributors may de ses participants ne peuvent
+ * be used to endorse or promote être utilisés pour approuver ou
+ * products derived from this promouvoir les produits dérivés
+ * software without specific prior de ce logiciel sans autorisation
+ * written permission. préalable et particulière
+ * par écrit.
+ *
+ * This file is part of the Ce fichier fait partie du projet
+ * OpenCADC project. OpenCADC.
+ *
+ * OpenCADC is free software: OpenCADC est un logiciel libre ;
+ * you can redistribute it and/or vous pouvez le redistribuer ou le
+ * modify it under the terms of modifier suivant les termes de
+ * the GNU Affero General Public la “GNU Affero General Public
+ * License as published by the License” telle que publiée
+ * Free Software Foundation, par la Free Software Foundation
+ * either version 3 of the : soit la version 3 de cette
+ * License, or (at your option) licence, soit (à votre gré)
+ * any later version. toute version ultérieure.
+ *
+ * OpenCADC is distributed in the OpenCADC est distribué
+ * hope that it will be useful, dans l’espoir qu’il vous
+ * but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE
+ * without even the implied GARANTIE : sans même la garantie
+ * warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ
+ * or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF
+ * PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence
+ * General Public License for Générale Publique GNU Affero
+ * more details. pour plus de détails.
+ *
+ * You should have received Vous devriez avoir reçu une
+ * a copy of the GNU Affero copie de la Licence Générale
+ * General Public License along Publique GNU Affero avec
+ * with OpenCADC. If not, see OpenCADC ; si ce n’est
+ * . pas le cas, consultez :
+ * .
+ *
+ *
+ ************************************************************************
+ */
+
+package ca.nrc.cadc.tap.writer.format;
+
+import ca.nrc.cadc.dali.util.Format;
+import ca.nrc.cadc.tap.TapSelectItem;
+
+public class BqFormatFactory extends DefaultFormatFactory {
+
+ @Override
+ protected Format