net.starschema.clouddb.jdbc.BQDatabaseMetadata.java Source code

Java tutorial

Introduction

Here is the source code for net.starschema.clouddb.jdbc.BQDatabaseMetadata.java

Source

/**
 * Starschema Big Query JDBC Driver
 * Copyright (C) 2012, Starschema Ltd.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 *
 * This class implements the java.sql.DatabaseMetaData interface
 */

package net.starschema.clouddb.jdbc;

import java.io.IOException;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.RowIdLifetime;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import net.starschema.clouddb.jdbc.DMDResultSet.DMDResultSetType;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.google.api.services.bigquery.model.DatasetList;
import com.google.api.services.bigquery.model.DatasetList.Datasets;
import com.google.api.services.bigquery.model.ProjectList.Projects;
import com.google.api.services.bigquery.model.Table;
import com.google.api.services.bigquery.model.TableFieldSchema;

// import net.starschema.clouddb.bqjdbc.logging.Logger;

/**
 * This class implements the DatabaseMetadata interface
 *
 * @author Gunics Balzs, Horvth Attila
 */
class BQDatabaseMetadata implements DatabaseMetaData {

    /**
     * Reference for the Connection object that made this DatabaseMetadata
     * object
     */
    BQConnection Connection;

    /**
     * Reference for the Logger Class
     */
    private static final Log logger = LogFactory.getLog(BQDatabaseMetadata.class);

    /**
     * We currently doesn't support multiple open resultsets.
     */
    static boolean multipleOpenResultsSupported = false;

    /**
     * Constructor that initializes variables
     *
     * @param bqConnection
     */
    public BQDatabaseMetadata(BQConnection bqConnection) {
        this.Connection = bqConnection;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Since bigquery doesn't support stored jobs, we'll return with a false.
     * </p>
     *
     * @return false
     */
    @Override
    public boolean allProceduresAreCallable() throws SQLException {
        return false;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Only the usable Tables name are returned.
     * </p>
     *
     * @return true
     */
    @Override
    public boolean allTablesAreSelectable() throws SQLException {
        return true;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Since commit is not supported, we return false, and no result sets will
     * be closed, nor committed
     * </p>
     *
     * @return false
     */
    @Override
    public boolean autoCommitFailureClosesAllResultSets() throws SQLException {
        return false;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * This feature missing from the driver, so we return with a false
     * </p>
     *
     * @return false
     */
    @Override
    public boolean dataDefinitionCausesTransactionCommit() throws SQLException {
        return false;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * This feature missing from the driver.
     * </p>
     *
     * @return true
     */
    @Override
    public boolean dataDefinitionIgnoredInTransactions() throws SQLException {
        return true;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Bigquery doesn't has a delete function, we can delete only tables.
     * </p>
     *
     * @return false
     */
    @Override
    public boolean deletesAreDetected(int type) throws SQLException {
        return false;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * LONGVARCHAR and LONGVARBINARY are not supported.
     * </p>
     *
     * @return false
     */
    @Override
    public boolean doesMaxRowSizeIncludeBlobs() throws SQLException {
        return false;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * returns an empty resultset
     * </p>
     *
     * @return empty resultset
     */
    @Override
    public ResultSet getAttributes(String catalog, String schemaPattern, String typeNamePattern,
            String attributeNamePattern) throws SQLException {
        logger.debug("Function call getAttributes catalog: " + (catalog != null ? catalog : "null")
                + ", schemaPattern: " + (schemaPattern != null ? schemaPattern : "null") + ", typeNamePattern:"
                + (typeNamePattern != null ? typeNamePattern : "null") + ", attributeNamePattern: "
                + (attributeNamePattern != null ? attributeNamePattern : "null"));
        logger.debug("not implemented yet returning empty resultset");
        String[] Col = new String[21];
        Col[0] = "TYPE_CAT";
        // String => type catalog (may be null)
        Col[1] = "TYPE_SCHEM";
        // String => type schema (may be null)
        Col[2] = "TYPE_NAME";
        // String => type name
        Col[3] = "ATTR_NAME";
        // String => attribute name
        Col[4] = "DATA_TYPE";
        // int => attribute type SQL type from java.sql.Types
        Col[5] = "ATTR_TYPE_NAME";
        // String => Data source dependent type name. For a UDT, the type name
        // is fully qualified. For a REF, the type name is fully qualified and
        // represents the target type of the reference type.
        Col[6] = "ATTR_SIZE";
        // int => column size. For char or date types this is the maximum number
        // of characters; for numeric or decimal types this is precision.
        Col[7] = "DECIMAL_DIGITS";
        // int => the number of fractional digits. Null is returned for data
        // types where DECIMAL_DIGITS is not applicable.
        Col[8] = "NUM_PREC_RADIX";
        // int => Radix (typically either 10 or 2)
        Col[9] = "NULLABLE";
        // int => whether NULL is allowed
        Col[10] = "REMARKS";
        // String => comment describing column (may be null)
        Col[11] = "ATTR_DEF";
        // String => default value (may be null)
        Col[12] = "SQL_DATA_TYPE";
        // int => unused
        Col[13] = "SQL_DATETIME_SUB";
        // int => unused
        Col[14] = "CHAR_OCTET_LENGTH";
        // int => for char types the maximum number of bytes in the column
        Col[15] = "ORDINAL_POSITION";
        // int => index of the attribute in the UDT (starting at 1)
        Col[16] = "IS_NULLABLE";
        // String => ISO rules are used to determine the nullability for a
        // attribute.
        Col[17] = "SCOPE_CATALOG";
        // String => catalog of table that is the scope of a reference attribute
        // (null if DATA_TYPE isn't REF)
        Col[18] = "SCOPE_SCHEMA";
        // String => schema of table that is the scope of a reference attribute
        // (null if DATA_TYPE isn't REF)
        Col[19] = "SCOPE_TABLE";
        // String => table name that is the scope of a reference attribute (null
        // if the DATA_TYPE isn't REF)
        Col[20] = "SOURCE_DATA_TYPE";
        // short => source type of a distinct type or user-generated Ref
        // type,SQL type from java.sql.Types (null if DATA_TYPE isn't DISTINCT
        // or user-generated REF)
        return new DMDResultSet(new Object[0][21], Col, DMDResultSetType.getAttributes);
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * This feature is not yet impelemented.
     * </p>
     *
     * @return an empty dataset
     */
    @Override
    public ResultSet getBestRowIdentifier(String catalog, String schema, String table, int scope, boolean nullable)
            throws SQLException {
        logger.debug("Function call getBestRowIdentifier(String,String,String,int,boolean)");
        logger.debug("Not implemented yet returning empty resultset");
        String[] Col = new String[8];
        Col[0] = "SCOPE";
        // short => actual scope of result
        Col[1] = "COLUMN_NAME";
        // String => column name
        Col[2] = "DATA_TYPE";
        // int => SQL data type from java.sql.Types
        Col[3] = "TYPE_NAME";
        // String => Data source dependent type name, for a UDT the type name is
        // fully qualified
        Col[4] = "COLUMN_SIZE";
        // int => precision
        Col[5] = "BUFFER_LENGTH";
        // int => not used
        Col[6] = "DECIMAL_DIGITS";
        // short => scale - Null is returned for data types where DECIMAL_DIGITS
        // is not applicable.
        Col[7] = "PSEUDO_COLUMN";
        // short => is this a pseudo column like an Oracle ROWID
        return new DMDResultSet(new Object[0][8], Col, DMDResultSetType.getBestRowIdentifier);
    }

    /** {@inheritDoc} */
    @Override
    public ResultSet getCatalogs() throws SQLException {
        logger.debug("Function call getCatalogs()");
        try {
            List<Projects> Projects = this.Connection.getBigquery().projects().list().execute().getProjects();

            if (Projects != null && Projects.size() != 0) {
                String[] Data = new String[Projects.size()];
                String toLog = "";
                for (int i = 0; i < Projects.size(); i++) {
                    Data[i] = Projects.get(i).getId().replace(":", "__").replace(".", "_");
                    toLog += Data[i] + " , ";
                }
                logger.debug("Catalogs are: " + toLog);
                return new DMDResultSet(Data, new String[] { "TABLE_CAT" }, DMDResultSetType.getCatalogs);
            } else {
                logger.debug("nothing to return");
                return new DMDResultSet(new String[] { null }, new String[] { "TABLE_CAT" },
                        DMDResultSetType.getCatalogs);
            }
        } catch (IOException e) {
            throw new BQSQLException(e);
        }
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns a : as a catalog separator
     * </p>
     *
     * @return :
     */
    @Override
    public String getCatalogSeparator() throws BQSQLException {
        logger.debug("function call: getCatalogSeparator() return is ':'");
        return ":";
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns the default catalog term: "project"
     * </p>
     *
     * @return project
     */
    @Override
    public String getCatalogTerm() throws SQLException {
        logger.debug("function call: getCatalogTerm()");
        return "project";
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * returns the supported clients in a result set
     * </p>
     *
     * @return supported clients
     */
    @Override
    public ResultSet getClientInfoProperties() throws SQLException {
        logger.debug("Function call getClientInfoProperties()");
        return new DMDResultSet(new Object[][] { { "iSQL", 64, "iSQL", "http://isql.sourceforge.net/" } }

                , new String[] { "NAME", "MAX_LEN", "DEFAULT_VALUE", "DESCRIPTION" },
                DMDResultSetType.getClientInfoProperties);
        // TODO add more clients!
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Since no Grantor, Grantee, and privilege, this won't be used, we'll
     * return an empty resultset
     * </p>
     *
     * @returns a Resultset with no Data
     */
    @Override
    public ResultSet getColumnPrivileges(String catalog, String schema, String table, String columnNamePattern)
            throws SQLException {
        logger.debug("Function call getColumnPrivileges(String,String,String,String)");
        logger.debug("Returning an empty resultset");
        String[] Col = new String[8];
        Col[0] = "TABLE_CAT"; // String => table catalog (may be null)
        Col[1] = "TABLE_SCHEM"; // String => table schema (may be null)
        Col[2] = "TABLE_NAME"; // String => table name
        Col[3] = "COLUMN_NAME"; // String => column name
        Col[4] = "GRANTOR"; // String => grantor of access (may be null)
        Col[5] = "GRANTEE"; // String => grantee of access
        Col[6] = "PRIVILEGE"; // String => name of access (SELECT, INSERT,
        // UPDATE, REFRENCES, ...)
        Col[7] = "IS_GRANTABLE";// String => "YES" if grantee is permitted to
        // grant to others;
        // "NO" if not; null if unknown
        return new DMDResultSet(new Object[][] { { null, null, table, "", null, "", "", "NO" } }, Col,
                DMDResultSetType.getColumnPrivileges);
        // TODO we might need this more implemented.
    }

    /** {@inheritDoc} */
    @Override
    public ResultSet getColumns(String catalog, String schemaPattern, String tableNamePattern,
            String columnNamePattern) throws SQLException {
        logger.debug("Function call getColumns" + "catalog: " + (catalog != null ? catalog : "null")
                + ", schemaPattern: " + (schemaPattern != null ? schemaPattern : "null") + ", tableNamePattern:"
                + (tableNamePattern != null ? tableNamePattern : "null") + ", columnNamePattern: "
                + (columnNamePattern != null ? columnNamePattern : "null"));
        List<Table> Tables = null;
        try {
            Tables = BQSupportFuncts.getTables(this.Connection, catalog, schemaPattern, tableNamePattern);
            if (Tables == null) { //Because of Crystal Reports It's not elegant, but hey it works!
                Tables = BQSupportFuncts.getTables(this.Connection, schemaPattern, catalog, tableNamePattern);
            }
        } catch (IOException e) {
            throw new BQSQLException(e);
        }

        if (Tables != null) {
            List<String[]> data = new ArrayList<String[]>();
            for (int i = 0; i < Tables.size(); i++) {
                String UparsedId = Tables.get(i).getId();
                String ProjectId = BQSupportFuncts.getProjectIdFromAnyGetId(UparsedId).replace(":", "__")
                        .replace(".", "_");
                String DatasetId = BQSupportFuncts.getDatasetIdFromTableDotGetId(UparsedId);
                String TableId = BQSupportFuncts.getTableIdFromTableDotGetId(UparsedId);

                List<TableFieldSchema> tblfldschemas = Tables.get(i).getSchema().getFields();
                if (tblfldschemas != null && tblfldschemas.size() != 0) {
                    int index = 1;
                    for (TableFieldSchema Column : tblfldschemas) {
                        if (columnNamePattern == null
                                || BQSupportFuncts.matchPattern(Column.getName(), columnNamePattern)) {
                            String[] Col = new String[23];
                            // TABLE_CAT String => table catalog (may be null)
                            Col[0] = ProjectId;
                            // TABLE_SCHEM String => table schema (may be null)
                            Col[1] = DatasetId;
                            // TABLE_NAME String => table name
                            Col[2] = TableId;
                            // COLUMN_NAME String => column name
                            Col[3] = Column.getName();
                            // DATA_TYPE int => SQL type from java.sql.Types
                            Col[4] = String.valueOf(BQSupportFuncts.parseToSqlFieldType(Column.getType()));
                            // TYPE_NAME String => Data source dependent type
                            // name, for a UDT the type name is fully qualified
                            Col[5] = Column.getType();
                            // COLUMN_SIZE int => column size. (In Bigquery max
                            // colsize is 64kb and its not specifically
                            // determined for fields)
                            Col[6] = "0"; //String.valueOf(Column.size());
                            // BUFFER_LENGTH is not used.
                            Col[7] = null;
                            // DECIMAL_DIGITS int => the number of fractional
                            // digits. Null is returned for data types where
                            // DECIMAL_DIGITS is not applicable.
                            Col[8] = null;
                            // NUM_PREC_RADIX int => Radix (typically either 10
                            // or 2)
                            Col[9] = null;
                            // NULLABLE int => is NULL allowed.
                            Col[10] = nullableAsInt(Column.getMode());
                            // REMARKS String => comment describing column (may
                            // be null)
                            Col[11] = null;
                            // COLUMN_DEF String => default value for the
                            // column, which should be interpreted as a string
                            // when the value is enclosed in single quotes (may
                            // be null)
                            Col[12] = "String";
                            // SQL_DATA_TYPE int => unused
                            Col[13] = Column.getType();
                            // SQL_DATETIME_SUB int => unused
                            Col[14] = null;
                            // CHAR_OCTET_LENGTH int => for char types the
                            // maximum number of bytes in the column
                            Col[15] = String.valueOf(64 * 1024);
                            // ORDINAL_POSITION int => index of column in table
                            // (starting at 1)
                            Col[16] = String.valueOf(index);
                            // IS_NULLABLE String => ISO rules are used to
                            // determine the nullability for a column.
                            Col[17] = isNullableISO(Column.getMode());
                            // SCOPE_CATLOG String => catalog of table that is
                            // the scope of a reference attribute (null if
                            // DATA_TYPE isn't REF)
                            Col[18] = null;
                            // SCOPE_SCHEMA String => schema of table that is
                            // the scope of a reference attribute (null if the
                            // DATA_TYPE isn't REF)
                            Col[19] = null;
                            // SCOPE_TABLE String => table name that this the
                            // scope of a reference attribure (null if the
                            // DATA_TYPE isn't REF)
                            Col[20] = null;
                            // SOURCE_DATA_TYPE short => source type of a
                            // distinct type or user-generated Ref type, SQL
                            // type from java.sql.Types (null if DATA_TYPE isn't
                            // DISTINCT or user-generated REF)
                            Col[21] = null;
                            // IS_AUTOINCREMENT String => Indicates whether this
                            // column is auto incremented
                            Col[22] = "";
                            data.add(Col);
                        }
                        index++;
                    }
                }
            }
            if (data.size() == 0) {
                return null;
            } else {
                String[][] List = new String[data.size()][23];
                for (int i = 0; i < data.size(); i++) {
                    List[i] = data.get(i);
                }
                return new DMDResultSet(List,
                        new String[] { "TABLE_CAT", "TABLE_SCHEM", "TABLE_NAME", "COLUMN_NAME", "DATA_TYPE",
                                "TYPE_NAME", "COLUMN_SIZE", "BUFFER_LENGTH", "DECIMAL_DIGITS", "NUM_PREC_RADIX",
                                "NULLABLE", "REMARKS", "COLUMN_DEF", "SQL_DATA_TYPE", "SQL_DATETIME_SUB",
                                "CHAR_OCTET_LENGTH", "ORDINAL_POSITION", "IS_NULLABLE", "SCOPE_CATLOG",
                                "SCOPE_SCHEMA", "SCOPE_TABLE", "SOURCE_DATA_TYPE", "IS_AUTOINCREMENT", },
                        DMDResultSetType.getColumns);
            }
        } else {
            return new DMDResultSet(
                    new String[][] { { null, null, null, null, null, null, null, null, null, null, null, null, null,
                            null, null, null, null, null, null, null, null, null, null } },
                    new String[] { "TABLE_CAT", "TABLE_SCHEM", "TABLE_NAME", "COLUMN_NAME", "DATA_TYPE",
                            "TYPE_NAME", "COLUMN_SIZE", "BUFFER_LENGTH", "DECIMAL_DIGITS", "NUM_PREC_RADIX",
                            "NULLABLE", "REMARKS", "COLUMN_DEF", "SQL_DATA_TYPE", "SQL_DATETIME_SUB",
                            "CHAR_OCTET_LENGTH", "ORDINAL_POSITION", "IS_NULLABLE", "SCOPE_CATLOG", "SCOPE_SCHEMA",
                            "SCOPE_TABLE", "SOURCE_DATA_TYPE", "IS_AUTOINCREMENT", },
                    DMDResultSetType.getColumns);
        }
    }

    private String nullableAsInt(String mode) {
        if (mode == null) {
            return String.valueOf(DatabaseMetaData.attributeNullableUnknown);
        }
        if ("NULLABLE".equals(mode)) {
            return String.valueOf(DatabaseMetaData.attributeNullable);
        }
        if ("REQUIRED".equals(mode)) {
            return String.valueOf(DatabaseMetaData.attributeNoNulls);
        }
        if ("REPEATED".equals(mode)) {
            return String.valueOf(DatabaseMetaData.attributeNullableUnknown);
        }
        return String.valueOf(DatabaseMetaData.attributeNullableUnknown);
    }

    private String isNullableISO(String mode) {
        if (mode == null) {
            return "";
        }
        if ("NULLABLE".equals(mode)) {
            return "YES";
        }
        if ("REQUIRED".equals(mode)) {
            return "NO";
        }
        if ("REPEATED".equals(mode)) {
            return "";
        }
        return "";
    }

    /** {@inheritDoc} */
    @Override
    public Connection getConnection() throws SQLException {
        return this.Connection;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Cross Reference Not supported, we return an empty resulset
     * </p>
     *
     * @return an empty resultset
     */
    @Override
    public ResultSet getCrossReference(String parentCatalog, String parentSchema, String parentTable,
            String foreignCatalog, String foreignSchema, String foreignTable) throws SQLException {
        logger.debug("Function call getCrossReference(String,String,String,String,String,String)");
        String[] Col = new String[14];
        Col[0] = "PKTABLE_CAT";
        // String => parent key table catalog (may be null)
        Col[1] = "PKTABLE_SCHEM";
        // String => parent key table schema (may be null)
        Col[2] = "PKTABLE_NAME";
        // String => parent key table name
        Col[3] = "PKCOLUMN_NAME";
        // String => parent key column name
        Col[4] = "FKTABLE_CAT";
        // String => foreign key table catalog (may be null) being exported (may
        // be null)
        Col[5] = "FKTABLE_SCHEM";
        // String => foreign key table schema (may be null) being exported (may
        // be null)
        Col[6] = "FKTABLE_NAME";
        // String => foreign key table name being exported
        Col[7] = "FCOLUMN_NAME";
        // String => foreign key column name being exported
        Col[8] = "KEY_SEQ";
        // short => sequence number within foreign key( a value of 1 represents
        // the first column of the foreign key, a value of 2 would represent the
        // second column within the foreign key).
        Col[9] = "UPDATE_RULE";
        // short => What happens to foreign key when parent key is updated:
        Col[10] = "DELETE_RULE";
        // short => What happens to the foreign key when parent key is deleted.
        Col[11] = "FK_NAME";
        // String => foreign key name (may be null)
        Col[12] = "PK_NAME";
        // String => parent key name (may be null)
        Col[13] = "DEFERRABILITY";
        // short => can the evaluation of foreign key constraints be deferred
        // until commit
        return new DMDResultSet(new Object[0][14], Col, DMDResultSetType.getCrossReference);
        // TODO
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Current version is 2-1.3.3 Returns 2
     * </p>
     */
    @Override
    public int getDatabaseMajorVersion() throws SQLException {
        return 2;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Current version is 2-1.3.3 Returns 1
     * </p>
     */
    @Override
    public int getDatabaseMinorVersion() throws SQLException {
        return 1;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns "Google Big Query"
     * </p>
     */
    @Override
    public String getDatabaseProductName() throws SQLException {
        return "Google Big Query";
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns "google bigquery v2-1.3.3-beta"
     * </p>
     */
    @Override
    public String getDatabaseProductVersion() throws SQLException {
        return "google bigquery v2-1.3.3-beta";
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Commit is not supported, so we return with no transaction
     * </p>
     *
     * return TRANSACTION_NONE
     */
    @Override
    public int getDefaultTransactionIsolation() throws SQLException {
        return java.sql.Connection.TRANSACTION_NONE;
    }

    /** {@inheritDoc} */
    @Override
    public int getDriverMajorVersion() {
        return BQDriver.getMajorVersionAsStatic();
    }

    /** {@inheritDoc} */
    @Override
    public int getDriverMinorVersion() {
        return BQDriver.getMinorVersionAsStatic();
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns "Starschema.net:BigQuery JDBC driver"
     * </p>
     */
    @Override
    public String getDriverName() throws SQLException {
        return "Starschema.net:BigQuery JDBC driver";
    }

    /** {@inheritDoc} */
    @Override
    public String getDriverVersion() throws SQLException {
        return BQDriver.getMajorVersionAsStatic() + "." + BQDriver.getMinorVersionAsStatic();
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Not working.
     * </p>
     *
     * @return an empty resultset
     */
    @Override
    public ResultSet getExportedKeys(String catalog, String schema, String table) throws SQLException {
        logger.debug("Function call getExportedKeys(String,String,String)");
        String[] Col = new String[14];
        Col[0] = "PKTABLE_CAT";
        // String => parent key table catalog (may be null)
        Col[1] = "PKTABLE_SCHEM";
        // String => parent key table schema (may be null)
        Col[2] = "PKTABLE_NAME";
        // String => parent key table name
        Col[3] = "PKCOLUMN_NAME";
        // String => parent key column name
        Col[4] = "FKTABLE_CAT";
        // String => foreign key table catalog (may be null) being exported (may
        // be null)
        Col[5] = "FKTABLE_SCHEM";
        // String => foreign key table schema (may be null) being exported (may
        // be null)
        Col[6] = "FKTABLE_NAME";
        // String => foreign key table name being exported
        Col[7] = "FCOLUMN_NAME";
        // String => foreign key column name being exported
        Col[8] = "KEY_SEQ";
        // short => sequence number within foreign key( a value of 1 represents
        // the first column of the foreign key, a value of 2 would represent the
        // second column within the foreign key).
        Col[9] = "UPDATE_RULE";
        // short => What happens to foreign key when parent key is updated:
        Col[10] = "DELETE_RULE";
        // short => What happens to the foreign key when parent key is deleted.
        Col[11] = "FK_NAME";
        // String => foreign key name (may be null)
        Col[12] = "PK_NAME";
        // String => parent key name (may be null)
        Col[13] = "DEFERRABILITY";
        // short => can the evaluation of foreign key constraints be deferred
        // until commit
        return new DMDResultSet(new Object[0][14], Col, DMDResultSetType.getExportedKeys);
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns "( ) : . , \\ \" / ' ' * < = > + - % & | ^ << >> ~ != <> >= <= "
     * </p>
     */
    @Override
    public String getExtraNameCharacters() throws SQLException {
        return "( ) : . , \\ \" / ' ' * < = > + - % & | ^ << >> ~ != <> >= <= ";
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Not implemented yet.
     * </p>
     *
     * @throws BQSQLException
     */
    @Override
    public ResultSet getFunctionColumns(String catalog, String schemaPattern, String functionNamePattern,
            String columnNamePattern) throws SQLException {
        logger.debug("Function call getFunctionColumns(String,String,String,String)");
        throw new BQSQLException("Not implemented." + "getFunctionColumns(String,String,String,String)");
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Not implemented yet.
     * </p>
     *
     * @throws BQSQLException
     */
    @Override
    public ResultSet getFunctions(String catalog, String schemaPattern, String functionNamePattern)
            throws SQLException {
        logger.debug("Function call getFunctions(String,String,String)");
        throw new BQSQLException("Not implemented." + "getFunctions(String,String,String)");
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns "\\\""
     * </p>
     */
    @Override
    public String getIdentifierQuoteString() throws SQLException {
        return "\\\"";
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Since we doesn't support keys, it returns an empty Result Set
     * </p>
     *
     * @return ResultSet
     */
    @Override
    public ResultSet getImportedKeys(String catalog, String schema, String table) throws SQLException {
        logger.debug("Function call getImportedKeys(String,String,String)");
        String[] Col = new String[14];
        Col[0] = "PKTABLE_CAT";
        // String => primary key table catalog being imported (may be null)
        Col[1] = "PKTABLE_SCHEM";
        // String => primary key table schema being imported (may be null)
        Col[2] = "PKTABLE_NAME";
        // String => primary key table name being imported
        Col[3] = "PKCOLUMN_NAME";
        // String => primary key column name being imported
        Col[4] = "FKTABLE_CAT";
        // String => foreign key table catalog (may be null)
        Col[5] = "FKTABLE_SCHEM ";
        // String => foreign key table schema (may be null)
        Col[6] = "FKTABLE_NAME";
        // String => foreign key table name
        Col[7] = "FKCOLUMN_NAME";
        // String => foreign key column name
        Col[8] = "KEY_SEQ";
        // short => sequence number within a foreign key( a value of 1
        // represents the first column
        // of the foreign key, a value of 2 would represent the second column
        // within the foreign key).
        Col[9] = "UPDATE_RULE";
        // short => What happens to a foreign key when the primary key is
        // updated:
        Col[10] = "DELETE_RULE";
        // short => What happens to the foreign key when primary is deleted.
        Col[11] = "FK_NAME";
        // String => foreign key name (may be null)
        Col[12] = "PK_NAME";
        // String => primary key name (may be null)
        Col[13] = "DEFERRABILITY";
        // short => can the evaluation of foreign key constraints be deferred
        // until commit
        return new DMDResultSet(new Object[0][14], Col, DMDResultSetType.getImportedKeys);
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Currently not supported.
     * </p>
     *
     * @return An empty Result Set
     */
    @Override
    public ResultSet getIndexInfo(String catalog, String schema, String table, boolean unique, boolean approximate)
            throws SQLException {
        logger.debug(
                "Function call getIndexInfo(String,String,String,boolean,boolean) returning an empty resultset");
        String[] Col = new String[13];
        Col[0] = "TABLE_CAT";
        // String => table catalog (may be null)
        Col[1] = "TABLE_SCHEM";
        // String => table schema (may be null)
        Col[2] = "TABLE_NAME";
        // String => table name
        Col[3] = "NON_UNIQUE";
        // boolean => Can index values be non-unique. false when TYPE is
        // tableIndexStatistic
        Col[4] = "INDEX_QUALIFIER";
        // String => index catalog (may be null); null when TYPE is
        // tableIndexStatistic
        Col[5] = "INDEX_NAME";
        // String => index name; null when TYPE is tableIndexStatistic
        Col[6] = "TYPE";
        // short => index type:
        Col[7] = "ORDINAL_POSITION";
        // short => column sequence number within index; zero when TYPE is
        // tableIndexStatistic
        Col[8] = "COLUMN_NAME";
        // String => column name; null when TYPE is tableIndexStatistic
        Col[9] = "ASC_OR_DESC";
        // String => column sort sequence, "A" => ascending, "D" => descending,
        // may be null if sort sequence is not supported; null when TYPE is
        // tableIndexStatistic
        Col[10] = "CARDINALITY";
        // int => When TYPE is tableIndexStatistic, then this is the number of
        // rows in the table; otherwise, it is the number of unique values in
        // the index.
        Col[11] = "PAGES";
        // int => When TYPE is tableIndexStatisic then this is the number of
        // pages used for the table, otherwise it is the number of pages used
        // for the current index.
        Col[12] = "FILTER_CONDITION";
        // String => Filter condition, if any. (may be null)
        return new DMDResultSet(new Object[0][13], Col, DMDResultSetType.getIndexInfo);
        // TODO implement it more
    }

    /** {@inheritDoc} */
    @Override
    public int getJDBCMajorVersion() throws SQLException {
        return BQDriver.getMajorVersionAsStatic();
    }

    /** {@inheritDoc} */
    @Override
    public int getJDBCMinorVersion() throws SQLException {
        return BQDriver.getMinorVersionAsStatic();
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns 0
     * </p>
     */
    @Override
    public int getMaxBinaryLiteralLength() throws SQLException {
        return 0;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns 0
     * </p>
     */
    @Override
    public int getMaxCatalogNameLength() throws SQLException {
        return 0;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns 0
     * </p>
     */
    @Override
    public int getMaxCharLiteralLength() throws SQLException {
        return 0;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns 0
     * </p>
     */
    @Override
    public int getMaxColumnNameLength() throws SQLException {
        return 0;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns 0
     * </p>
     */
    @Override
    public int getMaxColumnsInGroupBy() throws SQLException {
        return 0;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns 0
     * </p>
     */
    @Override
    public int getMaxColumnsInIndex() throws SQLException {
        return 0;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns 0
     * </p>
     */
    @Override
    public int getMaxColumnsInOrderBy() throws SQLException {
        return 0;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns 0
     * </p>
     */
    @Override
    public int getMaxColumnsInSelect() throws SQLException {
        return 0;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns 0
     * </p>
     */
    @Override
    public int getMaxColumnsInTable() throws SQLException {
        return 0;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Limit is not known.
     * </p>
     *
     * @return 0
     */
    @Override
    public int getMaxConnections() throws SQLException {
        return 0;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Limit is not known
     * </p>
     *
     * @return 0
     */
    @Override
    public int getMaxCursorNameLength() throws SQLException {
        return 0;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * No index in bigquery, so limit is not known
     * </p>
     *
     * @return 0
     */
    @Override
    public int getMaxIndexLength() throws SQLException {
        return 0;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Procedures not supported currently
     * </p>
     *
     * @return 0
     */
    @Override
    public int getMaxProcedureNameLength() throws SQLException {
        return 0;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns 64 * 1024
     * </p>
     */
    @Override
    public int getMaxRowSize() throws SQLException {
        return 64 * 1024;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Limit is not known
     * </p>
     *
     * @return 0
     */
    @Override
    public int getMaxSchemaNameLength() throws SQLException {
        return 0;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Limit is not known
     * </p>
     *
     * @return 0
     */
    @Override
    public int getMaxStatementLength() throws SQLException {
        return 0;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Limit is not known
     * </p>
     *
     * @return 0
     */
    @Override
    public int getMaxStatements() throws SQLException {
        return 0;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Limit is not known
     * </p>
     *
     * @return 0
     */
    @Override
    public int getMaxTableNameLength() throws SQLException {
        return 0;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Limit is not known;
     * </p>
     *
     * @return 0;
     */
    @Override
    public int getMaxTablesInSelect() throws SQLException {
        return 0;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Limit is not known
     * </p>
     *
     * @return 0
     */
    @Override
    public int getMaxUserNameLength() throws SQLException {
        return 0;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns: <br>
     * { fn ABS() }, <br>
     * { fn ACOS() }, <br>
     * { fn ACOSH() }, <br>
     * { fn ASIN() }, <br>
     * { fn ASINH() }, <br>
     * { fn ATAN() }, <br>
     * { fn ATANH() }, <br>
     * { fn ATAN2() }, <br>
     * { fn CEIL() }, <br>
     * { fn COS() }, <br>
     * { fn COSH() }, <br>
     * { fn COT() }, <br>
     * { fn DEGREES() }, <br>
     * { fn FLOOR() }, <br>
     * { fn LN() }, <br>
     * { fn LOG() }, <br>
     * { fn LOG2() }, <br>
     * { fn LOG10() }, <br>
     * { fn PI() }, <br>
     * { fn POW() }, <br>
     * { fn RADIANS() }, <br>
     * { fn ROUND() }, <br>
     * { fn SIN() }, <br>
     * { fn SINH() }, <br>
     * { fn SQRT() }, <br>
     * { fn TAN() }, <br>
     * { fn TANH() }
     * </p>
     */
    @Override
    public String getNumericFunctions() throws SQLException {
        return "{ fn  ABS() }," + "{ fn  ACOS() }," + "{ fn  ACOSH() }," + "{ fn  ASIN() }," + "{ fn  ASINH() },"
                + "{ fn  ATAN() }," + "{ fn  ATANH() }," + "{ fn  ATAN2() }," + "{ fn  CEIL() }," + "{ fn  COS() },"
                + "{ fn  COSH() }," + "{ fn  COT() }," + "{ fn  DEGREES() }," + "{ fn  FLOOR() }," + "{ fn  LN() },"
                + "{ fn  LOG() }," + "{ fn  LOG2() }," + "{ fn  LOG10() }," + "{ fn  PI() }," + "{ fn  POW() },"
                + "{ fn  RADIANS() }," + "{ fn  ROUND() }," + "{ fn  SIN() }," + "{ fn  SINH() },"
                + "{ fn  SQRT() }," + "{ fn  TAN() }," + "{ fn  TANH() }";
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * No primary keys in BigQuery, so we return an empty Result Set
     * </p>
     *
     * @return ResultSet
     */
    @Override
    public ResultSet getPrimaryKeys(String catalog, String schema, String table) throws SQLException {
        logger.debug("Function call getPrimaryKeys(String,String,String)");
        String[] Col = new String[6];
        Col[0] = "TABLE_CAT";
        // String => table catalog (may be null)
        Col[1] = "TABLE_SCHEM";
        // String => table schema (may be null)
        Col[2] = "TABLE_NAME";
        // String => table name
        Col[3] = "COLUMN_NAME";
        // String => column name
        Col[4] = "KEY_SEQ";
        // short => sequence number within primary key( a value of 1 represents
        // the first column of the primary key, a value of 2 would represent the
        // second column within the primary key).
        Col[5] = "PK_NAME";
        // String => primary key name (may be null)
        return new DMDResultSet(new Object[0][8], Col, DMDResultSetType.getPrimaryKeys);
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Procedures not supported, so we return with an empty ResultSet
     * </p>
     *
     * @return empty resultset
     */
    @Override
    public ResultSet getProcedureColumns(String catalog, String schemaPattern, String procedureNamePattern,
            String columnNamePattern) throws SQLException {
        logger.debug("Function call getProcedureColumns(String,String,String,String)");
        String[] Col = new String[20];
        Col[0] = "PROCEDURE_CAT";
        // String => procedure catalog (may be null)
        Col[1] = "PROCEDURE_SCHEM";
        // String => procedure schema (may be null)
        Col[2] = "PROCEDURE_NAME";
        // String => procedure name
        Col[3] = "COLUMN_NAME";
        // String => column/parameter name
        Col[4] = "COLUMN_TYPE";
        // Short => kind of column/parameter:
        Col[5] = "DATA_TYPE";
        // int => SQL type from java.sql.Types
        Col[6] = "TYPE_NAME";
        // String => SQL type name, for a UDT type the type name is fully
        // qualified
        Col[7] = "PRECISION";
        // int => precision
        Col[8] = "LENGTH";
        // int => length in bytes of data
        Col[9] = "SCALE";
        // short => scale - null is returned for data types where SCALE is not
        // applicable.
        Col[10] = "RADIX";
        // short => radix
        Col[11] = "NULLABLE";
        // short => can it contain NULL.
        Col[12] = "REMARKS";
        // String => comment describing parameter/column
        Col[13] = "COLUMN_DEF";
        // String => default value for the column, which should be interpreted
        // as a string when the value is enclosed in single quotes (may be null)
        Col[14] = "SQL_DATA_TYPE";
        // int => reserved for future use
        Col[15] = "SQL_DATETIME_SUB";
        // int => reserved for future use
        Col[16] = "CHAR_OCTET_LENGTH";
        // int => the maximum length of binary and character based columns.
        // For any other datatype the returned value is a NULL
        Col[17] = "ORDINAL_POSITION";
        // int => the ordinal position, starting from 1, for the input and
        // output
        // parameters for a procedure. A value of 0 is returned if this row
        // describes
        // the procedure's return value. For result set columns, it is the
        // ordinal
        // position of the column in the result set starting from 1. If there
        // are
        // multiple result sets, the column ordinal positions are implementation
        // defined.
        Col[18] = "IS_NULLABLE";
        // String => ISO rules are used to determine the nullability for a
        // column.
        Col[19] = "SPECIFIC_NAME";
        // String => the name which uniquely identifies this procedure within
        // its schema.
        return new DMDResultSet(new Object[0][20], Col, DMDResultSetType.getProcedureColumns);
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Not yet impelmented
     * https://developers.google.com/bigquery/docs/reference/v2/
     * https://developers.google.com/bigquery/docs/query-reference
     * </p>
     *
     * @return an empty Result Set
     */
    @Override
    public ResultSet getProcedures(String catalog, String schemaPattern, String procedureNamePattern)
            throws SQLException {
        logger.debug("Function call getProcedures(String,String,String)");
        String[] Col = new String[9];
        Col[0] = "PROCEDURE_CAT";
        // String => procedure catalog (may be null)
        Col[1] = "PROCEDURE_SCHEM";
        // String => procedure schema (may be null)
        Col[2] = "PROCEDURE_NAME";
        // String => procedure name
        Col[3] = ""; // reserved for future use
        Col[4] = ""; // reserved for future use
        Col[5] = ""; // reserved for future use
        Col[6] = "REMARKS";
        // String => explanatory comment on the procedure
        Col[7] = "PROCEDURE_TYPE";
        // short => kind of procedure:
        Col[8] = "SPECIFIC_NAME";
        // String => The name which uniquely identifies this procedure within
        // its schema.
        return new DMDResultSet(new Object[0][9], Col, DMDResultSetType.getProcedures);
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Procedures are not supported
     * </p>
     *
     * @return ""
     */
    @Override
    public String getProcedureTerm() throws SQLException {
        return "";
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns ResultSet.CLOSE_CURSORS_AT_COMMIT
     * </p>
     */
    @Override
    public int getResultSetHoldability() throws SQLException {
        return ResultSet.CLOSE_CURSORS_AT_COMMIT;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns RowIdLifetime.ROWID_UNSUPPORTED
     * </p>
     */
    @Override
    public RowIdLifetime getRowIdLifetime() throws SQLException {
        return RowIdLifetime.ROWID_UNSUPPORTED;
    }

    /** {@inheritDoc} */
    @Override
    public ResultSet getSchemas() throws SQLException {
        logger.debug("Function call getSchemas()");

        String[][] data = null;

        List<Projects> Projects;
        try {
            Projects = this.Connection.getBigquery().projects().list().execute().getProjects();
        } catch (IOException e) {
            throw new BQSQLException(e);
        }

        if (Projects != null && Projects.size() != 0) {
            for (Projects proj : Projects) {
                DatasetList datasetcontainer = null;
                try {
                    datasetcontainer = this.Connection.getBigquery().datasets().list(proj.getId()).execute();
                } catch (IOException e) {
                    throw new BQSQLException(e);
                }
                List<Datasets> datasetlist = datasetcontainer.getDatasets();
                if (datasetlist != null && datasetlist.size() != 0) {
                    data = new String[datasetlist.size()][2];
                    int i = 0;
                    for (Datasets datasets : datasetlist) {
                        data[i][0] = datasets.getDatasetReference().getDatasetId();
                        data[i][1] = datasets.getDatasetReference().getProjectId().replace(".", "_").replace(":",
                                "__");
                        i++;
                    }
                }
            }
        }
        if (data != null) {
            logger.debug("data was not null, data length = " + data.length);
            for (int i = 0; i < data.length; i++) {
                logger.debug("data" + i + "[0],[1] = " + data[i][0].toString() + "," + data[i][1].toString());
            }
            return new DMDResultSet(data, new String[] { "TABLE_SCHEM", "TABLE_CATALOG" },
                    DMDResultSetType.getSchemas);
        } else {
            logger.debug("data was null");
            return new DMDResultSet(new String[][] { { null, null } },
                    new String[] { "TABLE_SCHEM", "TABLE_CATALOG" }, DMDResultSetType.getSchemas);
        }
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Similar to getSchemas, but we can filter the results with the catalog and
     * schema
     *
     * </p>
     *
     * @param catalog
     *            - the catalog, AKA the project ID
     * @param schemaPattern
     *            - the schema name, AKA the dataset name
     * @return the schemas
     */
    @Override
    public ResultSet getSchemas(String catalog, String schemaPattern) throws SQLException {
        logger.debug("Function call getSchemas(String,String)");
        String[][] data = null;
        List<Projects> Projects;
        String[] Col = new String[2];
        Col[0] = "TABLE_SCHEM";
        // String => schema name
        Col[1] = "TABLE_CATALOG";
        // String => catalog name (may be null)
        /*
         * Parameters: catalog - a catalog name; must match the catalog name as
         * it is stored in the database;"" retrieves those without a catalog;
         * null means catalog name should not be used to narrow down the search.
         * schemaPattern - a schema name; must match the schema name as it is
         * stored in the database; null means schema name should not be used to
         * narrow down the search. Returns: a ResultSet object in which each row
         * is a schema description
         */

        try {
            Projects = this.Connection.getBigquery().projects().list().execute().getProjects();
        } catch (IOException e) {
            throw new BQSQLException(e);
        }
        int i;
        if (Projects != null && Projects.size() != 0) {
            for (Projects proj : Projects) {
                DatasetList datasetcontainer = null;
                try {
                    datasetcontainer = this.Connection.getBigquery().datasets().list(proj.getId()).execute();
                } catch (IOException e) {
                    throw new BQSQLException(e);
                }
                List<Datasets> datasetlist = datasetcontainer.getDatasets();
                if (datasetlist != null && datasetlist.size() != 0) {
                    data = new String[datasetlist.size()][2];
                    i = 0;
                    for (Datasets datasets : datasetlist) {
                        String schema = datasets.getDatasetReference().getDatasetId();
                        String projnm = datasets.getDatasetReference().getProjectId();
                        logger.debug("We search for catalog/project: " + catalog);
                        if ((schema.equals(schemaPattern) || schemaPattern == null)
                                && (projnm.equals(catalog) || catalog == null)) {
                            data[i][0] = schema;
                            data[i][1] = projnm;
                            i++;
                        }
                    }
                }
            }
        }

        if (data != null) {
            return new DMDResultSet(data, new String[] { "TABLE_SCHEM", "TABLE_CATALOG" },
                    DMDResultSetType.getSchemas);
        } else {
            return new DMDResultSet(new String[][] { { null, null } },
                    new String[] { "TABLE_SCHEM", "TABLE_CATALOG" }, DMDResultSetType.getSchemas);
        }
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns "schema"
     * </p>
     */
    @Override
    public String getSchemaTerm() throws SQLException {
        return "schema";
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns ""
     * </p>
     */
    @Override
    public String getSearchStringEscape() throws SQLException {
        return "";
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns: <br>
     * PI,<br>
     * POW,<br>
     * RADIANS,<br>
     * ROUND,<br>
     * SIN,<br>
     * SINH,<br>
     * SQRT,<br>
     * TAN,<br>
     * TANH,<br>
     * BOOLEAN,<br>
     * HEX_STRING,<br>
     * STRING,<br>
     * IFNULL,<br>
     * IS_INF,<br>
     * IS_NAN,<br>
     * IS_EXPLICITLY_DEFINED,<br>
     * FORMAT_IP,<br>
     * PARSE_IP,<br>
     * FORMAT_PACKED_IP,<br>
     * PARSE_PACKED_IP,<br>
     * REGEXP_MATCH,<br>
     * REGEXP_EXTRACT,<br>
     * REGEXP_REPLACE,<br>
     * CONCAT,<br>
     * LENGTH,<br>
     * LOWER,<br>
     * LPAD,<br>
     * RIGHT,<br>
     * RPAD,<br>
     * SUBSTR,<br>
     * UPPER,<br>
     * FORMAT_UTC_USEC,<br>
     * NOW,<br>
     * PARSE_UTC_USEC,<br>
     * STRFTIME_UTC_USEC,<br>
     * UTC_USEC_TO_DAY,<br>
     * UTC_USEC_TO_HOUR,<br>
     * UTC_USEC_TO_MONTH,<br>
     * UTC_USEC_TO_WEEK,<br>
     * UTC_USEC_TO_YEAR,<br>
     * POSITION
     * </p>
     */
    @Override
    public String getSQLKeywords() throws SQLException {
        return "PI,POW,RADIANS,ROUND,SIN,SINH,SQRT,TAN,TANH,BOOLEAN,"
                + "HEX_STRING,STRING,IFNULL,IS_INF,IS_NAN,IS_EXPLICITLY_DEFINED,"
                + "FORMAT_IP,PARSE_IP,FORMAT_PACKED_IP,PARSE_PACKED_IP,"
                + "REGEXP_MATCH,REGEXP_EXTRACT,REGEXP_REPLACE,CONCAT,"
                + "LENGTH,LOWER,LPAD,RIGHT,RPAD,SUBSTR,UPPER,"
                + "FORMAT_UTC_USEC,NOW,PARSE_UTC_USEC,STRFTIME_UTC_USEC,"
                + "UTC_USEC_TO_DAY,UTC_USEC_TO_HOUR,UTC_USEC_TO_MONTH,"
                + "UTC_USEC_TO_WEEK,UTC_USEC_TO_YEAR,POSITION";
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns DatabaseMetaData.sqlStateSQL
     * </p>
     */
    @Override
    public int getSQLStateType() throws SQLException {
        return DatabaseMetaData.sqlStateSQL;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns: <br>
     * { fn CONCAT() },<br>
     * { fn LEFT() },<br>
     * { fn LENGTH() },<br>
     * { fn LOWER() },<br>
     * { fn LPAD() },<br>
     * { fn RIGHT() },<br>
     * { fn RPAD() },<br>
     * { fn SUBSTR() },<br>
     * { fn UPPER( },<br>
     * </p>
     */
    @Override
    public String getStringFunctions() throws SQLException {
        return "{ fn CONCAT() }," + "{ fn LEFT() }," + "{ fn LENGTH() }," + "{ fn LOWER() }," + "{ fn LPAD() },"
                + "{ fn RIGHT() }," + "{ fn RPAD() }," + "{ fn SUBSTR() }," + "{ fn UPPER( },";
        // expr CONTAINS 'str'
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Not implemented yet.
     * </p>
     *
     * @return an empty ResultSet
     */
    @Override
    public ResultSet getSuperTables(String catalog, String schemaPattern, String tableNamePattern)
            throws SQLException {
        logger.debug("Function call getSuperTables(String,String,String)");
        String[] Col = new String[4];
        Col[0] = "TABLE_CAT";
        // String => the type's catalog (may be null)
        Col[1] = "TABLE_SCHEM";
        // String => type's schema (may be null)
        Col[2] = "TABLE_NAME";
        // String => type name
        Col[3] = "SUPERTABLE_NAME";
        // String => the direct super type's
        return new DMDResultSet(new Object[0][4], Col, DMDResultSetType.getSuperTables);
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Super Types are not supported
     * </p>
     *
     * @return empty ResultSet
     */
    @Override
    public ResultSet getSuperTypes(String catalog, String schemaPattern, String typeNamePattern)
            throws SQLException {
        logger.debug("Function call getSuperTypes(String,String,String)");
        String[] Col = new String[6];
        Col[0] = "TYPE_CAT";
        // String => the UDT's catalog (may be null)
        Col[1] = "TYPE_SCHEM";
        // String => UDT's schema (may be null)
        Col[2] = "TYPE_NAME";
        // String => type name of the UDT
        Col[3] = "SUPERTYPE_CAT";
        // String => the direct super type's catalog (may be null)
        Col[4] = "SUPERTYPE_SCHEM";
        // String => the direct super type's schema (may be null)
        Col[5] = "SUPERTYPE_NAME";
        // String => the direct super type's name
        return new DMDResultSet(new Object[0][6], Col, DMDResultSetType.getSuperTypes);
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns ""
     * </p>
     */
    @Override
    public String getSystemFunctions() throws SQLException {
        return "";
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns an empty resultset
     * </p>
     *
     */
    @Override
    public ResultSet getTablePrivileges(String catalog, String schemaPattern, String tableNamePattern)
            throws SQLException {
        logger.debug("Function call getTablePrivileges(String,String,String)");
        String[] Col = new String[8];
        Col[0] = "TABLE_CAT"; // String => table catalog (may be null)
        Col[1] = "TABLE_SCHEM"; // String => table schema (may be null)
        Col[2] = "TABLE_NAME"; // String => table name
        Col[3] = "COLUMN_NAME"; // String => column name
        Col[4] = "GRANTOR"; // String => grantor of access (may be null)
        Col[5] = "GRANTEE"; // String => grantee of access
        Col[6] = "PRIVILEGE"; // String => name of access (SELECT, INSERT,
        // UPDATE, REFRENCES, ...)
        Col[7] = "IS_GRANTABLE";// String => "YES" if grantee is permitted to
        // grant to others;
        // "NO" if not; null if unknown
        return new DMDResultSet(new Object[0][8], Col, DMDResultSetType.getTablePrivileges);
        // TODO we might need this more implemented.
    }

    /** {@inheritDoc} */
    @Override
    public ResultSet getTables(String catalog, String schemaPattern, String tableNamePattern, String[] types)
            throws SQLException {
        if (catalog != null && (catalog == " " || catalog.length() == 0)) {
            logger.debug(
                    "Catalog length was: " + catalog.length() + " it's an empty string replacing it with 'null' ");
            catalog = null;
        }
        if (schemaPattern != null) {
            if (schemaPattern == " " || schemaPattern.length() == 0) {
                logger.debug("schemaPattern length was: " + schemaPattern.length()
                        + " it's an empty string replacing it with 'null' ");
                schemaPattern = null;
            }
        }
        String typesToLog = "";
        if (types != null) {
            for (String string : types) {
                typesToLog += string + " , ";
            }
        }
        logger.debug("Function call getTables(catalog: " + ((catalog != null) ? catalog : "null")
                + ", schemaPattern: " + ((schemaPattern != null) ? schemaPattern : "null") + ", tableNamePattern: "
                + ((tableNamePattern != null) ? tableNamePattern : "null") + ", types: " + typesToLog + ")");
        List<Table> tables = null;
        try {
            tables = BQSupportFuncts.getTables(this.Connection, catalog, schemaPattern, tableNamePattern);
            if (tables == null) { //because of crystal reports, It's not elegant but hey, it works!
                tables = BQSupportFuncts.getTables(this.Connection, tableNamePattern, schemaPattern, catalog);
            }
        } catch (IOException e) {
            throw new BQSQLException(e);
        }
        if (tables != null && tables.size() != 0) {
            logger.debug("got result, size: " + tables.size());
            String[][] data = new String[tables.size()][10];
            for (int i = 0; i < tables.size(); i++) {
                String UparsedId = tables.get(i).getId();
                data[i][0] = BQSupportFuncts.getProjectIdFromAnyGetId(UparsedId).replace(":", "__").replace(".",
                        "_");
                data[i][1] = BQSupportFuncts.getDatasetIdFromTableDotGetId(UparsedId);
                data[i][2] = BQSupportFuncts.getTableIdFromTableDotGetId(UparsedId);
                data[i][3] = "TABLE";
                data[i][4] = tables.get(i).getDescription();
                data[i][5] = null;
                data[i][6] = BQSupportFuncts.getProjectIdFromAnyGetId(UparsedId).replace(":", "__").replace(".",
                        "_");
                data[i][7] = BQSupportFuncts.getDatasetIdFromTableDotGetId(UparsedId);
                data[i][8] = BQSupportFuncts.getTableIdFromTableDotGetId(UparsedId);
                data[i][9] = null;
            }
            return new DMDResultSet(data,
                    new String[] { "TABLE_CAT", "TABLE_SCHEM", "TABLE_NAME", "TABLE_TYPE", "REMARKS", "TYPE_CAT",
                            "TYPE_SCHEM", "TYPE_NAME", "SELF_REFERENCING_COL_NAME", "REF_GENERATION" },
                    DMDResultSetType.getTables);
        } else {
            logger.debug("no result or empty result, returning with nulls");
            return new DMDResultSet(
                    new String[][] { { null, null, null, null, null, null, null, null, null, null } },
                    new String[] { "TABLE_CAT", "TABLE_SCHEM", "TABLE_NAME", "TABLE_TYPE", "REMARKS", "TYPE_CAT",
                            "TYPE_SCHEM", "TYPE_NAME", "SELF_REFERENCING_COL_NAME", "REF_GENERATION" },
                    DMDResultSetType.getTables);
        }
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns {@code List<String>}contaning only "TABLE"
     * </p>
     */
    @Override
    public ResultSet getTableTypes() throws SQLException {
        logger.debug("Function call getTableTypes()");
        List<String> Res = new ArrayList<String>();
        Res.add("TABLE");
        return new DMDResultSet(Res.toArray(), new String[] { "TABLE_TYPE" }, DMDResultSetType.getTableTypes);
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns: <br>
     * { fn FORMAT_UTC_USEC() }, <br>
     * { fn NOW() }, <br>
     * { fn PARSE_UTC_USEC() }, <br>
     * { fn STRFTIME_UTC_USEC() }, <br>
     * { fn UTC_USEC_TO_DAY() }, <br>
     * { fn UTC_USEC_TO_HOUR() }, <br>
     * { fn UTC_USEC_TO_MONTH() }, <br>
     * { fn UTC_USEC_TO_WEEK() }, <br>
     * { fn UTC_USEC_TO_YEAR() }
     * </p>
     */
    @Override
    public String getTimeDateFunctions() throws SQLException {
        return "{ fn FORMAT_UTC_USEC() }," + "{ fn NOW() }," + "{ fn PARSE_UTC_USEC() },"
                + "{ fn STRFTIME_UTC_USEC() }," + "{ fn UTC_USEC_TO_DAY() }," + "{ fn UTC_USEC_TO_HOUR() },"
                + "{ fn UTC_USEC_TO_MONTH() }," + "{ fn UTC_USEC_TO_WEEK() }," + "{ fn UTC_USEC_TO_YEAR() }";
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Not yet implemented, returning an empty Result Set
     * </p>
     *
     * @return an empty ResultSet
     */
    @Override
    public ResultSet getTypeInfo() throws SQLException {
        logger.debug("Function call getTypeInfo()");
        logger.debug("Not implemented, returning empty result");
        String[] Col = new String[18];
        Col[0] = "TYPE_NAME"; // String => Type name
        Col[1] = "DATA_TYPE"; // int => SQL data type from java.sql.Types
        Col[2] = "PRECISION"; // int => maximum precision
        Col[3] = "LITERAL_PREFIX"; // String => prefix used to quote a literal
        // (may be null)
        Col[4] = "LITERAL_SUFFIX"; // String => suffix used to quote a literal
        // (may be null)
        Col[5] = "CREATE_PARAMS"; // String => parameters used in creating the
        // type (may be null)
        Col[6] = "NULLABLE"; // short => can you use NULL for this type.
        Col[7] = "CASE_SENSITIVE"; // boolean=> is it case sensitive.
        Col[8] = "SEARCHABLE"; // short => can you use "WHERE" based on this
        // type:
        Col[9] = "UNSIGNED_ATTRIBUTE"; // boolean => is it unsigned.
        Col[10] = "FIXED_PREC_SCALE"; // boolean => can it be a money value.
        Col[11] = "AUTO_INCREMENT"; // boolean => can it be used for an
        // auto-increment value.
        Col[12] = "LOCAL_TYPE_NAME"; // String => localized version of type name
        // (may be null)
        Col[13] = "MINIMUM_SCALE"; // short => minimum scale supported
        Col[14] = "MAXIMUM_SCALE"; // short => maximum scale supported
        Col[15] = "SQL_DATA_TYPE"; // int => unused
        Col[16] = "SQL_DATETIME_SUB";// int => unused
        Col[17] = "NUM_PREC_RADIX"; // int => usually 2 or 10
        return new DMDResultSet(new Object[0][18], Col, DMDResultSetType.getTypeInfo);
        // TODO we might need this more implemented
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Not supported, so we're returning an empty ResultSet
     * </p>
     *
     * @return an empty ResultSet
     */
    @Override
    public ResultSet getUDTs(String catalog, String schemaPattern, String typeNamePattern, int[] types)
            throws SQLException {
        logger.debug("Function call getUDTs(String,String,String,int[])");
        logger.debug("not implemented, returning an empty resultset");
        String[] Col = new String[7];
        Col[0] = "TYPE_CAT";
        // String => the type's catalog (may be null)
        Col[1] = "TYPE_SCHEM";
        // String => type's schema (may be null)
        Col[2] = "TYPE_NAME";
        // String => type name
        Col[3] = "CLASS_NAME";
        // String => Java class name
        Col[4] = "DATA_TYPE";
        // int => type value defined in java.sql.Types. One of JAVA_OBJECT,
        // STRUCT, or DISTINCT
        Col[5] = "REMARKS";
        // String => explanatory comment on the type
        Col[6] = "BASE_TYPE";
        // short => type code of the source type of a DISTINCT type or ...
        return new DMDResultSet(new Object[0][7], Col, DMDResultSetType.getUDTs);
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns an URL to the Bigquery Homepage.
     * </p>
     */
    @Override
    public String getURL() throws SQLException {
        return "https://developers.google.com/bigquery/";
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns ProjectId
     * </p>
     */
    @Override
    public String getUserName() throws SQLException {
        logger.debug("Function call getUserName()  returning the projectID: " + this.Connection.getProjectId());
        return this.Connection.getProjectId();
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * returns an empty resultset
     * </p>
     *
     */
    @Override
    public ResultSet getVersionColumns(String catalog, String schema, String table) throws SQLException {
        logger.debug("Function call getVersionColumns(String,String,String)");
        logger.debug("not implemented, returning an empty resultset");
        String[] Col = new String[8];
        Col[0] = "SCOPE";
        // short => is not used
        Col[1] = "COLUMN_NAME";
        // String => column name
        Col[2] = "DATA_TYPE";
        // int => SQL data type from java.sql.Types
        Col[3] = "TYPE_NAME";
        // String => Data source-dependent type name
        Col[4] = "COLUMN_SIZE";
        // int => precision
        Col[5] = "BUFFER_LENGTH";
        // int => length of column value in bytes
        Col[6] = "DECIMAL_DIGITS";
        // short => scale - Null is returned for data types where DECIMAL_DIGITS
        // is not applicable.
        Col[7] = "PSEUDO_COLUMN";
        // short => whether this is pseudo column like an Oracle ROWID
        return new DMDResultSet(new Object[0][8], Col, DMDResultSetType.getVersionColumns);
        // TODO we might need it
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns false
     * </p>
     */
    @Override
    public boolean insertsAreDetected(int type) throws SQLException {
        return false;
    }

    /**
     * <p>
     * Retrieves whether a catalog appears at the start of a fully qualified table name. If not, the catalog appears at the end.
     * <h1>Implementation Details:</h1><br>
     *
     * </p>
     *
     * @return false
     */
    @Override
    public boolean isCatalogAtStart() throws SQLException {
        logger.debug("Function call isCatalogAtStart(), return is true ");
        return true;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns true
     * </p>
     */
    @Override
    public boolean isReadOnly() throws SQLException {
        return true;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Not implemented
     * </p>
     *
     * @return false
     */
    @Override
    public boolean isWrapperFor(Class<?> iface) throws SQLException {
        return false;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns true
     * </p>
     */
    @Override
    public boolean locatorsUpdateCopy() throws SQLException {
        return true;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns true
     * </p>
     */
    @Override
    public boolean nullPlusNonNullIsNull() throws SQLException {
        return true; // TODO test it!
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns false
     * </p>
     */
    @Override
    public boolean nullsAreSortedAtEnd() throws SQLException {
        return false;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns false
     * </p>
     */
    @Override
    public boolean nullsAreSortedAtStart() throws SQLException {
        return false;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns false
     * </p>
     */
    @Override
    public boolean nullsAreSortedHigh() throws SQLException {
        return false;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns false
     * </p>
     */
    @Override
    public boolean nullsAreSortedLow() throws SQLException {
        return false;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns false
     * </p>
     */
    @Override
    public boolean othersDeletesAreVisible(int type) throws SQLException {
        return false;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns false
     * </p>
     */
    @Override
    public boolean othersInsertsAreVisible(int type) throws SQLException {
        return false;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns false
     * </p>
     */
    @Override
    public boolean othersUpdatesAreVisible(int type) throws SQLException {
        return false;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns false
     * </p>
     */
    @Override
    public boolean ownDeletesAreVisible(int type) throws SQLException {
        return false;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns false
     * </p>
     */
    @Override
    public boolean ownInsertsAreVisible(int type) throws SQLException {
        return false;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns false
     * </p>
     */
    @Override
    public boolean ownUpdatesAreVisible(int type) throws SQLException {
        return false;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns false
     * </p>
     */
    @Override
    public boolean storesLowerCaseIdentifiers() throws SQLException {
        return true;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns true
     * </p>
     */
    @Override
    public boolean storesLowerCaseQuotedIdentifiers() throws SQLException {
        return true;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns false
     * </p>
     */
    @Override
    public boolean storesMixedCaseIdentifiers() throws SQLException {
        return false;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns false
     * </p>
     */
    @Override
    public boolean storesMixedCaseQuotedIdentifiers() throws SQLException {
        return false;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns false
     * </p>
     */
    @Override
    public boolean storesUpperCaseIdentifiers() throws SQLException {
        return false;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns false
     * </p>
     */
    @Override
    public boolean storesUpperCaseQuotedIdentifiers() throws SQLException {
        return false;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns false
     * </p>
     */
    @Override
    public boolean supportsAlterTableWithAddColumn() throws SQLException {
        return false;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns false
     * </p>
     */
    @Override
    public boolean supportsAlterTableWithDropColumn() throws SQLException {
        return false;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * It doesn't support the ANSI92
     * </p>
     *
     * @return false
     */
    @Override
    public boolean supportsANSI92EntryLevelSQL() throws SQLException {
        return false;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * It does not support the ANSI92
     * </p>
     *
     * @return false
     */
    @Override
    public boolean supportsANSI92FullSQL() throws SQLException {
        return false;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * It doesn't supports ANSI92
     * </p>
     *
     * @return false
     */
    @Override
    public boolean supportsANSI92IntermediateSQL() throws SQLException {
        return false;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns false
     * </p>
     */
    @Override
    public boolean supportsBatchUpdates() throws SQLException {
        return false;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns false
     * </p>
     */
    @Override
    public boolean supportsCatalogsInDataManipulation() throws SQLException {
        return false;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns false
     * </p>
     */
    @Override
    public boolean supportsCatalogsInIndexDefinitions() throws SQLException {
        return false;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns false
     * </p>
     */
    @Override
    public boolean supportsCatalogsInPrivilegeDefinitions() throws SQLException {
        return false;

    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns false
     * </p>
     */
    @Override
    public boolean supportsCatalogsInProcedureCalls() throws SQLException {
        return false;

    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns false
     * </p>
     */
    @Override
    public boolean supportsCatalogsInTableDefinitions() throws SQLException {
        return false;

    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns true
     * </p>
     */
    @Override
    public boolean supportsColumnAliasing() throws SQLException {
        return true;

    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns false
     * </p>
     */
    @Override
    public boolean supportsConvert() throws SQLException {
        return false;

    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns false
     * </p>
     */
    @Override
    public boolean supportsConvert(int fromType, int toType) throws SQLException {
        return false;

    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns true
     * </p>
     */
    @Override
    public boolean supportsCoreSQLGrammar() throws SQLException {
        return true;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns false
     * </p>
     */
    @Override
    public boolean supportsCorrelatedSubqueries() throws SQLException {
        // http://publib.boulder.ibm.com/infocenter/iseries/v5r3/index.jsp?topic=%2Fsqlp%2Frbafyexsub1.htm
        return false;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns false
     * </p>
     */
    @Override
    public boolean supportsDataDefinitionAndDataManipulationTransactions() throws SQLException {
        return false;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns false
     * </p>
     */
    @Override
    public boolean supportsDataManipulationTransactionsOnly() throws SQLException {
        return false;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns true
     * </p>
     */
    @Override
    public boolean supportsDifferentTableCorrelationNames() throws SQLException {
        return true;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns true
     * </p>
     */
    @Override
    public boolean supportsExpressionsInOrderBy() throws SQLException {
        return true;

    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns false
     * </p>
     */
    @Override
    public boolean supportsExtendedSQLGrammar() throws SQLException {
        return false;

    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns false
     * </p>
     */
    @Override
    public boolean supportsFullOuterJoins() throws SQLException {
        return false;

    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns false
     * </p>
     */
    @Override
    public boolean supportsGetGeneratedKeys() throws SQLException {
        return false;

    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns true
     * </p>
     */
    @Override
    public boolean supportsGroupBy() throws SQLException {
        return true;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns false
     * </p>
     */
    @Override
    public boolean supportsGroupByBeyondSelect() throws SQLException {
        return false;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns false
     * </p>
     */
    @Override
    public boolean supportsGroupByUnrelated() throws SQLException {
        return false;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns false
     * </p>
     */
    @Override
    public boolean supportsIntegrityEnhancementFacility() throws SQLException {
        return false;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns false
     * </p>
     */
    @Override
    public boolean supportsLikeEscapeClause() throws SQLException {
        return false;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns true
     * </p>
     */
    @Override
    public boolean supportsLimitedOuterJoins() throws SQLException {
        return true;

    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns false
     * </p>
     */
    @Override
    public boolean supportsMinimumSQLGrammar() throws SQLException {
        return false;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns false
     * </p>
     */
    @Override
    public boolean supportsMixedCaseIdentifiers() throws SQLException {
        return false;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns false
     * </p>
     */
    @Override
    public boolean supportsMixedCaseQuotedIdentifiers() throws SQLException {
        return false;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns false
     * </p>
     */
    @Override
    public boolean supportsMultipleOpenResults() throws SQLException {
        return multipleOpenResultsSupported; // In the current version.
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns false
     * </p>
     */
    @Override
    public boolean supportsMultipleResultSets() throws SQLException {
        return false;

    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns true
     * </p>
     */
    @Override
    public boolean supportsMultipleTransactions() throws SQLException {
        return true;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns false
     * </p>
     */
    @Override
    public boolean supportsNamedParameters() throws SQLException {
        return false; // Bigquery doesn't support stored jobs.
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns false
     * </p>
     */
    @Override
    public boolean supportsNonNullableColumns() throws SQLException {
        return false;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns false
     * </p>
     */
    @Override
    public boolean supportsOpenCursorsAcrossCommit() throws SQLException {
        return false;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns false
     * </p>
     */
    @Override
    public boolean supportsOpenCursorsAcrossRollback() throws SQLException {
        return false;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns false
     * </p>
     */
    @Override
    public boolean supportsOpenStatementsAcrossCommit() throws SQLException {
        return false;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns false
     * </p>
     */
    @Override
    public boolean supportsOpenStatementsAcrossRollback() throws SQLException {
        return false;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns false
     * </p>
     */
    @Override
    public boolean supportsOrderByUnrelated() throws SQLException {
        return false; // Tested
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns true
     * </p>
     */
    @Override
    public boolean supportsOuterJoins() throws SQLException {
        return true;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns false
     * </p>
     */
    @Override
    public boolean supportsPositionedDelete() throws SQLException {
        return false;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns false
     * </p>
     */
    @Override
    public boolean supportsPositionedUpdate() throws SQLException {
        return false;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns false
     * </p>
     */
    @Override
    public boolean supportsResultSetConcurrency(int type, int concurrency) throws SQLException {
        if (ResultSet.TYPE_FORWARD_ONLY == type) {
            if (ResultSet.CONCUR_READ_ONLY == concurrency) {
                return true;
            }
            if (ResultSet.CONCUR_UPDATABLE == concurrency) {
                return false;
            }
        }

        if (ResultSet.TYPE_SCROLL_INSENSITIVE == type) {
            if (ResultSet.CONCUR_READ_ONLY == concurrency) {
                return true;
            }
            if (ResultSet.CONCUR_UPDATABLE == concurrency) {
                return false;
            }
        }

        if (ResultSet.TYPE_SCROLL_SENSITIVE == type) {
            if (ResultSet.CONCUR_READ_ONLY == concurrency) {
                return true;
            }
            if (ResultSet.CONCUR_UPDATABLE == concurrency) {
                return false;
            }
        }
        return false;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns false
     * </p>
     */
    @Override
    public boolean supportsResultSetHoldability(int holdability) throws SQLException {
        return false; // Only read only functions atm.

    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Our resultset is scroll insensitive
     * </p>
     *
     * @return TYPE_SCROLL_INSENSITIVE
     */
    @Override
    public boolean supportsResultSetType(int type) throws SQLException {
        if (type == java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE)
            return true;
        if (type == ResultSet.TYPE_FORWARD_ONLY)
            return true;
        return false;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns false
     * </p>
     */
    @Override
    public boolean supportsSavepoints() throws SQLException {
        return false;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns false
     * </p>
     */
    @Override
    public boolean supportsSchemasInDataManipulation() throws SQLException {
        return false;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns false
     * </p>
     */
    @Override
    public boolean supportsSchemasInIndexDefinitions() throws SQLException {
        return false;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns false
     * </p>
     */
    @Override
    public boolean supportsSchemasInPrivilegeDefinitions() throws SQLException {
        return false;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns false
     * </p>
     */
    @Override
    public boolean supportsSchemasInProcedureCalls() throws SQLException {
        return false;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns false
     * </p>
     */
    @Override
    public boolean supportsSchemasInTableDefinitions() throws SQLException {
        return false;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns false
     * </p>
     */
    @Override
    public boolean supportsSelectForUpdate() throws SQLException {
        return false;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns false
     * </p>
     */
    @Override
    public boolean supportsStatementPooling() throws SQLException {
        return false;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns false
     * </p>
     */
    @Override
    public boolean supportsStoredFunctionsUsingCallSyntax() throws SQLException {
        return false;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns false
     * </p>
     */
    @Override
    public boolean supportsStoredProcedures() throws SQLException {
        return false;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns true
     * </p>
     */
    @Override
    public boolean supportsSubqueriesInComparisons() throws SQLException {
        return true;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns false
     * </p>
     */
    @Override
    public boolean supportsSubqueriesInExists() throws SQLException {
        return false;

    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * expr IN(expr1, expr2, ...) Returns true if expr matches expr1, expr2,<br>
     * or any value in the parentheses. The IN keyword is an efficient<br>
     * shorthand for (expr = expr1 || expr = expr2 || ...). The expressions<br>
     * used with the IN keyword must be constants and they must match the<br>
     * data type of expr.<br>
     * <br>
     * Returns false
     * </p>
     */
    @Override
    public boolean supportsSubqueriesInIns() throws SQLException {
        return false;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns false
     * </p>
     */
    @Override
    public boolean supportsSubqueriesInQuantifieds() throws SQLException {
        return false;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns false
     * </p>
     */
    @Override
    public boolean supportsTableCorrelationNames() throws SQLException {
        return false;
    }

    /** {@inheritDoc} */
    @Override
    public boolean supportsTransactionIsolationLevel(int level) throws SQLException {
        if (java.sql.Connection.TRANSACTION_NONE == level) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns false
     * </p>
     */
    @Override
    public boolean supportsTransactions() throws SQLException {
        return false;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns true
     * </p>
     */
    @Override
    public boolean supportsUnion() throws SQLException {
        return true;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns false
     * </p>
     */
    @Override
    public boolean supportsUnionAll() throws SQLException {
        return false;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * No wrappers in the current version
     * </p>
     *
     * @throws SQLException
     */
    @Override
    public <T> T unwrap(Class<T> iface) throws SQLException {
        throw new BQSQLException("no object found that implements " + iface.toString());
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns false
     * </p>
     */
    @Override
    public boolean updatesAreDetected(int type) throws SQLException {
        return false;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns false
     * </p>
     */
    @Override
    public boolean usesLocalFilePerTable() throws SQLException {
        return false;
    }

    /**
     * <p>
     * <h1>Implementation Details:</h1><br>
     * Returns false
     * </p>
     */
    @Override
    public boolean usesLocalFiles() throws SQLException {
        return false;
    }
}