diff --git a/jdbc-v2/src/main/java/com/clickhouse/jdbc/metadata/DatabaseMetaDataImpl.java b/jdbc-v2/src/main/java/com/clickhouse/jdbc/metadata/DatabaseMetaDataImpl.java index 5289eb5fb..65c79de2b 100644 --- a/jdbc-v2/src/main/java/com/clickhouse/jdbc/metadata/DatabaseMetaDataImpl.java +++ b/jdbc-v2/src/main/java/com/clickhouse/jdbc/metadata/DatabaseMetaDataImpl.java @@ -31,9 +31,33 @@ public class DatabaseMetaDataImpl implements java.sql.DatabaseMetaData, JdbcV2Wrapper { private static final Logger log = LoggerFactory.getLogger(DatabaseMetaDataImpl.class); + + public enum TableType { + DICTIONARY("DICTIONARY"), + LOG_TABLE("LOG TABLE"), + MEMORY_TABLE("MEMORY TABLE"), + REMOTE_TABLE("REMOTE TABLE"), + TABLE("TABLE"), + VIEW("VIEW"), + SYSTEM_TABLE("SYSTEM TABLE"), + TEMPORARY_TABLE("TEMPORARY TABLE"); + + private final String typeName; + + TableType(String typeName) { + this.typeName = typeName; + } + + public String getTypeName() { + return typeName; + } + } public static final String[] TABLE_TYPES = new String[] { "DICTIONARY", "LOG TABLE", "MEMORY TABLE", "REMOTE TABLE", "TABLE", "VIEW", "SYSTEM TABLE", "TEMPORARY TABLE" }; + private static final String DATABASE_PRODUCT_NAME = "ClickHouse"; + private static final String DRIVER_NAME = DATABASE_PRODUCT_NAME + " JDBC Driver"; + ConnectionImpl connection; private boolean useCatalogs = false; @@ -95,7 +119,7 @@ public boolean nullsAreSortedHigh() throws SQLException { @Override public boolean nullsAreSortedLow() throws SQLException { - return !nullsAreSortedHigh(); // opposite of nullsAreSortedHigh + return true; // opposite of nullsAreSortedHigh } @Override @@ -106,12 +130,12 @@ public boolean nullsAreSortedAtStart() throws SQLException { @Override public boolean nullsAreSortedAtEnd() throws SQLException { - return false; + return true; // by default NULLS LAST https://clickhouse.com/docs/sql-reference/statements/select/order-by } @Override public String getDatabaseProductName() throws SQLException { - return "ClickHouse"; + return DATABASE_PRODUCT_NAME; } @Override @@ -125,7 +149,7 @@ public String getDatabaseProductVersion() throws SQLException { @Override public String getDriverName() throws SQLException { - return "ClickHouse JDBC Driver"; + return DRIVER_NAME; } @Override @@ -165,17 +189,17 @@ public boolean storesUpperCaseIdentifiers() throws SQLException { @Override public boolean storesLowerCaseIdentifiers() throws SQLException { - return false; + return true; // identifiers are case-insensitive https://clickhouse.com/docs/sql-reference/syntax#identifiers } @Override public boolean storesMixedCaseIdentifiers() throws SQLException { - return true; + return false; } @Override public boolean supportsMixedCaseQuotedIdentifiers() throws SQLException { - return true; + return false; // https://clickhouse.com/docs/sql-reference/syntax#identifiers } @Override @@ -185,12 +209,12 @@ public boolean storesUpperCaseQuotedIdentifiers() throws SQLException { @Override public boolean storesLowerCaseQuotedIdentifiers() throws SQLException { - return false; + return true; } @Override public boolean storesMixedCaseQuotedIdentifiers() throws SQLException { - return true; + return false; } @Override @@ -239,7 +263,7 @@ public String getTimeDateFunctions() throws SQLException { @Override public String getSearchStringEscape() throws SQLException { - return "\\"; + return "\\"; // https://clickhouse.com/docs/sql-reference/functions/string-search-functions#like } @Override @@ -269,22 +293,26 @@ public boolean nullPlusNonNullIsNull() throws SQLException { @Override public boolean supportsConvert() throws SQLException { + // TODO select { fn CONVERT({ts '2021-01-01 12:12:12'}, TIMESTAMP) } + // select cast('2021-01-01 12:12:12' as DateTime) return false; } @Override public boolean supportsConvert(int fromType, int toType) throws SQLException { + // TODO select { fn CONVERT({ts '2021-01-01 12:12:12'}, TIMESTAMP) } + // select cast('2021-01-01 12:12:12' as DateTime) return false; } @Override public boolean supportsTableCorrelationNames() throws SQLException { - return true; + return true; // support aliases } @Override public boolean supportsDifferentTableCorrelationNames() throws SQLException { - return false; + return false; // can be the same as table name `select * from numbers numbers limit 10` } @Override @@ -319,12 +347,12 @@ public boolean supportsLikeEscapeClause() throws SQLException { @Override public boolean supportsMultipleResultSets() throws SQLException { - return false; + return false; // only one statement per `execute` } @Override public boolean supportsMultipleTransactions() throws SQLException { - return false; + return false; // no transaction support } @Override @@ -334,17 +362,17 @@ public boolean supportsNonNullableColumns() throws SQLException { @Override public boolean supportsMinimumSQLGrammar() throws SQLException { - return true; + return true; // https://www.nv5geospatialsoftware.com/docs/odbcconformance.html } @Override public boolean supportsCoreSQLGrammar() throws SQLException { - return true; + return true; // https://www.nv5geospatialsoftware.com/docs/odbcconformance.html } @Override public boolean supportsExtendedSQLGrammar() throws SQLException { - return false; + return true; // https://www.nv5geospatialsoftware.com/docs/odbcconformance.html } @Override @@ -374,12 +402,12 @@ public boolean supportsOuterJoins() throws SQLException { @Override public boolean supportsFullOuterJoins() throws SQLException { - return true; + return true; // https://clickhouse.com/docs/sql-reference/statements/select/join } @Override public boolean supportsLimitedOuterJoins() throws SQLException { - return true; + return supportsFullOuterJoins(); // https://clickhouse.com/docs/sql-reference/statements/select/join } /** @@ -409,7 +437,7 @@ public String getCatalogTerm() { @Override public boolean isCatalogAtStart() throws SQLException { - return true; + return true; // we do not support catalogs yet but it will appear at start in the future } @Override @@ -444,47 +472,47 @@ public boolean supportsSchemasInPrivilegeDefinitions() throws SQLException { @Override public boolean supportsCatalogsInDataManipulation() throws SQLException { - return false; + return false; // do not support catalogs yet } @Override public boolean supportsCatalogsInProcedureCalls() throws SQLException { - return false; + return false; // no catalogs } @Override public boolean supportsCatalogsInTableDefinitions() throws SQLException { - return false; + return false; // no catalogs } @Override public boolean supportsCatalogsInIndexDefinitions() throws SQLException { - return false; + return false; // no catalogs } @Override public boolean supportsCatalogsInPrivilegeDefinitions() throws SQLException { - return false; + return false; // no catalogs } @Override public boolean supportsPositionedDelete() throws SQLException { - return false; + return false; // no full support of deletes } @Override public boolean supportsPositionedUpdate() throws SQLException { - return false; + return false; // no full support of updates } @Override public boolean supportsSelectForUpdate() throws SQLException { - return false; + return false; // https://clickhouse.com/docs/sql-reference/statements/alter/update } @Override public boolean supportsStoredProcedures() throws SQLException { - return false; + return false; // no support } @Override @@ -544,150 +572,142 @@ public boolean supportsOpenStatementsAcrossRollback() throws SQLException { @Override public int getMaxBinaryLiteralLength() throws SQLException { - return 0; + return Integer.MAX_VALUE; } @Override public int getMaxCharLiteralLength() throws SQLException { - return 0; + return Integer.MAX_VALUE; } @Override public int getMaxColumnNameLength() throws SQLException { - return 0; + return Short.MAX_VALUE; } @Override public int getMaxColumnsInGroupBy() throws SQLException { - return 0; + return 0; // no limit } @Override public int getMaxColumnsInIndex() throws SQLException { - return 0; + return 0; // no limit } @Override public int getMaxColumnsInOrderBy() throws SQLException { - return 0; + return 0; // no limit } @Override public int getMaxColumnsInSelect() throws SQLException { - return 0; + return 0; // no limit } @Override public int getMaxColumnsInTable() throws SQLException { - return 0; + return 1000; } @Override public int getMaxConnections() throws SQLException { - return 0; + return 150; // no limit in theory but 150 is too many from one client } @Override public int getMaxCursorNameLength() throws SQLException { - return 0; + return 0; // no cursor - no limit } @Override public int getMaxIndexLength() throws SQLException { - return 0; + return 0; // no limit } @Override public int getMaxSchemaNameLength() throws SQLException { - return 0; + return Integer.MAX_VALUE; } @Override public int getMaxProcedureNameLength() throws SQLException { - return 0; + return 0; // no limit } @Override public int getMaxCatalogNameLength() throws SQLException { - return 0; + return 0; // no catalog - no limit } @Override public int getMaxRowSize() throws SQLException { - return 0; + return 0; // no limit } @Override public boolean doesMaxRowSizeIncludeBlobs() throws SQLException { - return true; + return true; // blobs sent as String as part of row data and not accessible from somehow else } @Override public int getMaxStatementLength() throws SQLException { - return 0; + return 0; // there is configurable limit in ClickHouse but at this point we treat it as unknown. } @Override public int getMaxStatements() throws SQLException { - return 0; + return getMaxConnections(); // as much as connections } @Override public int getMaxTableNameLength() throws SQLException { - return 0; + return Integer.MAX_VALUE; } @Override public int getMaxTablesInSelect() throws SQLException { - return 0; + return 0; // no limit } @Override public int getMaxUserNameLength() throws SQLException { - return 0; + return 0; // unknown } @Override public int getDefaultTransactionIsolation() throws SQLException { - try { - return connection.getTransactionIsolation(); - } catch (Exception e) { - throw ExceptionUtils.toSqlState(e); - } + return Connection.TRANSACTION_NONE; } @Override public boolean supportsTransactions() throws SQLException { - return false; + return false; // no transaction support } @Override public boolean supportsTransactionIsolationLevel(int level) throws SQLException { - try { - return level == connection.getTransactionIsolation(); - } catch (Exception e) { - throw ExceptionUtils.toSqlState(e); - } + return Connection.TRANSACTION_NONE == level; // no transaction support } @Override public boolean supportsDataDefinitionAndDataManipulationTransactions() throws SQLException { - return false; + return false; // no transaction support } @Override public boolean supportsDataManipulationTransactionsOnly() throws SQLException { - return false; + return false; // no transaction support } @Override public boolean dataDefinitionCausesTransactionCommit() throws SQLException { - return false; + return false; // no transaction support } @Override public boolean dataDefinitionIgnoredInTransactions() throws SQLException { - return false; + return false; // no transaction support } @Override @@ -1191,52 +1211,52 @@ public boolean supportsResultSetType(int type) throws SQLException { @Override public boolean supportsResultSetConcurrency(int type, int concurrency) throws SQLException { - return false; + return ResultSet.TYPE_FORWARD_ONLY == type && ResultSet.CONCUR_READ_ONLY == concurrency; } @Override public boolean ownUpdatesAreVisible(int type) throws SQLException { - return false; + return false; // do not support updates in ResultSet } @Override public boolean ownDeletesAreVisible(int type) throws SQLException { - return false; + return false; // do not support deletes in ResultSet } @Override public boolean ownInsertsAreVisible(int type) throws SQLException { - return false; + return false; // do not support inserts in ResultSet } @Override public boolean othersUpdatesAreVisible(int type) throws SQLException { - return false; + return false; // no } @Override public boolean othersDeletesAreVisible(int type) throws SQLException { - return false; + return false; // no } @Override public boolean othersInsertsAreVisible(int type) throws SQLException { - return false; + return false; // no } @Override public boolean updatesAreDetected(int type) throws SQLException { - return false; + return false; // no updates supported in ResultSets } @Override public boolean deletesAreDetected(int type) throws SQLException { - return false; + return false; // no updates supported in ResultSets } @Override public boolean insertsAreDetected(int type) throws SQLException { - return false; + return false; // no updates supported in ResultSets } @Override @@ -1274,20 +1294,17 @@ public boolean supportsSavepoints() throws SQLException { @Override public boolean supportsNamedParameters() throws SQLException { - // TODO: it should be true - return false; + return false; // no callable statements } @Override public boolean supportsMultipleOpenResults() throws SQLException { - // TODO: should be explained - return false; + return false; // no callable object support } @Override public boolean supportsGetGeneratedKeys() throws SQLException { - // TODO: update when implemented in ClickHouse - return false; + return false; // no generated keys are not returned } @Override @@ -1404,12 +1421,12 @@ public int getSQLStateType() throws SQLException { @Override public boolean locatorsUpdateCopy() throws SQLException { - return false; + return false; // no - we do not support LOB locators } @Override public boolean supportsStatementPooling() throws SQLException { - return false; + return false; // TODO ? } @Override @@ -1541,11 +1558,11 @@ public boolean generatedKeyAlwaysReturned() throws SQLException { @Override public long getMaxLogicalLobSize() throws SQLException { - return 0; + return 0; // no limits - mainly stored as strings } @Override public boolean supportsRefCursors() throws SQLException { - return false; + return false; // no ref cursors } } diff --git a/jdbc-v2/src/test/java/com/clickhouse/jdbc/metadata/DatabaseMetaDataTest.java b/jdbc-v2/src/test/java/com/clickhouse/jdbc/metadata/DatabaseMetaDataTest.java index 7201d9c52..24bb1ac87 100644 --- a/jdbc-v2/src/test/java/com/clickhouse/jdbc/metadata/DatabaseMetaDataTest.java +++ b/jdbc-v2/src/test/java/com/clickhouse/jdbc/metadata/DatabaseMetaDataTest.java @@ -19,12 +19,12 @@ import java.sql.Types; import java.util.Arrays; import java.util.Collections; -import java.util.HashSet; import java.util.List; import java.util.Properties; import java.util.Set; import java.util.stream.Collectors; +import static java.sql.RowIdLifetime.ROWID_UNSUPPORTED; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertNotEquals; @@ -144,6 +144,165 @@ public void testGetColumns() throws Exception { } } + @Test(groups = {"integration"}) + public void testSupportFlags() throws Exception { + try (Connection conn = getJdbcConnection()) { + DatabaseMetaData dbmd = conn.getMetaData(); + + + assertEquals(dbmd.getMaxConnections(), 150); + assertEquals(dbmd.isReadOnly(), false); + assertEquals(dbmd.getDriverName(), "ClickHouse JDBC Driver"); + assertEquals(dbmd.getSchemaTerm(), "schema"); + assertEquals(dbmd.getDatabaseProductName(), "ClickHouse"); + assertEquals(dbmd.supportsMixedCaseIdentifiers(), true); + assertEquals(dbmd.supportsMixedCaseQuotedIdentifiers(), false); + assertEquals(dbmd.getIdentifierQuoteString(), "`"); + assertEquals(dbmd.getSQLKeywords(), "APPLY,ASOF,ATTACH,CLUSTER,DATABASE,DATABASES,DETACH,DICTIONARY,DICTIONARIES,ILIKE,INF,LIMIT,LIVE,KILL,MATERIALIZED,NAN,OFFSET,OPTIMIZE,OUTFILE,POLICY,PREWHERE,PROFILE,QUARTER,QUOTA,RENAME,REPLACE,SAMPLE,SETTINGS,SHOW,TABLES,TIES,TOP,TOTALS,TRUNCATE,USE,WATCH,WEEK"); + assertEquals(dbmd.getNumericFunctions(), "abs,acos,acosh,asin,asinh,atan,atan2,atanh,cbrt,cos,cosh,divide,e,erf,erfc,exp,exp10,exp2,gcd,hypot,intDiv,intDivOrZero,intExp10,intExp2,lcm,lgamma,ln,log,log10,log1p,log2,minus,modulo,moduloOrZero,multiply,negate,pi,plus,pow,power,sign,sin,sinh,sqrt,tan,tgamma"); + assertEquals(dbmd.getStringFunctions(), "appendTrailingCharIfAbsent,base64Decode,base64Encode,char_length,CHAR_LENGTH,character_length,CHARACTER_LENGTH,concat,concatAssumeInjective,convertCharset,countMatches,countSubstrings,countSubstringsCaseInsensitive,countSubstringsCaseInsensitiveUTF8,CRC32,CRC32IEEE,CRC64,decodeXMLComponent,empty,encodeXMLComponent,endsWith,extract,extractAll,extractAllGroupsHorizontal,extractAllGroupsVertical,extractTextFromHTML ,format,ilike,isValidUTF8,lcase,leftPad,leftPadUTF8,length,lengthUTF8,like,locate,lower,lowerUTF8,match,mid,multiFuzzyMatchAllIndices,multiFuzzyMatchAny,multiFuzzyMatchAnyIndex,multiMatchAllIndices,multiMatchAny,multiMatchAnyIndex,multiSearchAllPositions,multiSearchAllPositionsUTF8,multiSearchAny,multiSearchFirstIndex,multiSearchFirstPosition,ngramDistance,ngramSearch,normalizedQueryHash,normalizeQuery,notEmpty,notLike,position,positionCaseInsensitive,positionCaseInsensitiveUTF8,positionUTF8,regexpQuoteMeta,repeat,replace,replaceAll,replaceOne,replaceRegexpAll,replaceRegexpOne,reverse,reverseUTF8,rightPad,rightPadUTF8,startsWith,substr,substring,substringUTF8,tokens,toValidUTF8,trim,trimBoth,trimLeft,trimRight,tryBase64Decode,ucase,upper,upperUTF8"); + assertEquals(dbmd.getSystemFunctions(), "bar,basename,blockNumber,blockSerializedSize,blockSize,buildId,byteSize,countDigits,currentDatabase,currentProfiles,currentRoles,currentUser,defaultProfiles,defaultRoles,defaultValueOfArgumentType,defaultValueOfTypeName,dumpColumnStructure,enabledProfiles,enabledRoles,errorCodeToName,filesystemAvailable,filesystemCapacity,filesystemFree,finalizeAggregation,formatReadableQuantity,formatReadableSize,formatReadableTimeDelta,FQDN,getMacro,getServerPort,getSetting,getSizeOfEnumType,greatest,hasColumnInTable,hostName,identity,ifNotFinite,ignore,indexHint,initializeAggregation,initialQueryID,isConstant,isDecimalOverflow,isFinite,isInfinite,isNaN,joinGet,least,MACNumToString,MACStringToNum,MACStringToOUI,materialize,modelEvaluate,neighbor,queryID,randomFixedString,randomPrintableASCII,randomString,randomStringUTF8,replicate,rowNumberInAllBlocks,rowNumberInBlock,runningAccumulate,runningConcurrency,runningDifference,runningDifferenceStartingWithFirstValue,shardCount ,shardNum,sleep,sleepEachRow,tcpPort,throwIf,toColumnTypeName,toTypeName,transform,uptime,version,visibleWidth"); + assertEquals(dbmd.getTimeDateFunctions(), "addDays,addHours,addMinutes,addMonths,addQuarters,addSeconds,addWeeks,addYears,date_add,date_diff,date_sub,date_trunc,dateName,formatDateTime,FROM_UNIXTIME,fromModifiedJulianDay,fromModifiedJulianDayOrNull,now,subtractDays,subtractHours,subtractMinutes,subtractMonths,subtractQuarters,subtractSeconds,subtractWeeks,subtractYears,timeSlot,timeSlots,timestamp_add,timestamp_sub,timeZone,timeZoneOf,timeZoneOffset,today,toDayOfMonth,toDayOfWeek,toDayOfYear,toHour,toISOWeek,toISOYear,toMinute,toModifiedJulianDay,toModifiedJulianDayOrNull,toMonday,toMonth,toQuarter,toRelativeDayNum,toRelativeHourNum,toRelativeMinuteNum,toRelativeMonthNum,toRelativeQuarterNum,toRelativeSecondNum,toRelativeWeekNum,toRelativeYearNum,toSecond,toStartOfDay,toStartOfFifteenMinutes,toStartOfFiveMinute,toStartOfHour,toStartOfInterval,toStartOfISOYear,toStartOfMinute,toStartOfMonth,toStartOfQuarter,toStartOfSecond,toStartOfTenMinutes,toStartOfWeek,toStartOfYear,toTime,toTimeZone,toUnixTimestamp,toWeek,toYear,toYearWeek,toYYYYMM,toYYYYMMDD,toYYYYMMDDhhmmss,yesterday"); + assertEquals(dbmd.getSearchStringEscape(), "\\"); + assertEquals(dbmd.getExtraNameCharacters(), ""); + assertEquals(dbmd.supportsAlterTableWithAddColumn(), true); + assertEquals(dbmd.supportsAlterTableWithDropColumn(), true); + assertEquals(dbmd.supportsColumnAliasing(), true); + assertEquals(dbmd.supportsConvert(), false); + assertEquals(dbmd.supportsTableCorrelationNames(), true); + assertEquals(dbmd.supportsDifferentTableCorrelationNames(), false); + assertEquals(dbmd.supportsExpressionsInOrderBy(), true); + assertEquals(dbmd.supportsOrderByUnrelated(), true); + assertEquals(dbmd.supportsGroupBy(), true); + assertEquals(dbmd.supportsGroupByUnrelated(), true); + assertEquals(dbmd.supportsGroupByBeyondSelect(), true); + assertEquals(dbmd.supportsLikeEscapeClause(), true); + assertEquals(dbmd.supportsMultipleResultSets(), false); + assertEquals(dbmd.supportsMultipleTransactions(), false); + assertEquals(dbmd.supportsNonNullableColumns(), true); + assertEquals(dbmd.supportsMinimumSQLGrammar(), true); + assertEquals(dbmd.supportsCoreSQLGrammar(), true); + assertEquals(dbmd.supportsExtendedSQLGrammar(), true); + assertEquals(dbmd.supportsANSI92EntryLevelSQL(), true); + assertEquals(dbmd.supportsANSI92IntermediateSQL(), false); + assertEquals(dbmd.supportsANSI92FullSQL(), false); + assertEquals(dbmd.supportsIntegrityEnhancementFacility(), false); + assertEquals(dbmd.supportsOuterJoins(), true); + assertEquals(dbmd.supportsFullOuterJoins(), true); + assertEquals(dbmd.supportsLimitedOuterJoins(), true); + assertEquals(dbmd.getProcedureTerm(), "function"); + assertEquals(dbmd.getCatalogTerm(), "cluster"); + assertEquals(dbmd.isCatalogAtStart(), true); + assertEquals(dbmd.getCatalogSeparator(), "."); + assertEquals(dbmd.supportsSchemasInDataManipulation(), true); + assertEquals(dbmd.supportsSchemasInProcedureCalls(), false); + assertEquals(dbmd.supportsSchemasInTableDefinitions(), true); + assertEquals(dbmd.supportsSchemasInIndexDefinitions(), true); + assertEquals(dbmd.supportsSchemasInPrivilegeDefinitions(), true); + assertEquals(dbmd.supportsCatalogsInDataManipulation(), false); + assertEquals(dbmd.supportsCatalogsInProcedureCalls(), false); + assertEquals(dbmd.supportsCatalogsInTableDefinitions(), false); + assertEquals(dbmd.supportsCatalogsInIndexDefinitions(), false); + assertEquals(dbmd.supportsCatalogsInPrivilegeDefinitions(), false); + assertEquals(dbmd.supportsPositionedDelete(), false); + assertEquals(dbmd.supportsPositionedUpdate(), false); + assertEquals(dbmd.supportsSelectForUpdate(), false); + assertEquals(dbmd.supportsStoredProcedures(), false); + assertEquals(dbmd.supportsSubqueriesInComparisons(), true); + assertEquals(dbmd.supportsSubqueriesInExists(), false); + assertEquals(dbmd.supportsSubqueriesInIns(), true); + assertEquals(dbmd.supportsSubqueriesInQuantifieds(), true); + assertEquals(dbmd.supportsCorrelatedSubqueries(), true); + assertEquals(dbmd.supportsUnion(), true); + assertEquals(dbmd.supportsUnionAll(), true); + assertEquals(dbmd.supportsOpenCursorsAcrossCommit(), false); + assertEquals(dbmd.supportsOpenCursorsAcrossRollback(), false); + assertEquals(dbmd.supportsOpenStatementsAcrossCommit(), false); + assertEquals(dbmd.supportsOpenStatementsAcrossRollback(), false); + assertEquals(dbmd.getMaxBinaryLiteralLength(), Integer.MAX_VALUE); + assertEquals(dbmd.getMaxCharLiteralLength(), Integer.MAX_VALUE); + assertEquals(dbmd.getMaxColumnNameLength(), Short.MAX_VALUE); + assertEquals(dbmd.getMaxColumnsInGroupBy(), 0); + assertEquals(dbmd.getMaxColumnsInIndex(), 0); + assertEquals(dbmd.getMaxColumnsInOrderBy(), 0); + assertEquals(dbmd.getMaxColumnsInSelect(), 0); + assertEquals(dbmd.getMaxColumnsInTable(), 1000); + assertEquals(dbmd.getMaxCursorNameLength(), 0); + assertEquals(dbmd.getMaxIndexLength(), 0); + assertEquals(dbmd.getMaxSchemaNameLength(), Integer.MAX_VALUE); + assertEquals(dbmd.getMaxProcedureNameLength(), 0); + assertEquals(dbmd.getMaxCatalogNameLength(), 0); + assertEquals(dbmd.getMaxRowSize(), 0); + assertEquals(dbmd.getMaxStatementLength(), 0); + assertEquals(dbmd.getMaxStatements(), 150); + assertEquals(dbmd.getMaxTableNameLength(), Integer.MAX_VALUE); + assertEquals(dbmd.getMaxTablesInSelect(), 0); + assertEquals(dbmd.getMaxUserNameLength(), 0); + assertEquals(dbmd.getDefaultTransactionIsolation(), 0); + assertEquals(dbmd.supportsTransactions(), false); + assertEquals(dbmd.supportsDataDefinitionAndDataManipulationTransactions(), false); + assertEquals(dbmd.supportsDataManipulationTransactionsOnly(), false); + assertEquals(dbmd.supportsBatchUpdates(), true); + assertEquals(dbmd.supportsSavepoints(), false); + assertEquals(dbmd.supportsNamedParameters(), false); + assertEquals(dbmd.supportsMultipleOpenResults(), false); + assertEquals(dbmd.supportsGetGeneratedKeys(), false); + assertEquals(dbmd.getResultSetHoldability(), 1); + assertEquals(dbmd.getJDBCMajorVersion(), 9); + assertEquals(dbmd.getJDBCMinorVersion(), 4); + assertEquals(dbmd.getSQLStateType(), 2); + assertEquals(dbmd.supportsStatementPooling(), false); + assertEquals(dbmd.getRowIdLifetime(), ROWID_UNSUPPORTED); + assertEquals(dbmd.supportsStoredFunctionsUsingCallSyntax(), false); + assertEquals(dbmd.getMaxLogicalLobSize(), 0); + assertEquals(dbmd.supportsRefCursors(), false); + assertEquals(dbmd.supportsSharding(), false); + assertEquals(dbmd.allProceduresAreCallable(), true); + assertEquals(dbmd.allTablesAreSelectable(), true); + assertEquals(dbmd.nullsAreSortedHigh(), false); + assertEquals(dbmd.nullsAreSortedLow(), true); + assertEquals(dbmd.nullsAreSortedAtStart(), false); + assertEquals(dbmd.nullsAreSortedAtEnd(), true); + assertEquals(dbmd.usesLocalFiles(), false); + assertEquals(dbmd.usesLocalFilePerTable(), false); + assertEquals(dbmd.storesUpperCaseIdentifiers(), false); + assertEquals(dbmd.storesLowerCaseIdentifiers(), true); + assertEquals(dbmd.storesMixedCaseIdentifiers(), false); + assertEquals(dbmd.storesUpperCaseQuotedIdentifiers(), false); + assertEquals(dbmd.storesMixedCaseQuotedIdentifiers(), false); + assertEquals(dbmd.nullPlusNonNullIsNull(), true); + assertEquals(dbmd.supportsConvert(), false); + + assertEquals(dbmd.getDefaultTransactionIsolation(), Connection.TRANSACTION_NONE); + assertEquals(dbmd.supportsTransactionIsolationLevel(Connection.TRANSACTION_NONE), true); + for (int type : new int[] {Connection.TRANSACTION_SERIALIZABLE, Connection.TRANSACTION_READ_COMMITTED, Connection.TRANSACTION_READ_UNCOMMITTED, Connection.TRANSACTION_REPEATABLE_READ} ) { + assertFalse(dbmd.supportsTransactionIsolationLevel(type)); + } + assertEquals(dbmd.dataDefinitionCausesTransactionCommit(), false); + assertEquals(dbmd.dataDefinitionIgnoredInTransactions(), false); + assertEquals(dbmd.supportsResultSetType(ResultSet.TYPE_FORWARD_ONLY), true); + + for (int type : new int[] {ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.TYPE_SCROLL_SENSITIVE} ) { + assertFalse(dbmd.supportsResultSetType(type)); + assertFalse(dbmd.ownUpdatesAreVisible(type)); + assertFalse(dbmd.ownDeletesAreVisible(type)); + assertFalse(dbmd.ownInsertsAreVisible(type)); + assertFalse(dbmd.othersUpdatesAreVisible(type)); + assertFalse(dbmd.othersDeletesAreVisible(type)); + assertFalse(dbmd.othersInsertsAreVisible(type)); + assertFalse(dbmd.updatesAreDetected(type)); + assertFalse(dbmd.deletesAreDetected(type)); + assertFalse(dbmd.insertsAreDetected(type)); + + for (int concurType : new int[] {ResultSet.CONCUR_UPDATABLE, ResultSet.CONCUR_READ_ONLY}) { + assertFalse(dbmd.supportsResultSetConcurrency(type, concurType)); + } + } + + assertFalse(dbmd.generatedKeyAlwaysReturned()); + } + } + @Test(groups = { "integration" }) public void testGetColumnsWithTable() throws Exception { try (Connection conn = getJdbcConnection()) { @@ -333,6 +492,29 @@ public void testGetTableTypes() throws Exception { } } + @Test + public void testGetTablesReturnKnownTableTypes() throws Exception { + try (Connection conn = getJdbcConnection()) { + DatabaseMetaData dbmd = conn.getMetaData(); + + try (ResultSet rs = dbmd.getTables(null, "system", "numbers", null)) { + assertTrue(rs.next()); + String tableType = rs.getString("TABLE_TYPE"); + Assert.assertEquals(tableType, DatabaseMetaDataImpl.TableType.SYSTEM_TABLE.getTypeName(), "table was " + rs.getString("TABLE_NAME")); + + } + try (Statement stmt = conn.createStatement()){ + stmt.executeUpdate("CREATE TABLE test_db_metadata_type_memory (v Int32) ENGINE Memory"); + } + try (ResultSet rs = dbmd.getTables(null, "default", "test_db_metadata_type_memory", null)) { + while (rs.next()) { + String tableType = rs.getString("TABLE_TYPE"); + Assert.assertEquals(tableType, DatabaseMetaDataImpl.TableType.MEMORY_TABLE.getTypeName()); + } + } + } + } + @Test(groups = { "integration" }, enabled = false) public void testGetColumnsWithEmptyCatalog() throws Exception { // test not relevant until catalogs are implemented