tech.ydb.jdbc.impl.YdbDatabaseMetaDataImpl Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of ydb-jdbc-driver Show documentation
Show all versions of ydb-jdbc-driver Show documentation
JDBC Driver over YDB Java SDK
package tech.ydb.jdbc.impl;
import java.sql.ResultSet;
import java.sql.RowIdLifetime;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import javax.annotation.Nullable;
import com.google.common.base.Strings;
import tech.ydb.jdbc.YdbConnection;
import tech.ydb.jdbc.YdbConst;
import tech.ydb.jdbc.YdbDatabaseMetaData;
import tech.ydb.jdbc.YdbDriverInfo;
import tech.ydb.jdbc.YdbTypes;
import tech.ydb.jdbc.common.YdbFunctions;
import tech.ydb.jdbc.context.YdbExecutor;
import tech.ydb.proto.scheme.SchemeOperationProtos;
import tech.ydb.scheme.SchemeClient;
import tech.ydb.scheme.description.ListDirectoryResult;
import tech.ydb.table.Session;
import tech.ydb.table.description.TableColumn;
import tech.ydb.table.description.TableDescription;
import tech.ydb.table.description.TableIndex;
import tech.ydb.table.result.ResultSetReader;
import tech.ydb.table.settings.DescribeTableSettings;
import tech.ydb.table.values.PrimitiveType;
import tech.ydb.table.values.Type;
public class YdbDatabaseMetaDataImpl implements YdbDatabaseMetaData {
private static final Logger LOGGER = Logger.getLogger(YdbDatabaseMetaDataImpl.class.getName());
static final String TABLE = "TABLE";
static final String SYSTEM_TABLE = "SYSTEM TABLE";
private final YdbConnectionImpl connection;
private final YdbTypes types;
private final YdbExecutor executor;
public YdbDatabaseMetaDataImpl(YdbConnectionImpl connection) {
this.connection = Objects.requireNonNull(connection);
this.types = connection.getYdbTypes();
this.executor = new YdbExecutor(LOGGER);
}
@Override
public boolean allProceduresAreCallable() {
return false;
}
@Override
public boolean allTablesAreSelectable() {
return true;
}
@Override
public String getURL() {
return connection.getCtx().getUrl();
}
@Override
public String getUserName() {
return "";
}
@Override
public boolean isReadOnly() throws SQLException {
return connection.isReadOnly();
}
@Override
public boolean nullsAreSortedHigh() {
return true;
}
@Override
public boolean nullsAreSortedLow() {
return false;
}
@Override
public boolean nullsAreSortedAtStart() {
return false;
}
@Override
public boolean nullsAreSortedAtEnd() {
return false;
}
@Override
public String getDatabaseProductName() {
return "YDB";
}
@Override
public String getDatabaseProductVersion() {
return "unspecified"; // TODO: don't know how to get YDB version
}
@Override
public String getDriverName() {
return YdbDriverInfo.DRIVER_NAME;
}
@Override
public String getDriverVersion() {
return YdbDriverInfo.DRIVER_VERSION;
}
@Override
public int getDriverMajorVersion() {
return YdbDriverInfo.DRIVER_MAJOR_VERSION;
}
@Override
public int getDriverMinorVersion() {
return YdbDriverInfo.DRIVER_MINOR_VERSION;
}
@Override
public boolean usesLocalFiles() {
return false;
}
@Override
public boolean usesLocalFilePerTable() {
return false;
}
@Override
public boolean supportsMixedCaseIdentifiers() {
return true;
}
@Override
public boolean storesUpperCaseIdentifiers() {
return false;
}
@Override
public boolean storesLowerCaseIdentifiers() {
return false;
}
@Override
public boolean storesMixedCaseIdentifiers() {
return true;
}
@Override
public boolean supportsMixedCaseQuotedIdentifiers() {
return true;
}
@Override
public boolean storesUpperCaseQuotedIdentifiers() {
return false;
}
@Override
public boolean storesLowerCaseQuotedIdentifiers() {
return false;
}
@Override
public boolean storesMixedCaseQuotedIdentifiers() {
return true;
}
@Override
public String getIdentifierQuoteString() {
return QUOTE_IDENTIFIER;
}
@Override
public String getSQLKeywords() {
return ""; // TODO: unknown?
}
@Override
public String getNumericFunctions() {
return YdbFunctions.NUMERIC_FUNCTIONS;
}
@Override
public String getStringFunctions() {
return YdbFunctions.STRING_FUNCTIONS;
}
@Override
public String getSystemFunctions() {
return YdbFunctions.SYSTEM_FUNCTIONS;
}
@Override
public String getTimeDateFunctions() {
return YdbFunctions.DATETIME_FUNCTIONS;
}
@Override
public String getSearchStringEscape() {
return "\\";
}
@Override
public String getExtraNameCharacters() {
return "";
}
@Override
public boolean supportsAlterTableWithAddColumn() {
return true;
}
@Override
public boolean supportsAlterTableWithDropColumn() {
return true;
}
@Override
public boolean supportsColumnAliasing() {
return true;
}
@Override
public boolean nullPlusNonNullIsNull() {
return true;
}
@Override
public boolean supportsConvert() {
return false; // Probably not
}
@Override
public boolean supportsConvert(int fromType, int toType) {
return false; // Probably not
}
@Override
public boolean supportsTableCorrelationNames() {
return true;
}
@Override
public boolean supportsDifferentTableCorrelationNames() {
return false;
}
@Override
public boolean supportsExpressionsInOrderBy() {
return true;
}
@Override
public boolean supportsOrderByUnrelated() {
return false;
}
@Override
public boolean supportsGroupBy() {
return true;
}
@Override
public boolean supportsGroupByUnrelated() {
return true;
}
@Override
public boolean supportsGroupByBeyondSelect() {
return true;
}
@Override
public boolean supportsLikeEscapeClause() {
return true;
}
@Override
public boolean supportsMultipleResultSets() {
return true;
}
@Override
public boolean supportsMultipleTransactions() {
return true; // multiple transactions in different connections
}
@Override
public boolean supportsNonNullableColumns() {
return false; // not yet
}
@Override
public boolean supportsMinimumSQLGrammar() {
return true; // think so
}
@Override
public boolean supportsCoreSQLGrammar() {
return false; // no
}
@Override
public boolean supportsExtendedSQLGrammar() {
return false; // no
}
@Override
public boolean supportsANSI92EntryLevelSQL() {
return false; // no
}
@Override
public boolean supportsANSI92IntermediateSQL() {
return false; // no
}
@Override
public boolean supportsANSI92FullSQL() {
return false; // no
}
@Override
public boolean supportsIntegrityEnhancementFacility() {
return false; // no
}
@Override
public boolean supportsOuterJoins() {
return true; // yes
}
@Override
public boolean supportsFullOuterJoins() {
return true; // yes
}
@Override
public boolean supportsLimitedOuterJoins() {
return true; // yes
}
@Override
public String getSchemaTerm() {
return "Database";
}
@Override
public String getProcedureTerm() {
return "";
}
@Override
public String getCatalogTerm() {
return "Path";
}
@Override
public boolean isCatalogAtStart() {
return true;
}
@Override
public String getCatalogSeparator() {
return "/";
}
@Override
public boolean supportsSchemasInDataManipulation() {
return false;
}
@Override
public boolean supportsSchemasInProcedureCalls() {
return false;
}
@Override
public boolean supportsSchemasInTableDefinitions() {
return false;
}
@Override
public boolean supportsSchemasInIndexDefinitions() {
return false;
}
@Override
public boolean supportsSchemasInPrivilegeDefinitions() {
return false;
}
@Override
public boolean supportsCatalogsInDataManipulation() {
return true;
}
@Override
public boolean supportsCatalogsInProcedureCalls() {
return true;
}
@Override
public boolean supportsCatalogsInTableDefinitions() {
return true;
}
@Override
public boolean supportsCatalogsInIndexDefinitions() {
return true;
}
@Override
public boolean supportsCatalogsInPrivilegeDefinitions() {
return true;
}
@Override
public boolean supportsPositionedDelete() {
return false; // No
}
@Override
public boolean supportsPositionedUpdate() {
return false; // No
}
@Override
public boolean supportsSelectForUpdate() {
return false; // Pessimistic locks are not supported
}
@Override
public boolean supportsStoredProcedures() {
return false; // not supported
}
@Override
public boolean supportsSubqueriesInComparisons() {
return true;
}
@Override
public boolean supportsSubqueriesInExists() {
return true;
}
@Override
public boolean supportsSubqueriesInIns() {
return true;
}
@Override
public boolean supportsSubqueriesInQuantifieds() {
return true;
}
@Override
public boolean supportsCorrelatedSubqueries() {
return true;
}
@Override
public boolean supportsUnion() {
return false; // only All supported
}
@Override
public boolean supportsUnionAll() {
return true;
}
@Override
public boolean supportsOpenCursorsAcrossCommit() {
return true; // yes
}
@Override
public boolean supportsOpenCursorsAcrossRollback() {
return true; // yes
}
@Override
public boolean supportsOpenStatementsAcrossCommit() {
return true; // yes
}
@Override
public boolean supportsOpenStatementsAcrossRollback() {
return true; // yes
}
@Override
public int getMaxBinaryLiteralLength() {
return YdbConst.MAX_COLUMN_SIZE;
}
@Override
public int getMaxCharLiteralLength() {
return YdbConst.MAX_COLUMN_SIZE;
}
@Override
public int getMaxColumnNameLength() {
return YdbConst.MAX_COLUMN_NAME_LENGTH;
}
@Override
public int getMaxColumnsInGroupBy() {
return YdbConst.MAX_COLUMNS;
}
@Override
public int getMaxColumnsInIndex() {
return YdbConst.MAX_COLUMNS_IN_PRIMARY_KEY;
}
@Override
public int getMaxColumnsInOrderBy() {
return YdbConst.MAX_COLUMNS;
}
@Override
public int getMaxColumnsInSelect() {
return YdbConst.MAX_COLUMNS;
}
@Override
public int getMaxColumnsInTable() {
return YdbConst.MAX_COLUMNS;
}
@Override
public int getMaxConnections() {
return YdbConst.MAX_CONNECTIONS;
}
@Override
public int getMaxCursorNameLength() {
return YdbConst.MAX_ELEMENT_NAME_LENGTH;
}
@Override
public int getMaxIndexLength() {
return YdbConst.MAX_PRIMARY_KEY_SIZE;
}
@Override
public int getMaxSchemaNameLength() {
return YdbConst.MAX_ELEMENT_NAME_LENGTH;
}
@Override
public int getMaxProcedureNameLength() {
return YdbConst.MAX_ELEMENT_NAME_LENGTH;
}
@Override
public int getMaxCatalogNameLength() {
return YdbConst.MAX_ELEMENT_NAME_LENGTH;
}
@Override
public int getMaxRowSize() {
return YdbConst.MAX_ROW_SIZE;
}
@Override
public boolean doesMaxRowSizeIncludeBlobs() {
return true;
}
@Override
public int getMaxStatementLength() {
return YdbConst.MAX_STATEMENT_LENGTH;
}
@Override
public int getMaxStatements() {
return 0; // no limit for statements (statement is opened only in memory)
}
@Override
public int getMaxTableNameLength() {
return YdbConst.MAX_ELEMENT_NAME_LENGTH;
}
@Override
public int getMaxTablesInSelect() {
return 0; // Limit is unknown
}
@Override
public int getMaxUserNameLength() {
return YdbConst.MAX_ELEMENT_NAME_LENGTH;
}
@Override
public int getDefaultTransactionIsolation() {
return YdbConst.TRANSACTION_SERIALIZABLE_READ_WRITE;
}
@Override
public boolean supportsTransactions() {
return true;
}
@Override
public boolean supportsTransactionIsolationLevel(int level) {
switch (level) {
case YdbConst.TRANSACTION_SERIALIZABLE_READ_WRITE:
case YdbConst.ONLINE_CONSISTENT_READ_ONLY:
case YdbConst.ONLINE_INCONSISTENT_READ_ONLY:
case YdbConst.STALE_CONSISTENT_READ_ONLY:
return true;
default:
return false;
}
}
@Override
public boolean supportsDataDefinitionAndDataManipulationTransactions() {
return true; // basically yes, but DDL executed outsize of a transaction
}
@Override
public boolean supportsDataManipulationTransactionsOnly() {
return true; // transaction will be prepared anyway
}
@Override
public boolean dataDefinitionCausesTransactionCommit() {
return false; // DDL outside of transactions
}
@Override
public boolean dataDefinitionIgnoredInTransactions() {
return true; // DDL outside of transactions
}
@Override
public ResultSet getProcedures(String catalog, String schemaPattern, String procedureNamePattern) {
return fromEmptyResultSet(); // Procedures are not supported
}
@Override
public ResultSet getProcedureColumns(String catalog, String schemaPattern, String procedureNamePattern,
String columnNamePattern) {
return fromEmptyResultSet(); // Procedures are not supported
}
@Override
public ResultSet getTables(String catalog, String schemaPattern, String tableNamePattern, String[] types)
throws SQLException {
LOGGER.log(Level.FINE,
"getTables, catalog=[{0}], schemaPattern=[{1}], tableNamePattern=[{2}], types={3}",
new Object[]{catalog, schemaPattern, tableNamePattern, types == null ? "" : Arrays.asList(types)}
);
if (!isMatchedCatalog(catalog)) {
return fromEmptyResultSet();
}
if (!isMatchedSchema(schemaPattern)) {
return fromEmptyResultSet();
}
boolean matchTables;
boolean matchSystemTables;
if (types == null) {
matchTables = true;
matchSystemTables = true;
} else {
Set typesSet = new HashSet<>(Arrays.asList(types));
matchTables = typesSet.contains(TABLE);
matchSystemTables = typesSet.contains(SYSTEM_TABLE);
}
if (!matchTables && !matchSystemTables) {
return fromEmptyResultSet();
}
List