/* This file is part of VoltDB. * Copyright (C) 2008-2017 VoltDB Inc. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) 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 Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with VoltDB. If not, see <http://www.gnu.org/licenses/>. */ package org.voltdb.jdbc; import java.sql.CallableStatement; import java.sql.Connection; import java.sql.ResultSet; import java.sql.RowIdLifetime; import java.sql.SQLException; import java.util.Arrays; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.voltdb.VoltTable; import org.voltdb.VoltTable.ColumnInfo; import org.voltdb.VoltType; public class JDBC4DatabaseMetaData implements java.sql.DatabaseMetaData { /* * Two types of tables the metadata generator generates. It has to match the * table types generated in JdbcDatabaseMetaDataGenerator. */ static final String tableTypes[] = new String[] {"TABLE", "VIEW"}; private final CallableStatement sysInfo; private final CallableStatement sysCatalog; private final JDBC4Connection sourceConnection; JDBC4DatabaseMetaData(JDBC4Connection connection) throws SQLException { this.sourceConnection = connection; this.sysInfo = connection.prepareCall("{call @SystemInformation}"); this.sysCatalog = connection.prepareCall("{call @SystemCatalog(?)}"); // Initialize system information loadSystemInformation(); } private String buildString = null; private String versionString = null; private String catalogString = null; private void loadSystemInformation() throws SQLException { ResultSet res = this.sysInfo.executeQuery(); while (res.next()) { if (res.getString(2).equals("BUILDSTRING")) buildString = res.getString(3); else if (res.getString(2).equals("VERSION")) versionString = res.getString(3); else if (res.getString(2).equals("CATALOG")) catalogString = res.getString(3); } res.close(); } private void checkClosed() throws SQLException { if (this.sourceConnection.isClosed()) throw SQLError.get(SQLError.CONNECTION_CLOSED); } // Retrieves whether the current user can call all the procedures returned by the method getProcedures. @Override public boolean allProceduresAreCallable() throws SQLException { checkClosed(); return true; } // Retrieves whether the current user can use all the tables returned by the method getTables in a SELECT statement. @Override public boolean allTablesAreSelectable() throws SQLException { checkClosed(); return true; } // Retrieves whether a SQLException while autoCommit is true indicates that all open ResultSets are closed, even ones that are holdable. @Override public boolean autoCommitFailureClosesAllResultSets() throws SQLException { checkClosed(); return true; } // Retrieves whether a data definition statement within a transaction forces the transaction to commit. @Override public boolean dataDefinitionCausesTransactionCommit() throws SQLException { checkClosed(); return true; } // Retrieves whether this database ignores a data definition statement within a transaction. @Override public boolean dataDefinitionIgnoredInTransactions() throws SQLException { checkClosed(); return true; } // Retrieves whether or not a visible row delete can be detected by calling the method ResultSet.rowDeleted. @Override public boolean deletesAreDetected(int type) throws SQLException { checkClosed(); return false; } // Retrieves whether the return value for the method getMaxRowSize includes the SQL data types LONGVARCHAR and LONGVARBINARY. @Override public boolean doesMaxRowSizeIncludeBlobs() throws SQLException { checkClosed(); return true; } // Retrieves a description of the given attribute of the given type for a user-defined type (UDT) that is available in the given schema and catalog. @Override public ResultSet getAttributes(String catalog, String schemaPattern, String typeNamePattern, String attributeNamePattern) throws SQLException { checkClosed(); throw SQLError.noSupport(); } // Retrieves a description of a table's optimal set of columns that uniquely identifies a row. @Override public ResultSet getBestRowIdentifier(String catalog, String schema, String table, int scope, boolean nullable) throws SQLException { checkClosed(); throw SQLError.noSupport(); } // Retrieves the catalog names available in this database. @Override public ResultSet getCatalogs() throws SQLException { checkClosed(); VoltTable result = new VoltTable(new VoltTable.ColumnInfo("TABLE_CAT",VoltType.STRING)); result.addRow(new Object[] { catalogString }); return new JDBC4ResultSet(null, result); } // Retrieves the String that this database uses as the separator between a catalog and table name. @Override public String getCatalogSeparator() throws SQLException { return "."; } // Retrieves the database vendor's preferred term for "catalog". @Override public String getCatalogTerm() throws SQLException { checkClosed(); return "catalog"; } // Retrieves a list of the client info properties that the driver supports. @Override public ResultSet getClientInfoProperties() throws SQLException { checkClosed(); throw SQLError.noSupport(); } // Retrieves a description of the access rights for a table's columns. @Override public ResultSet getColumnPrivileges(String catalog, String schema, String table, String columnNamePattern) throws SQLException { checkClosed(); throw SQLError.noSupport(); } // Retrieves a description of table columns available in the specified catalog. @Override public ResultSet getColumns(String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern) throws SQLException { checkClosed(); this.sysCatalog.setString(1, "COLUMNS"); JDBC4ResultSet res = (JDBC4ResultSet) this.sysCatalog.executeQuery(); VoltTable vtable = res.getVoltTable().clone(0); // If no pattern is specified, default to matching any/all. if (tableNamePattern == null || tableNamePattern.length() == 0) { tableNamePattern = "%"; } Pattern table_pattern = computeJavaPattern(tableNamePattern); if (columnNamePattern == null || columnNamePattern.length() == 0) { columnNamePattern = "%"; } Pattern column_pattern = computeJavaPattern(columnNamePattern); // Filter columns based on table name and column name while (res.next()) { Matcher table_matcher = table_pattern.matcher(res.getString("TABLE_NAME")); if (table_matcher.matches()) { Matcher column_matcher = column_pattern.matcher(res.getString("COLUMN_NAME")); if (column_matcher.matches()) { vtable.addRow(res.getRowData()); } } } return new JDBC4ResultSet(this.sysCatalog, vtable); } // Retrieves the connection that produced this metadata object. @Override public Connection getConnection() throws SQLException { checkClosed(); return sourceConnection; } // Retrieves a description of the foreign key columns in the given foreign key table that reference the primary key or the columns representing a unique constraint of the parent table (could be the same or a different table). @Override public ResultSet getCrossReference(String parentCatalog, String parentSchema, String parentTable, String foreignCatalog, String foreignSchema, String foreignTable) throws SQLException { checkClosed(); throw SQLError.noSupport(); } // Retrieves the major version number of the underlying database. @Override public int getDatabaseMajorVersion() throws SQLException { checkClosed(); System.out.println("\n\n\nVERSION: " + versionString); return Integer.valueOf(versionString.split("\\.")[0]); } // Retrieves the minor version number of the underlying database. @Override public int getDatabaseMinorVersion() throws SQLException { checkClosed(); return Integer.valueOf(versionString.split("\\.")[1]); } // Retrieves the name of this database product. @Override public String getDatabaseProductName() throws SQLException { checkClosed(); return "VoltDB"; } // Retrieves the version number of this database product. @Override public String getDatabaseProductVersion() throws SQLException { checkClosed(); return buildString; } // Retrieves this database's default transaction isolation level. @Override public int getDefaultTransactionIsolation() throws SQLException { checkClosed(); return Connection.TRANSACTION_SERIALIZABLE; } // Retrieves this JDBC driver's major version number. @Override public int getDriverMajorVersion() { return 1; } // Retrieves this JDBC driver's minor version number. @Override public int getDriverMinorVersion() { return 1; } // Retrieves the name of this JDBC driver. @Override public String getDriverName() throws SQLException { checkClosed(); return "voltdb"; } // Retrieves the version number of this JDBC driver as a String. @Override public String getDriverVersion() throws SQLException { checkClosed(); return new String(getDriverMajorVersion() + "." + getDriverMinorVersion()); } /** * Retrieves a description of the foreign key columns that reference the * given table's primary key columns (the foreign keys exported by a table). */ @Override public ResultSet getExportedKeys(String catalog, String schema, String table) throws SQLException { checkClosed(); VoltTable vtable = new VoltTable( new ColumnInfo("PKTABLE_CAT", VoltType.STRING), new ColumnInfo("PKTABLE_SCHEM", VoltType.STRING), new ColumnInfo("PKTABLE_NAME", VoltType.STRING), new ColumnInfo("PKCOLUMN_NAME", VoltType.STRING), new ColumnInfo("FKTABLE_CAT", VoltType.STRING), new ColumnInfo("FKTABLE_SCHEM", VoltType.STRING), new ColumnInfo("FKTABLE_NAME", VoltType.STRING), new ColumnInfo("FKCOLUMN_NAME", VoltType.STRING), new ColumnInfo("KEY_SEQ", VoltType.SMALLINT), new ColumnInfo("UPDATE_RULE", VoltType.SMALLINT), new ColumnInfo("DELETE_RULE", VoltType.SMALLINT), new ColumnInfo("FK_NAME", VoltType.STRING), new ColumnInfo("PK_NAME", VoltType.STRING), new ColumnInfo("DEFERRABILITY", VoltType.SMALLINT) ); //NB: @SystemCatalog(?) will need additional support if we want to // populate the table. JDBC4ResultSet res = new JDBC4ResultSet(this.sysCatalog, vtable); return res; } /** * Retrieves all the "extra" characters that can be used in unquoted identifier * names (those beyond a-z, A-Z, 0-9 and _). */ @Override public String getExtraNameCharacters() throws SQLException { checkClosed(); return ""; } // Retrieves a description of the given catalog's system or user function parameters and return type. @Override public ResultSet getFunctionColumns(String catalog, String schemaPattern, String functionNamePattern, String columnNamePattern) throws SQLException { checkClosed(); throw SQLError.noSupport(); } // Retrieves a description of the system and user functions available in the given catalog. @Override public ResultSet getFunctions(String catalog, String schemaPattern, String functionNamePattern) throws SQLException { checkClosed(); throw SQLError.noSupport(); } // Retrieves the string used to quote SQL identifiers. @Override public String getIdentifierQuoteString() throws SQLException { checkClosed(); return "\""; } // Retrieves a description of the primary key columns that are referenced by the given table's foreign key columns (the primary keys imported by a table) throws SQLException. @Override public ResultSet getImportedKeys(String catalog, String schema, String table) throws SQLException { checkClosed(); VoltTable vtable = new VoltTable( new ColumnInfo("PKTABLE_CAT", VoltType.STRING), new ColumnInfo("PKTABLE_SCHEM", VoltType.STRING), new ColumnInfo("PKTABLE_NAME", VoltType.STRING), new ColumnInfo("PKCOLUMN_NAME", VoltType.STRING), new ColumnInfo("FKTABLE_CAT", VoltType.STRING), new ColumnInfo("FKTABLE_SCHEM", VoltType.STRING), new ColumnInfo("FKTABLE_NAME", VoltType.STRING), new ColumnInfo("FKCOLUMN_NAME", VoltType.STRING), new ColumnInfo("KEY_SEQ", VoltType.SMALLINT), new ColumnInfo("UPDATE_RULE", VoltType.SMALLINT), new ColumnInfo("DELETE_RULE", VoltType.SMALLINT), new ColumnInfo("FK_NAME", VoltType.STRING), new ColumnInfo("PK_NAME", VoltType.STRING), new ColumnInfo("DEFERRABILITY", VoltType.SMALLINT) ); //NB: @SystemCatalog(?) will need additional support if we want to // populate the table. JDBC4ResultSet res = new JDBC4ResultSet(this.sysCatalog, vtable); return res; } // Retrieves a description of the given table's indices and statistics. // NOTE: currently returns the NON_UNIQUE column as a TINYINT due // to lack of boolean support in VoltTable schemas. @Override public ResultSet getIndexInfo(String catalog, String schema, String table, boolean unique, boolean approximate) throws SQLException { assert(table != null && !table.isEmpty()); checkClosed(); this.sysCatalog.setString(1, "INDEXINFO"); JDBC4ResultSet res = (JDBC4ResultSet) this.sysCatalog.executeQuery(); VoltTable vtable = res.getVoltTable().clone(0); // Filter the indexes by table name while (res.next()) { if (res.getString("TABLE_NAME").equals(table)) { if (!unique || res.getShort("NON_UNIQUE") == 0) { vtable.addRow(res.getRowData()); } } } return new JDBC4ResultSet(sysCatalog, vtable); } // Retrieves the major JDBC version number for this driver. @Override public int getJDBCMajorVersion() throws SQLException { checkClosed(); return 4; } // Retrieves the minor JDBC version number for this driver. @Override public int getJDBCMinorVersion() throws SQLException { checkClosed(); return 0; } // Retrieves the maximum number of hex characters this database allows in an inline binary literal. @Override public int getMaxBinaryLiteralLength() throws SQLException { checkClosed(); return VoltType.MAX_VALUE_LENGTH; } // Retrieves the maximum number of characters that this database allows in a catalog name. @Override public int getMaxCatalogNameLength() throws SQLException { checkClosed(); throw SQLError.noSupport(); } // Retrieves the maximum number of characters this database allows for a character literal. @Override public int getMaxCharLiteralLength() throws SQLException { checkClosed(); return VoltType.MAX_VALUE_LENGTH; } // Retrieves the maximum number of characters this database allows for a column name. @Override public int getMaxColumnNameLength() throws SQLException { checkClosed(); throw SQLError.noSupport(); } // Retrieves the maximum number of columns this database allows in a GROUP BY clause. @Override public int getMaxColumnsInGroupBy() throws SQLException { checkClosed(); throw SQLError.noSupport(); } // Retrieves the maximum number of columns this database allows in an index. @Override public int getMaxColumnsInIndex() throws SQLException { checkClosed(); throw SQLError.noSupport(); } // Retrieves the maximum number of columns this database allows in an ORDER BY clause. @Override public int getMaxColumnsInOrderBy() throws SQLException { checkClosed(); throw SQLError.noSupport(); } // Retrieves the maximum number of columns this database allows in a SELECT list. @Override public int getMaxColumnsInSelect() throws SQLException { checkClosed(); throw SQLError.noSupport(); } // Retrieves the maximum number of columns this database allows in a table. @Override public int getMaxColumnsInTable() throws SQLException { checkClosed(); throw SQLError.noSupport(); } // Retrieves the maximum number of concurrent connections to this database that are possible. @Override public int getMaxConnections() throws SQLException { checkClosed(); throw SQLError.noSupport(); } // Retrieves the maximum number of characters that this database allows in a cursor name. @Override public int getMaxCursorNameLength() throws SQLException { checkClosed(); throw SQLError.noSupport(); } // Retrieves the maximum number of bytes this database allows for an index, including all of the parts of the index. @Override public int getMaxIndexLength() throws SQLException { checkClosed(); throw SQLError.noSupport(); } // Retrieves the maximum number of characters that this database allows in a procedure name. @Override public int getMaxProcedureNameLength() throws SQLException { checkClosed(); throw SQLError.noSupport(); } // Retrieves the maximum number of bytes this database allows in a single row. @Override public int getMaxRowSize() throws SQLException { checkClosed(); return 2 * 1024 * 1024; // 2 MB } // Retrieves the maximum number of characters that this database allows in a schema name. @Override public int getMaxSchemaNameLength() throws SQLException { checkClosed(); throw SQLError.noSupport(); } // Retrieves the maximum number of characters this database allows in an SQL statement. @Override public int getMaxStatementLength() throws SQLException { checkClosed(); throw SQLError.noSupport(); } // Retrieves the maximum number of active statements to this database that can be open at the same time. @Override public int getMaxStatements() throws SQLException { checkClosed(); throw SQLError.noSupport(); } // Retrieves the maximum number of characters this database allows in a table name. @Override public int getMaxTableNameLength() throws SQLException { checkClosed(); throw SQLError.noSupport(); } // Retrieves the maximum number of tables this database allows in a SELECT statement. @Override public int getMaxTablesInSelect() throws SQLException { checkClosed(); throw SQLError.noSupport(); } // Retrieves the maximum number of characters this database allows in a user name. @Override public int getMaxUserNameLength() throws SQLException { checkClosed(); throw SQLError.noSupport(); } // Retrieves a comma-separated list of math functions available with this database. @Override public String getNumericFunctions() throws SQLException { checkClosed(); return "ABS,BITAND,BITNOT,BITOR,BIT_SHIFT_LEFT,BIT_SHIFT_RIGHT,BITXOR,CEILING,COS,COT,CSC,EXP,FLOOR,LN,LOG,LOG10,PI,POWER,ROUND,SEC,SIN,SQRT,TAN"; } // Retrieves a description of the given table's primary key columns. @Override public ResultSet getPrimaryKeys(String catalog, String schema, String table) throws SQLException { assert(table != null && !table.isEmpty()); checkClosed(); this.sysCatalog.setString(1, "PRIMARYKEYS"); JDBC4ResultSet res = (JDBC4ResultSet) this.sysCatalog.executeQuery(); VoltTable vtable = res.getVoltTable().clone(0); // Filter the primary keys based on table name while (res.next()) { if (res.getString("TABLE_NAME").equals(table)) { vtable.addRow(res.getRowData()); } } return new JDBC4ResultSet(sysCatalog, vtable); } // Retrieves a description of the given catalog's stored procedure parameter and result columns. // TODO: implement pattern filtering somewhere (preferably server-side) @Override public ResultSet getProcedureColumns(String catalog, String schemaPattern, String procedureNamePattern, String columnNamePattern) throws SQLException { assert(procedureNamePattern != null && !procedureNamePattern.isEmpty()); checkClosed(); this.sysCatalog.setString(1, "PROCEDURECOLUMNS"); JDBC4ResultSet res = (JDBC4ResultSet) this.sysCatalog.executeQuery(); VoltTable vtable = res.getVoltTable().clone(0); // Filter the results based on procedure name and column name while (res.next()) { if (res.getString("PROCEDURE_NAME").equals(procedureNamePattern)) { if (columnNamePattern == null || columnNamePattern.equals("%") || res.getString("COLUMN_NAME").equals(columnNamePattern)) { vtable.addRow(res.getRowData()); } } } return new JDBC4ResultSet(sysCatalog, vtable); } // Retrieves a description of the stored procedures available in the given catalog. // TODO: implement pattern filtering somewhere (preferably server-side) @Override public ResultSet getProcedures(String catalog, String schemaPattern, String procedureNamePattern) throws SQLException { if (procedureNamePattern != null && !procedureNamePattern.equals("%")) throw new SQLException(String.format("getProcedures('%s','%s','%s') does not support pattern filtering", catalog, schemaPattern, procedureNamePattern)); checkClosed(); this.sysCatalog.setString(1, "PROCEDURES"); ResultSet res = this.sysCatalog.executeQuery(); return res; } // Retrieves the database vendor's preferred term for "procedure". @Override public String getProcedureTerm() throws SQLException { checkClosed(); throw SQLError.noSupport(); } // Retrieves this database's default holdability for ResultSet objects. @Override public int getResultSetHoldability() throws SQLException { checkClosed(); throw SQLError.noSupport(); } // Indicates whether or not this data source supports the SQL ROWID type, and if so the lifetime for which a RowId object remains valid. @Override public RowIdLifetime getRowIdLifetime() throws SQLException { checkClosed(); throw SQLError.noSupport(); } // Retrieves the schema names available in this database. @Override public ResultSet getSchemas() throws SQLException { checkClosed(); VoltTable vtable = new VoltTable( new ColumnInfo("TABLE_SCHEM", VoltType.STRING), new ColumnInfo("TABLE_CATALOG", VoltType.STRING)); JDBC4ResultSet res = new JDBC4ResultSet(this.sysCatalog, vtable); return res; } // Retrieves the schema names available in this database. @Override public ResultSet getSchemas(String catalog, String schemaPattern) throws SQLException { return getSchemas(); // empty } // Retrieves the database vendor's preferred term for "schema". @Override public String getSchemaTerm() throws SQLException { checkClosed(); throw SQLError.noSupport(); } // Retrieves the string that can be used to escape wildcard characters. @Override public String getSearchStringEscape() throws SQLException { checkClosed(); throw SQLError.noSupport(); } // Retrieves a comma-separated list of all of this database's SQL keywords that are NOT also SQL:2003 keywords. @Override public String getSQLKeywords() throws SQLException { checkClosed(); return ""; } // Indicates whether the SQLSTATE returned by SQLException.getSQLState is X/Open (now known as Open Group) SQL CLI or SQL:2003. @Override public int getSQLStateType() throws SQLException { checkClosed(); return sqlStateXOpen; } // Retrieves a comma-separated list of string functions available with this database. @Override public String getStringFunctions() throws SQLException { checkClosed(); // TODO: find a more suitable place for COALESCE return "BIN,COALESCE,CHAR,CHAR_LENGTH,CONCAT,FORMAT_CURRENCY,HEX,STR,INSERT,LCASE,LEFT,LOWER,LTRIM," + "OCTET_LENGTH,OVERLAY,POSITION,REGEXP_POSITION,REPEAT,REPLACE,RIGHT,RTRIM,SPACE,SUBSTRING,SUBSTR,"+ "TRIM,UCASE,UPPER"; } // Retrieves a description of the table hierarchies defined in a particular schema in this database. @Override public ResultSet getSuperTables(String catalog, String schemaPattern, String tableNamePattern) throws SQLException { checkClosed(); throw SQLError.noSupport(); } // Retrieves a description of the user-defined type (UDT) hierarchies defined in a particular schema in this database. @Override public ResultSet getSuperTypes(String catalog, String schemaPattern, String typeNamePattern) throws SQLException { checkClosed(); throw SQLError.noSupport(); } // Retrieves a comma-separated list of system functions available with this database. @Override public String getSystemFunctions() throws SQLException { checkClosed(); throw SQLError.noSupport(); } // Retrieves a description of the access rights for each table available in a catalog. @Override public ResultSet getTablePrivileges(String catalog, String schemaPattern, String tableNamePattern) throws SQLException { checkClosed(); VoltTable vtable = new VoltTable( new ColumnInfo("TABLE_CAT", VoltType.STRING), new ColumnInfo("TABLE_SCHEM", VoltType.STRING), new ColumnInfo("TABLE_NAME", VoltType.STRING), new ColumnInfo("GRANTOR", VoltType.STRING), new ColumnInfo("GRANTEE", VoltType.STRING), new ColumnInfo("PRIVILEGE", VoltType.STRING), new ColumnInfo("IS_GRANTABLE", VoltType.STRING) ); //NB: @SystemCatalog(?) will need additional support if we want to // populate the table. JDBC4ResultSet res = new JDBC4ResultSet(this.sysCatalog, vtable); return res; } // Convert the users VoltDB SQL pattern into a regex pattern public static Pattern computeJavaPattern(String sqlPattern) { StringBuffer pattern_buff = new StringBuffer(); // Replace "_" with "." (match exactly 1 character) // Replace "%" with ".*" (match 0 or more characters) for (int i=0; i<sqlPattern.length(); i++) { char c = sqlPattern.charAt(i); if (c == '_') { pattern_buff.append('.'); } else if (c == '%') { pattern_buff.append(".*"); } else pattern_buff.append(c); } return Pattern.compile(pattern_buff.toString()); } // Retrieves a description of the tables available in the given catalog. @Override public ResultSet getTables(String catalog, String schemaPattern, String tableNamePattern, String[] types) throws SQLException { checkClosed(); this.sysCatalog.setString(1, "TABLES"); JDBC4ResultSet res = (JDBC4ResultSet) this.sysCatalog.executeQuery(); VoltTable vtable = res.getVoltTable().clone(0); List<String> typeStrings = null; if (types != null) { typeStrings = Arrays.asList(types); } // If no pattern is specified, default to matching any/all. if (tableNamePattern == null || tableNamePattern.length() == 0) { tableNamePattern = "%"; } Pattern table_pattern = computeJavaPattern(tableNamePattern); // Filter tables based on type and pattern while (res.next()) { if (typeStrings == null || typeStrings.contains(res.getString("TABLE_TYPE"))) { Matcher table_matcher = table_pattern.matcher(res.getString("TABLE_NAME")); if (table_matcher.matches()) { vtable.addRow(res.getRowData()); } } } return new JDBC4ResultSet(this.sysCatalog, vtable); } // Retrieves the table types available in this database. @Override public ResultSet getTableTypes() throws SQLException { checkClosed(); VoltTable vtable = new VoltTable(new ColumnInfo("TABLE_TYPE", VoltType.STRING)); for (String type : tableTypes) { vtable.addRow(type); } JDBC4ResultSet res = new JDBC4ResultSet(this.sysCatalog, vtable); return res; } // Retrieves a comma-separated list of the time and date functions available with this database. @Override public String getTimeDateFunctions() throws SQLException { checkClosed(); return "CURRENT_TIMESTAMP,DATEADD,DAY,DAYOFMONTH,DAYOFWEEK,DAYOFYEAR,EXTRACT,FROM_UNIXTIME,HOUR," + "IS_VALID_TIMESTAMP,MAX_VALID_TIMESTAMP,MIN_VALID_TIMESTAMP," + "MINUTE,MONTH,NOW,QUARTER,SECOND,SINCE_EPOCH,TO_TIMESTAMP,TRUNCATE,WEEK,WEEKOFYEAR,"+ "WEEKDAY,YEAR"; } // Retrieves a description of all the data types supported by this database. @Override public ResultSet getTypeInfo() throws SQLException { checkClosed(); this.sysCatalog.setString(1, "TYPEINFO"); ResultSet res = this.sysCatalog.executeQuery(); return res; } // Retrieves a description of the user-defined types (UDTs) defined in a particular schema. @Override public ResultSet getUDTs(String catalog, String schemaPattern, String typeNamePattern, int[] types) throws SQLException { checkClosed(); throw SQLError.noSupport(); } // Retrieves the URL for this DBMS. @Override public String getURL() throws SQLException { checkClosed(); return "http://voltdb.com/"; } // Retrieves the user name as known to this database. @Override public String getUserName() throws SQLException { checkClosed(); return this.sourceConnection.User; } // Retrieves a description of a table's columns that are automatically updated when any value in a row is updated. @Override public ResultSet getVersionColumns(String catalog, String schema, String table) throws SQLException { checkClosed(); throw SQLError.noSupport(); } // Retrieves whether or not a visible row insert can be detected by calling the method ResultSet.rowInserted. @Override public boolean insertsAreDetected(int type) throws SQLException { checkClosed(); return false; } // Retrieves whether a catalog appears at the start of a fully qualified table name. @Override public boolean isCatalogAtStart() throws SQLException { checkClosed(); return false; } // Retrieves whether this database is in read-only mode. @Override public boolean isReadOnly() throws SQLException { checkClosed(); return false; } // Indicates whether updates made to a LOB are made on a copy or directly to the LOB. @Override public boolean locatorsUpdateCopy() throws SQLException { checkClosed(); return false; } // Retrieves whether this database supports concatenations between NULL and non-NULL values being NULL. @Override public boolean nullPlusNonNullIsNull() throws SQLException { checkClosed(); return true; } // Retrieves whether NULL values are sorted at the end regardless of sort order. @Override public boolean nullsAreSortedAtEnd() throws SQLException { checkClosed(); return false; } // Retrieves whether NULL values are sorted at the start regardless of sort order. @Override public boolean nullsAreSortedAtStart() throws SQLException { checkClosed(); return false; } // Retrieves whether NULL values are sorted high. @Override public boolean nullsAreSortedHigh() throws SQLException { checkClosed(); return false; } // Retrieves whether NULL values are sorted low. @Override public boolean nullsAreSortedLow() throws SQLException { checkClosed(); return true; } // Retrieves whether deletes made by others are visible. @Override public boolean othersDeletesAreVisible(int type) throws SQLException { checkClosed(); return false; } // Retrieves whether inserts made by others are visible. @Override public boolean othersInsertsAreVisible(int type) throws SQLException { checkClosed(); return false; } // Retrieves whether updates made by others are visible. @Override public boolean othersUpdatesAreVisible(int type) throws SQLException { checkClosed(); return false; } // Retrieves whether a result set's own deletes are visible. @Override public boolean ownDeletesAreVisible(int type) throws SQLException { checkClosed(); return false; } // Retrieves whether a result set's own inserts are visible. @Override public boolean ownInsertsAreVisible(int type) throws SQLException { checkClosed(); return false; } // Retrieves whether for the given type of ResultSet object, the result set's own updates are visible. @Override public boolean ownUpdatesAreVisible(int type) throws SQLException { checkClosed(); return false; } // Retrieves whether this database treats mixed case unquoted SQL identifiers as case insensitive and stores them in lower case. @Override public boolean storesLowerCaseIdentifiers() throws SQLException { checkClosed(); return false; // Note: Proc names are sensitive, but not tables/columns! } // Retrieves whether this database treats mixed case quoted SQL identifiers as case insensitive and stores them in lower case. @Override public boolean storesLowerCaseQuotedIdentifiers() throws SQLException { checkClosed(); return false; // Note: Proc names are sensitive, but not tables/columns! } // Retrieves whether this database treats mixed case unquoted SQL identifiers as case insensitive and stores them in mixed case. @Override public boolean storesMixedCaseIdentifiers() throws SQLException { checkClosed(); return false; // Note: Proc names are sensitive, but not tables/columns! } // Retrieves whether this database treats mixed case quoted SQL identifiers as case insensitive and stores them in mixed case. @Override public boolean storesMixedCaseQuotedIdentifiers() throws SQLException { checkClosed(); return false; // Note: Proc names are sensitive, but not tables/columns! } // Retrieves whether this database treats mixed case unquoted SQL identifiers as case insensitive and stores them in upper case. @Override public boolean storesUpperCaseIdentifiers() throws SQLException { checkClosed(); return true; // Note: Proc names are sensitive, but not tables/columns! } // Retrieves whether this database treats mixed case quoted SQL identifiers as case insensitive and stores them in upper case. @Override public boolean storesUpperCaseQuotedIdentifiers() throws SQLException { checkClosed(); return true; // Note: Proc names are sensitive, but not tables/columns! } // Retrieves whether this database supports ALTER TABLE with add column. @Override public boolean supportsAlterTableWithAddColumn() throws SQLException { checkClosed(); return false; } // Retrieves whether this database supports ALTER TABLE with drop column. @Override public boolean supportsAlterTableWithDropColumn() throws SQLException { checkClosed(); return false; } // Retrieves whether this database supports the ANSI92 entry level SQL grammar. @Override public boolean supportsANSI92EntryLevelSQL() throws SQLException { checkClosed(); return false; } // Retrieves whether this database supports the ANSI92 full SQL grammar supported. @Override public boolean supportsANSI92FullSQL() throws SQLException { checkClosed(); return false; } // Retrieves whether this database supports the ANSI92 intermediate SQL grammar supported. @Override public boolean supportsANSI92IntermediateSQL() throws SQLException { checkClosed(); return false; } // Retrieves whether this database supports batch updates. @Override public boolean supportsBatchUpdates() throws SQLException { checkClosed(); return true; } // Retrieves whether a catalog name can be used in a data manipulation statement. @Override public boolean supportsCatalogsInDataManipulation() throws SQLException { checkClosed(); return false; } // Retrieves whether a catalog name can be used in an index definition statement. @Override public boolean supportsCatalogsInIndexDefinitions() throws SQLException { checkClosed(); return false; } // Retrieves whether a catalog name can be used in a privilege definition statement. @Override public boolean supportsCatalogsInPrivilegeDefinitions() throws SQLException { checkClosed(); return false; } // Retrieves whether a catalog name can be used in a procedure call statement. @Override public boolean supportsCatalogsInProcedureCalls() throws SQLException { checkClosed(); return false; } // Retrieves whether a catalog name can be used in a table definition statement. @Override public boolean supportsCatalogsInTableDefinitions() throws SQLException { checkClosed(); return false; } // Retrieves whether this database supports column aliasing. @Override public boolean supportsColumnAliasing() throws SQLException { checkClosed(); return true; } // Retrieves whether this database supports the JDBC scalar function CONVERT for the conversion of one JDBC type to another. @Override public boolean supportsConvert() throws SQLException { checkClosed(); return false; } // Retrieves whether this database supports the JDBC scalar function CONVERT for conversions between the JDBC types fromType and toType. @Override public boolean supportsConvert(int fromType, int toType) throws SQLException { checkClosed(); switch (fromType) { /* * ALL types can be converted to VARCHAR /VoltType.String */ case java.sql.Types.VARCHAR: case java.sql.Types.VARBINARY: case java.sql.Types.TIMESTAMP: case java.sql.Types.OTHER: switch (toType) { case java.sql.Types.VARCHAR: return true; default: return false; } case java.sql.Types.TINYINT: case java.sql.Types.SMALLINT: case java.sql.Types.INTEGER: case java.sql.Types.BIGINT: case java.sql.Types.FLOAT: case java.sql.Types.DECIMAL: switch (toType) { case java.sql.Types.VARCHAR: case java.sql.Types.TINYINT: case java.sql.Types.SMALLINT: case java.sql.Types.INTEGER: case java.sql.Types.BIGINT: case java.sql.Types.FLOAT: case java.sql.Types.DECIMAL: return true; default: return false; } default: return false; } } // Retrieves whether this database supports the ODBC Core SQL grammar. @Override public boolean supportsCoreSQLGrammar() throws SQLException { checkClosed(); return false; } // Retrieves whether this database supports correlated subqueries. @Override public boolean supportsCorrelatedSubqueries() throws SQLException { checkClosed(); return false; } // Retrieves whether this database supports both data definition and data manipulation statements within a transaction. @Override public boolean supportsDataDefinitionAndDataManipulationTransactions() throws SQLException { checkClosed(); return false; } // Retrieves whether this database supports only data manipulation statements within a transaction. @Override public boolean supportsDataManipulationTransactionsOnly() throws SQLException { checkClosed(); return false; } // Retrieves whether, when table correlation names are supported, they are restricted to being different from the names of the tables. @Override public boolean supportsDifferentTableCorrelationNames() throws SQLException { checkClosed(); return false; // Alias may be same as the table name } // Retrieves whether this database supports expressions in ORDER BY lists. @Override public boolean supportsExpressionsInOrderBy() throws SQLException { checkClosed(); return false; } // Retrieves whether this database supports the ODBC Extended SQL grammar. @Override public boolean supportsExtendedSQLGrammar() throws SQLException { checkClosed(); return false; // Only assuming based on currently limited set } // Retrieves whether this database supports full nested outer joins. @Override public boolean supportsFullOuterJoins() throws SQLException { checkClosed(); return false; } // Retrieves whether auto-generated keys can be retrieved after a statement has been executed @Override public boolean supportsGetGeneratedKeys() throws SQLException { checkClosed(); return false; } // Retrieves whether this database supports some form of GROUP BY clause. @Override public boolean supportsGroupBy() throws SQLException { checkClosed(); return true; } // Retrieves whether this database supports using columns not included in the SELECT statement in a GROUP BY clause provided that all of the columns in the SELECT statement are included in the GROUP BY clause. @Override public boolean supportsGroupByBeyondSelect() throws SQLException { checkClosed(); return false; } // Retrieves whether this database supports using a column that is not in the SELECT statement in a GROUP BY clause. @Override public boolean supportsGroupByUnrelated() throws SQLException { checkClosed(); return false; } // Retrieves whether this database supports the SQL Integrity Enhancement Facility. @Override public boolean supportsIntegrityEnhancementFacility() throws SQLException { checkClosed(); return false; // Does support DEFAULT, but not CHECK and UNIQUE constraints get violated over partition boundaries! } // Retrieves whether this database supports specifying a LIKE escape clause. @Override public boolean supportsLikeEscapeClause() throws SQLException { checkClosed(); return false; } // Retrieves whether this database provides limited support for outer joins. @Override public boolean supportsLimitedOuterJoins() throws SQLException { checkClosed(); return true; } // Retrieves whether this database supports the ODBC Minimum SQL grammar. @Override public boolean supportsMinimumSQLGrammar() throws SQLException { checkClosed(); return false; } // Retrieves whether this database treats mixed case unquoted SQL identifiers as case sensitive and as a result stores them in mixed case. @Override public boolean supportsMixedCaseIdentifiers() throws SQLException { checkClosed(); return false; // Note: Proc names are sensitive, but not tables/columns! } // Retrieves whether this database treats mixed case quoted SQL identifiers as case sensitive and as a result stores them in mixed case. @Override public boolean supportsMixedCaseQuotedIdentifiers() throws SQLException { checkClosed(); return false; // Note: Proc names are sensitive, but not tables/columns! } // Retrieves whether it is possible to have multiple ResultSet objects returned from a CallableStatement object simultaneously. @Override public boolean supportsMultipleOpenResults() throws SQLException { checkClosed(); return true; } // Retrieves whether this database supports getting multiple ResultSet objects from a single call to the method execute. @Override public boolean supportsMultipleResultSets() throws SQLException { checkClosed(); return true; } // Retrieves whether this database allows having multiple transactions open at once (on different connections) throws SQLException. @Override public boolean supportsMultipleTransactions() throws SQLException { checkClosed(); return false; } // Retrieves whether this database supports named parameters to callable statements. @Override public boolean supportsNamedParameters() throws SQLException { checkClosed(); return false; } // Retrieves whether columns in this database may be defined as non-nullable. @Override public boolean supportsNonNullableColumns() throws SQLException { checkClosed(); return true; } // Retrieves whether this database supports keeping cursors open across commits. @Override public boolean supportsOpenCursorsAcrossCommit() throws SQLException { checkClosed(); return false; } // Retrieves whether this database supports keeping cursors open across rollbacks. @Override public boolean supportsOpenCursorsAcrossRollback() throws SQLException { checkClosed(); return false; } // Retrieves whether this database supports keeping statements open across commits. @Override public boolean supportsOpenStatementsAcrossCommit() throws SQLException { checkClosed(); return true; } // Retrieves whether this database supports keeping statements open across rollbacks. @Override public boolean supportsOpenStatementsAcrossRollback() throws SQLException { checkClosed(); return true; } // Retrieves whether this database supports using a column that is not in the SELECT statement in an ORDER BY clause. @Override public boolean supportsOrderByUnrelated() throws SQLException { checkClosed(); return true; } // Retrieves whether this database supports some form of outer join. @Override public boolean supportsOuterJoins() throws SQLException { checkClosed(); return true; } // Retrieves whether this database supports positioned DELETE statements. @Override public boolean supportsPositionedDelete() throws SQLException { checkClosed(); return false; } // Retrieves whether this database supports positioned UPDATE statements. @Override public boolean supportsPositionedUpdate() throws SQLException { checkClosed(); return false; } // Retrieves whether this database supports the given concurrency type in combination with the given result set type. @Override public boolean supportsResultSetConcurrency(int type, int concurrency) throws SQLException { checkClosed(); if (type == ResultSet.TYPE_SCROLL_INSENSITIVE && concurrency == ResultSet.CONCUR_READ_ONLY) return true; return false; } // Retrieves whether this database supports the given result set holdability. @Override public boolean supportsResultSetHoldability(int holdability) throws SQLException { checkClosed(); return false; } // Retrieves whether this database supports the given result set type. @Override public boolean supportsResultSetType(int type) throws SQLException { checkClosed(); if (type == ResultSet.TYPE_SCROLL_INSENSITIVE) return true; return false; } // Retrieves whether this database supports savepoints. @Override public boolean supportsSavepoints() throws SQLException { checkClosed(); return false; } // Retrieves whether a schema name can be used in a data manipulation statement. @Override public boolean supportsSchemasInDataManipulation() throws SQLException { checkClosed(); return false; } // Retrieves whether a schema name can be used in an index definition statement. @Override public boolean supportsSchemasInIndexDefinitions() throws SQLException { checkClosed(); return false; } // Retrieves whether a schema name can be used in a privilege definition statement. @Override public boolean supportsSchemasInPrivilegeDefinitions() throws SQLException { checkClosed(); return false; } // Retrieves whether a schema name can be used in a procedure call statement. @Override public boolean supportsSchemasInProcedureCalls() throws SQLException { checkClosed(); return false; } // Retrieves whether a schema name can be used in a table definition statement. @Override public boolean supportsSchemasInTableDefinitions() throws SQLException { checkClosed(); return false; } // Retrieves whether this database supports SELECT FOR UPDATE statements. @Override public boolean supportsSelectForUpdate() throws SQLException { checkClosed(); return false; } // Retrieves whether this database supports statement pooling. @Override public boolean supportsStatementPooling() throws SQLException { checkClosed(); return false; } // Retrieves whether this database supports invoking user-defined or vendor functions using the stored procedure escape syntax. @Override public boolean supportsStoredFunctionsUsingCallSyntax() throws SQLException { checkClosed(); return false; } // Retrieves whether this database supports stored procedure calls that use the stored procedure escape syntax. @Override public boolean supportsStoredProcedures() throws SQLException { checkClosed(); return true; } // Retrieves whether this database supports subqueries in comparison expressions. @Override public boolean supportsSubqueriesInComparisons() throws SQLException { checkClosed(); return false; } // Retrieves whether this database supports subqueries in EXISTS expressions. @Override public boolean supportsSubqueriesInExists() throws SQLException { checkClosed(); return false; } // Retrieves whether this database supports subqueries in IN expressions. @Override public boolean supportsSubqueriesInIns() throws SQLException { checkClosed(); return false; } // Retrieves whether this database supports subqueries in quantified expressions. @Override public boolean supportsSubqueriesInQuantifieds() throws SQLException { checkClosed(); return false; } // Retrieves whether this database supports table correlation names. @Override public boolean supportsTableCorrelationNames() throws SQLException { checkClosed(); return true; } // Retrieves whether this database supports the given transaction isolation level. @Override public boolean supportsTransactionIsolationLevel(int level) throws SQLException { checkClosed(); if (level == Connection.TRANSACTION_SERIALIZABLE) return true; return false; } // Retrieves whether this database supports transactions. @Override public boolean supportsTransactions() throws SQLException { checkClosed(); return false; } // Retrieves whether this database supports SQL UNION. @Override public boolean supportsUnion() throws SQLException { checkClosed(); return false; } // Retrieves whether this database supports SQL UNION ALL. @Override public boolean supportsUnionAll() throws SQLException { checkClosed(); return false; } // Retrieves whether or not a visible row update can be detected by calling the method ResultSet.rowUpdated. @Override public boolean updatesAreDetected(int type) throws SQLException { checkClosed(); return false; } // Retrieves whether this database uses a file for each table. @Override public boolean usesLocalFilePerTable() throws SQLException { checkClosed(); return false; } // Retrieves whether this database stores tables in a local file. @Override public boolean usesLocalFiles() throws SQLException { checkClosed(); return false; } // Returns true if this either implements the interface argument or is directly or indirectly a wrapper for an object that does. @Override public boolean isWrapperFor(Class<?> iface) throws SQLException { checkClosed(); return iface.isInstance(this); } // Returns an object that implements the given interface to allow access to non-standard methods, or standard methods not exposed by the proxy. @Override public <T> T unwrap(Class<T> iface) throws SQLException { checkClosed(); try { return iface.cast(this); } catch (ClassCastException cce) { throw SQLError.get(SQLError.ILLEGAL_ARGUMENT, iface.toString()); } } @Override public ResultSet getPseudoColumns(String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern) throws SQLException { checkClosed(); throw SQLError.noSupport(); } @Override public boolean generatedKeyAlwaysReturned() throws SQLException { throw SQLError.noSupport(); } }