MongoDatabaseMetaData.java
package com.dbschema.mongo;
import com.dbschema.mongo.resultSet.ListResultSet;
import com.dbschema.mongo.schema.MetaCollection;
import com.dbschema.mongo.schema.MetaField;
import com.dbschema.mongo.schema.MetaIndex;
import com.dbschema.mongo.schema.MetaJson;
import org.jetbrains.annotations.NotNull;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
/**
* Mongo databases are equivalent to catalogs for this driver. Schemas aren't used. Mongo collections are
* equivalent to tables, in that each collection is a table.
*/
public class MongoDatabaseMetaData implements DatabaseMetaData {
private static final String DB_NAME = "Mongo";
private final MongoConnection con;
public final static String OBJECT_ID_TYPE_NAME = "OBJECT_ID";
public final static String DOCUMENT_TYPE_NAME = "DOCUMENT";
public MongoDatabaseMetaData(MongoConnection con) {
this.con = con;
}
/**
* @see java.sql.DatabaseMetaData#getSchemas()
*/
@Override
public ResultSet getSchemas() throws SQLAlreadyClosedException {
List<String> mongoDbs = con.getService().getDatabaseNames();
ListResultSet retVal = new ListResultSet();
retVal.setColumnNames("TABLE_SCHEM", "TABLE_CATALOG");
for (String mongoDb : mongoDbs) {
retVal.addRow(new String[]{mongoDb, DB_NAME});
}
return retVal;
}
/**
* @see java.sql.DatabaseMetaData#getCatalogs()
*/
@Override
public ResultSet getCatalogs() {
ListResultSet retVal = new ListResultSet();
retVal.setColumnNames("TABLE_CAT");
retVal.addRow(new String[]{DB_NAME});
return retVal;
}
/**
* @see java.sql.DatabaseMetaData#getTables(java.lang.String, java.lang.String, java.lang.String,
* java.lang.String[])
*/
public ResultSet getTables(String catalogName, String schemaPattern, String tableNamePattern, String[] types) throws SQLAlreadyClosedException {
ListResultSet resultSet = new ListResultSet();
resultSet.setColumnNames("TABLE_CAT", "TABLE_SCHEM", "TABLE_NAME",
"TABLE_TYPE", "REMARKS", "TYPE_CAT", "TYPE_SCHEM", "TYPE_NAME", "SELF_REFERENCING_COL_NAME",
"REF_GENERATION");
MongoNamePattern pSchema = MongoNamePattern.create(schemaPattern);
MongoNamePattern pTable = MongoNamePattern.create(tableNamePattern);
for (String schema : con.getService().getDatabaseNames()) {
if (pSchema.matches(schema)) {
for (String tableName : con.getService().getCollectionNames(schema)) {
if (pTable.matches(tableName))
resultSet.addRow(createTableRow(schema, tableName));
}
}
}
return resultSet;
}
private String[] createTableRow(String catalogName, String tableName) {
String[] data = new String[10];
data[0] = null; // TABLE_CAT
data[1] = catalogName; // TABLE_SCHEM
data[2] = tableName; // TABLE_NAME
data[3] = "TABLE"; // TABLE_TYPE
data[4] = ""; // REMARKS
data[5] = ""; // TYPE_CAT
data[6] = ""; // TYPE_SCHEM
data[7] = ""; // TYPE_NAME
data[8] = ""; // SELF_REFERENCING_COL_NAME
data[9] = ""; // REF_GENERATION
return data;
}
/**
* @see java.sql.DatabaseMetaData#getColumns(java.lang.String, java.lang.String, java.lang.String,
* java.lang.String)
*/
@Override
public ResultSet getColumns(String catalogName, String schemaName, String tableNamePattern, String columnNamePattern) throws SQLAlreadyClosedException {
// As far as this driver implementation goes, every "table" in MongoDB is actually a collection, and
// every collection "table" has two columns - "_id" column which is the primary key, and a "document"
// column which is the JSON document corresponding to the "_id". An "_id" value can be specified on
// insert, or it can be omitted, in which case MongoDB generates a unique value.
List<MetaCollection> collections = con.getService().getMetaCollections(schemaName, tableNamePattern);
ListResultSet result = new ListResultSet();
result.setColumnNames("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");
List<String[]> columnsData = new ArrayList<>();
for (MetaCollection collection : collections) {
MongoNamePattern p = MongoNamePattern.create(columnNamePattern);
for (MetaField field : collection.fields) {
if (p.matches(field.name)) {
exportColumnsRecursive(collection, columnsData, field);
}
}
}
columnsData.sort((o1, o2) -> {
String n1 = o1[3];
String n2 = o2[3];
if ("_id".equals(n1)) return -1;
if ("_id".equals(n2)) return 1;
return n1.compareTo(n2);
});
for (String[] column : columnsData) {
result.addRow(column);
}
return result;
}
private void exportColumnsRecursive(MetaCollection collection, List<String[]> columnsData, MetaField field) {
String name = field.getNameWithPath();
columnsData.add(new String[]{
DB_NAME, // "TABLE_CAT",
collection.db, // "TABLE_SCHEMA",
collection.name, // "TABLE_NAME", (i.e. MongoDB Collection Name)
name, // "COLUMN_NAME",
"" + field.type, // "DATA_TYPE",
field.typeName, // "TYPE_NAME",
null, // "COLUMN_SIZE",
null, // "BUFFER_LENGTH", (not used)
null, // "DECIMAL_DIGITS",
null, // "NUM_PREC_RADIX",
"" + (field.isMandatory() ? columnNoNulls : columnNullable), // "NULLABLE",
null, // "REMARKS",
null, // "COLUMN_DEF",
null, // "SQL_DATA_TYPE", (not used)
null, // "SQL_DATETIME_SUB", (not used)
null, // "CHAR_OCTET_LENGTH",
null, // "ORDINAL_POSITION",
"YES", // "IS_NULLABLE",
null, // "SCOPE_CATLOG", (not a REF type)
null, // "SCOPE_SCHEMA", (not a REF type)
null, // "SCOPE_TABLE", (not a REF type)
null, // "SOURCE_DATA_TYPE", (not a DISTINCT or REF type)
"NO" // "IS_AUTOINCREMENT" (can be auto-generated, but can also be specified)
});
if (field instanceof MetaJson) {
MetaJson json = (MetaJson) field;
for (MetaField children : json.fields) {
exportColumnsRecursive(collection, columnsData, children);
}
}
}
/**
* @see java.sql.DatabaseMetaData#getPrimaryKeys(java.lang.String, java.lang.String, java.lang.String)
*/
public ResultSet getPrimaryKeys(String catalogName, String schemaName, String tableNamePattern) throws SQLAlreadyClosedException {
/*
* <LI><B>TABLE_CAT</B> String => table catalog (may be <code>null</code>)
* <LI><B>TABLE_SCHEM</B> String => table schema (may be <code>null</code>)
* <LI><B>TABLE_NAME</B> String => table name
* <LI><B>COLUMN_NAME</B> String => column name
* <LI><B>KEY_SEQ</B> 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).
* <LI><B>PK_NAME</B> String
*
*/
ListResultSet result = new ListResultSet();
result.setColumnNames("TABLE_CAT", "TABLE_SCHEM", "TABLE_NAME", "COLUMN_NAME", "KEY_SEQ", "PK_NAME");
List<MetaCollection> collections = con.getService().getMetaCollections(schemaName, tableNamePattern);
for (MetaCollection collection : collections) {
for (MetaIndex index : collection.metaIndexes) {
if (index.pk) {
for (MetaField field : index.metaFields) {
result.addRow(new String[]{
collection.name, // "TABLE_CAT",
null, // "TABLE_SCHEMA",
collection.name, // "TABLE_NAME", (i.e. MongoDB Collection Name)
field.getNameWithPath(), // "COLUMN_NAME",
"" + index.metaFields.indexOf(field), // "ORDINAL_POSITION"
index.name // "INDEX_NAME",
});
}
}
}
}
return result;
}
/**
* @see java.sql.DatabaseMetaData#getIndexInfo(java.lang.String, java.lang.String, java.lang.String,
* boolean, boolean)
*/
public ResultSet getIndexInfo(String catalogName, String schemaName, String tableNamePattern, boolean unique,
boolean approximate) throws SQLAlreadyClosedException {
/*
* * <OL>
* <LI><B>TABLE_CAT</B> String => table catalog (may be <code>null</code>)
* <LI><B>TABLE_SCHEMA</B> String => table schema (may be <code>null</code>)
* <LI><B>TABLE_NAME</B> String => table name
* <LI><B>NON_UNIQUE</B> boolean => Can index values be non-unique.
* false when TYPE is tableIndexStatistic
* <LI><B>INDEX_QUALIFIER</B> String => index catalog (may be <code>null</code>);
* <code>null</code> when TYPE is tableIndexStatistic
* <LI><B>INDEX_NAME</B> String => index name; <code>null</code> when TYPE is
* tableIndexStatistic
* <LI><B>TYPE</B> short => index type:
* <UL>
* <LI> tableIndexStatistic - this identifies table statistics that are
* returned in conjuction with a table's index descriptions
* <LI> tableIndexClustered - this is a clustered index
* <LI> tableIndexHashed - this is a hashed index
* <LI> tableIndexOther - this is some other style of index
* </UL>
* <LI><B>ORDINAL_POSITION</B> short => column sequence number
* within index; zero when TYPE is tableIndexStatistic
* <LI><B>COLUMN_NAME</B> String => column name; <code>null</code> when TYPE is
* tableIndexStatistic
* <LI><B>ASC_OR_DESC</B> String => column sort sequence, "A" => ascending,
* "D" => descending, may be <code>null</code> if sort sequence is not supported;
* <code>null</code> when TYPE is tableIndexStatistic
* <LI><B>CARDINALITY</B> 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.
* <LI><B>PAGES</B> 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.
* <LI><B>FILTER_CONDITION</B> String => Filter condition, if any.
* (may be <code>null</code>)
* </OL>
*/
ListResultSet result = new ListResultSet();
result.setColumnNames("TABLE_CAT", "TABLE_SCHEM", "TABLE_NAME", "NON_UNIQUE", "INDEX_QUALIFIER", "INDEX_NAME",
"TYPE", "ORDINAL_POSITION", "COLUMN_NAME", "ASC_OR_DESC", "CARDINALITY", "PAGES", "FILTER_CONDITION");
List<MetaCollection> collections = con.getService().getMetaCollections(schemaName, tableNamePattern);
for (MetaCollection collection : collections) {
for (MetaIndex index : collection.metaIndexes) {
if (!index.pk) {
for (MetaField field : index.metaFields) {
result.addRow(new String[]{collection.name, // "TABLE_CAT",
null, // "TABLE_SCHEMA",
collection.name, // "TABLE_NAME", (i.e. MongoDB Collection Name)
"YES", // "NON-UNIQUE",
collection.name, // "INDEX QUALIFIER",
index.name, // "INDEX_NAME",
"0", // "TYPE",
"" + index.metaFields.indexOf(field), // "ORDINAL_POSITION"
field.getNameWithPath(), // "COLUMN_NAME",
"A", // "ASC_OR_DESC",
"0", // "CARDINALITY",
"0", // "PAGES",
"" // "FILTER_CONDITION",
});
}
}
}
}
return result;
}
/**
* @see java.sql.DatabaseMetaData#getTypeInfo()
*/
public ResultSet getTypeInfo() {
/*
* <P>Each type description has the following columns:
* <OL>
* <LI><B>TYPE_NAME</B> String => Type name
* <LI><B>DATA_TYPE</B> int => SQL data type from java.sql.Types
* <LI><B>PRECISION</B> int => maximum precision
* <LI><B>LITERAL_PREFIX</B> String => prefix used to quote a literal
* (may be <code>null</code>)
* <LI><B>LITERAL_SUFFIX</B> String => suffix used to quote a literal
(may be <code>null</code>)
* <LI><B>CREATE_PARAMS</B> String => parameters used in creating
* the type (may be <code>null</code>)
* <LI><B>NULLABLE</B> short => can you use NULL for this type.
* <UL>
* <LI> typeNoNulls - does not allow NULL values
* <LI> typeNullable - allows NULL values
* <LI> typeNullableUnknown - nullability unknown
* </UL>
* <LI><B>CASE_SENSITIVE</B> boolean=> is it case sensitive.
* <LI><B>SEARCHABLE</B> short => can you use "WHERE" based on this type:
* <UL>
* <LI> typePredNone - No support
* <LI> typePredChar - Only supported with WHERE .. LIKE
* <LI> typePredBasic - Supported except for WHERE .. LIKE
* <LI> typeSearchable - Supported for all WHERE ..
* </UL>
* <LI><B>UNSIGNED_ATTRIBUTE</B> boolean => is it unsigned.
* <LI><B>FIXED_PREC_SCALE</B> boolean => can it be a money value.
* <LI><B>AUTO_INCREMENT</B> boolean => can it be used for an
* auto-increment value.
* <LI><B>LOCAL_TYPE_NAME</B> String => localized version of type name
* (may be <code>null</code>)
* <LI><B>MINIMUM_SCALE</B> short => minimum scale supported
* <LI><B>MAXIMUM_SCALE</B> short => maximum scale supported
* <LI><B>SQL_DATA_TYPE</B> int => unused
* <LI><B>SQL_DATETIME_SUB</B> int => unused
* <LI><B>NUM_PREC_RADIX</B> int => usually 2 or 10
* </OL>
*/
ListResultSet retVal = new ListResultSet();
retVal.setColumnNames("TYPE_NAME", "DATA_TYPE", "PRECISION", "LITERAL_PREFIX",
"LITERAL_SUFFIX", "CREATE_PARAMS", "NULLABLE", "CASE_SENSITIVE", "SEARCHABLE",
"UNSIGNED_ATTRIBUTE", "FIXED_PREC_SCALE", "AUTO_INCREMENT", "LOCAL_TYPE_NAME", "MINIMUM_SCALE",
"MAXIMUM_SCALE", "SQL_DATA_TYPE", "SQL_DATETIME_SUB", "NUM_PREC_RADIX");
retVal.addRow(new String[]{OBJECT_ID_TYPE_NAME, // "TYPE_NAME",
"" + Types.VARCHAR, // "DATA_TYPE",
"800", // "PRECISION",
"'", // "LITERAL_PREFIX",
"'", // "LITERAL_SUFFIX",
null, // "CREATE_PARAMS",
"" + typeNullable, // "NULLABLE",
"true", // "CASE_SENSITIVE",
"" + typeSearchable, // "SEARCHABLE",
"false", // "UNSIGNED_ATTRIBUTE",
"false", // "FIXED_PREC_SCALE",
"false", // "AUTO_INCREMENT",
OBJECT_ID_TYPE_NAME, // "LOCAL_TYPE_NAME",
"0", // "MINIMUM_SCALE",
"0", // "MAXIMUM_SCALE",
null, // "SQL_DATA_TYPE", (not used)
null, // "SQL_DATETIME_SUB", (not used)
"10", // "NUM_PREC_RADIX" (javadoc says usually 2 or 10)
});
retVal.addRow(new String[]{DOCUMENT_TYPE_NAME, // "TYPE_NAME",
"" + Types.CLOB, // "DATA_TYPE",
"16777216", // "PRECISION",
"'", // "LITERAL_PREFIX",
"'", // "LITERAL_SUFFIX",
null, // "CREATE_PARAMS",
"" + typeNullable, // "NULLABLE",
"true", // "CASE_SENSITIVE",
"" + typeSearchable, // "SEARCHABLE",
"false", // "UNSIGNED_ATTRIBUTE",
"false", // "FIXED_PREC_SCALE",
"false", // "AUTO_INCREMENT",
DOCUMENT_TYPE_NAME, // "LOCAL_TYPE_NAME",
"0", // "MINIMUM_SCALE",
"0", // "MAXIMUM_SCALE",
null, // "SQL_DATA_TYPE", (not used)
null, // "SQL_DATETIME_SUB", (not used)
"10", // "NUM_PREC_RADIX" (javadoc says usually 2 or 10)
});
return retVal;
}
public <T> T unwrap(Class<T> iface) {
return null;
}
public boolean isWrapperFor(Class<?> iface) {
return false;
}
public boolean allProceduresAreCallable() {
return false;
}
public boolean allTablesAreSelectable() {
return false;
}
/**
* @see java.sql.DatabaseMetaData#getURL()
*/
public String getURL() {
return con.getUrl();
}
public String getUserName() {
return null;
}
public boolean isReadOnly() {
return false;
}
public boolean nullsAreSortedHigh() {
return false;
}
public boolean nullsAreSortedLow() {
return false;
}
public boolean nullsAreSortedAtStart() {
return false;
}
public boolean nullsAreSortedAtEnd() {
return false;
}
/**
* @see java.sql.DatabaseMetaData#getDatabaseProductName()
*/
public String getDatabaseProductName() {
return "Mongo DB";
}
/**
* @see java.sql.DatabaseMetaData#getDatabaseProductVersion()
*/
@NotNull
public String getDatabaseProductVersion() throws SQLException {
return con.getService().getVersion();
}
/**
* @see java.sql.DatabaseMetaData#getDriverName()
*/
public String getDriverName() {
return "MongoDB JDBC Driver";
}
/**
* @see java.sql.DatabaseMetaData#getDriverVersion()
*/
public String getDriverVersion() {
return "1.19";
}
/**
* @see java.sql.DatabaseMetaData#getDriverMajorVersion()
*/
public int getDriverMajorVersion() {
return 1;
}
/**
* @see java.sql.DatabaseMetaData#getDriverMinorVersion()
*/
public int getDriverMinorVersion() {
return 19;
}
public boolean usesLocalFiles() {
return false;
}
public boolean usesLocalFilePerTable() {
return false;
}
public boolean supportsMixedCaseIdentifiers() {
return false;
}
public boolean storesUpperCaseIdentifiers() {
return false;
}
public boolean storesLowerCaseIdentifiers() {
return false;
}
public boolean storesMixedCaseIdentifiers() {
return false;
}
public boolean supportsMixedCaseQuotedIdentifiers() {
return false;
}
public boolean storesUpperCaseQuotedIdentifiers() {
return false;
}
public boolean storesLowerCaseQuotedIdentifiers() {
return false;
}
public boolean storesMixedCaseQuotedIdentifiers() {
return false;
}
public String getIdentifierQuoteString() {
return null;
}
public String getSQLKeywords() {
return null;
}
public String getNumericFunctions() {
return null;
}
public String getStringFunctions() {
return null;
}
public String getSystemFunctions() {
return null;
}
public String getTimeDateFunctions() {
return "date";
}
public String getSearchStringEscape() {
return "\\";
}
public String getExtraNameCharacters() {
return null;
}
/**
* @see java.sql.DatabaseMetaData#supportsAlterTableWithAddColumn()
*/
public boolean supportsAlterTableWithAddColumn() {
return false;
}
/**
* @see java.sql.DatabaseMetaData#supportsAlterTableWithDropColumn()
*/
public boolean supportsAlterTableWithDropColumn() {
return false;
}
public boolean supportsColumnAliasing() {
return false;
}
public boolean nullPlusNonNullIsNull() {
return false;
}
public boolean supportsConvert() {
return false;
}
public boolean supportsConvert(int fromType, int toType) {
return false;
}
public boolean supportsTableCorrelationNames() {
return false;
}
public boolean supportsDifferentTableCorrelationNames() {
return false;
}
public boolean supportsExpressionsInOrderBy() {
return false;
}
public boolean supportsOrderByUnrelated() {
return false;
}
public boolean supportsGroupBy() {
return false;
}
public boolean supportsGroupByUnrelated() {
return false;
}
public boolean supportsGroupByBeyondSelect() {
return false;
}
public boolean supportsLikeEscapeClause() {
return true;
}
/**
* @see java.sql.DatabaseMetaData#supportsMultipleResultSets()
*/
public boolean supportsMultipleResultSets() {
return false;
}
/**
* @see java.sql.DatabaseMetaData#supportsMultipleTransactions()
*/
public boolean supportsMultipleTransactions() {
return false;
}
/**
* @see java.sql.DatabaseMetaData#supportsNonNullableColumns()
*/
public boolean supportsNonNullableColumns() {
return true;
}
/**
* @see java.sql.DatabaseMetaData#supportsMinimumSQLGrammar()
*/
public boolean supportsMinimumSQLGrammar() {
return false;
}
/**
* @see java.sql.DatabaseMetaData#supportsCoreSQLGrammar()
*/
public boolean supportsCoreSQLGrammar() {
return false;
}
/**
* @see java.sql.DatabaseMetaData#supportsExtendedSQLGrammar()
*/
public boolean supportsExtendedSQLGrammar() {
return false;
}
/**
* @see java.sql.DatabaseMetaData#supportsANSI92EntryLevelSQL()
*/
public boolean supportsANSI92EntryLevelSQL() {
return false;
}
/**
* @see java.sql.DatabaseMetaData#supportsANSI92IntermediateSQL()
*/
public boolean supportsANSI92IntermediateSQL() {
return false;
}
/**
* @see java.sql.DatabaseMetaData#supportsANSI92FullSQL()
*/
public boolean supportsANSI92FullSQL() {
return false;
}
/**
* @see java.sql.DatabaseMetaData#supportsIntegrityEnhancementFacility()
*/
public boolean supportsIntegrityEnhancementFacility() {
return false;
}
/**
* @see java.sql.DatabaseMetaData#supportsOuterJoins()
*/
public boolean supportsOuterJoins() {
return false;
}
/**
* @see java.sql.DatabaseMetaData#supportsFullOuterJoins()
*/
public boolean supportsFullOuterJoins() {
return false;
}
/**
* @see java.sql.DatabaseMetaData#supportsLimitedOuterJoins()
*/
public boolean supportsLimitedOuterJoins() {
return false;
}
/**
* @see java.sql.DatabaseMetaData#getSchemaTerm()
*/
public String getSchemaTerm() {
return null;
}
/**
* @see java.sql.DatabaseMetaData#getProcedureTerm()
*/
public String getProcedureTerm() {
return null;
}
/**
* @see java.sql.DatabaseMetaData#getCatalogTerm()
*/
public String getCatalogTerm() {
return "database";
}
/**
* @see java.sql.DatabaseMetaData#isCatalogAtStart()
*/
public boolean isCatalogAtStart() {
return true;
}
/**
* @see java.sql.DatabaseMetaData#getCatalogSeparator()
*/
public String getCatalogSeparator() {
return ".";
}
/**
* @see java.sql.DatabaseMetaData#supportsSchemasInDataManipulation()
*/
public boolean supportsSchemasInDataManipulation() {
return false;
}
/**
* @see java.sql.DatabaseMetaData#supportsSchemasInProcedureCalls()
*/
public boolean supportsSchemasInProcedureCalls() {
return false;
}
/**
* @see java.sql.DatabaseMetaData#supportsSchemasInTableDefinitions()
*/
public boolean supportsSchemasInTableDefinitions() {
return false;
}
/**
* @see java.sql.DatabaseMetaData#supportsSchemasInIndexDefinitions()
*/
public boolean supportsSchemasInIndexDefinitions() {
return false;
}
/**
* @see java.sql.DatabaseMetaData#supportsSchemasInPrivilegeDefinitions()
*/
public boolean supportsSchemasInPrivilegeDefinitions() {
return false;
}
/**
* @see java.sql.DatabaseMetaData#supportsCatalogsInDataManipulation()
*/
public boolean supportsCatalogsInDataManipulation() {
return true;
}
/**
* @see java.sql.DatabaseMetaData#supportsCatalogsInProcedureCalls()
*/
public boolean supportsCatalogsInProcedureCalls() {
return false;
}
/**
* @see java.sql.DatabaseMetaData#supportsCatalogsInTableDefinitions()
*/
public boolean supportsCatalogsInTableDefinitions() {
return false;
}
public boolean supportsCatalogsInIndexDefinitions() {
return false;
}
/**
* @see java.sql.DatabaseMetaData#supportsCatalogsInPrivilegeDefinitions()
*/
public boolean supportsCatalogsInPrivilegeDefinitions() {
return false;
}
/**
* @see java.sql.DatabaseMetaData#supportsPositionedDelete()
*/
public boolean supportsPositionedDelete() {
return false;
}
/**
* @see java.sql.DatabaseMetaData#supportsPositionedUpdate()
*/
public boolean supportsPositionedUpdate() {
return false;
}
/**
* @see java.sql.DatabaseMetaData#supportsSelectForUpdate()
*/
public boolean supportsSelectForUpdate() {
return false;
}
/**
* @see java.sql.DatabaseMetaData#supportsStoredProcedures()
*/
public boolean supportsStoredProcedures() {
return false;
}
public boolean supportsSubqueriesInComparisons() {
return false;
}
public boolean supportsSubqueriesInExists() {
return false;
}
public boolean supportsSubqueriesInIns() {
return false;
}
public boolean supportsSubqueriesInQuantifieds() {
return false;
}
public boolean supportsCorrelatedSubqueries() {
return false;
}
public boolean supportsUnion() {
return false;
}
public boolean supportsUnionAll() {
return false;
}
public boolean supportsOpenCursorsAcrossCommit() {
return false;
}
public boolean supportsOpenCursorsAcrossRollback() {
return false;
}
public boolean supportsOpenStatementsAcrossCommit() {
return false;
}
public boolean supportsOpenStatementsAcrossRollback() {
return false;
}
public int getMaxBinaryLiteralLength() {
return 0;
}
public int getMaxCharLiteralLength() {
return 0;
}
public int getMaxColumnNameLength() {
return 0;
}
public int getMaxColumnsInGroupBy() {
return 0;
}
public int getMaxColumnsInIndex() {
return 0;
}
public int getMaxColumnsInOrderBy() {
return 0;
}
public int getMaxColumnsInSelect() {
return 0;
}
public int getMaxColumnsInTable() {
return 0;
}
/**
* @see java.sql.DatabaseMetaData#getMaxConnections()
*/
public int getMaxConnections() {
return 0;
}
public int getMaxCursorNameLength() {
return 0;
}
public int getMaxIndexLength() {
return 0;
}
public int getMaxSchemaNameLength() {
return 0;
}
public int getMaxProcedureNameLength() {
return 0;
}
public int getMaxCatalogNameLength() {
return 0;
}
public int getMaxRowSize() {
return 0;
}
public boolean doesMaxRowSizeIncludeBlobs() {
return false;
}
public int getMaxStatementLength() {
return 0;
}
public int getMaxStatements() {
return 0;
}
/**
* @see java.sql.DatabaseMetaData#getMaxTableNameLength()
*/
public int getMaxTableNameLength() {
/*
* The maximum size of a collection name is 128 characters (including the name of the db and indexes).
* It is probably best to keep it under 80/90 chars.
*/
return 90;
}
/**
* @see java.sql.DatabaseMetaData#getMaxTablesInSelect()
*/
public int getMaxTablesInSelect() {
// MongoDB collections are represented as SQL tables in this driver. Mongo doesn't support joins.
return 1;
}
public int getMaxUserNameLength() {
return 0;
}
/**
* @see java.sql.DatabaseMetaData#getDefaultTransactionIsolation()
*/
public int getDefaultTransactionIsolation() {
return Connection.TRANSACTION_NONE;
}
/**
* MongoDB doesn't support transactions, but document updates are atomic.
*
* @see java.sql.DatabaseMetaData#supportsTransactions()
*/
public boolean supportsTransactions() {
return false;
}
/**
* @see java.sql.DatabaseMetaData#supportsTransactionIsolationLevel(int)
*/
public boolean supportsTransactionIsolationLevel(int level) {
return false;
}
/**
* @see java.sql.DatabaseMetaData#supportsDataDefinitionAndDataManipulationTransactions()
*/
public boolean supportsDataDefinitionAndDataManipulationTransactions() {
return false;
}
public boolean supportsDataManipulationTransactionsOnly() {
return false;
}
public boolean dataDefinitionCausesTransactionCommit() {
return false;
}
public boolean dataDefinitionIgnoredInTransactions() {
return false;
}
/**
* @see java.sql.DatabaseMetaData#getProcedures(java.lang.String, java.lang.String, java.lang.String)
*/
public ResultSet getProcedures(String catalogName, String schemaPattern, String procedureNamePattern) {
ListResultSet retVal = new ListResultSet();
retVal.setColumnNames("PROCEDURE_CAT", "PROCEDURE_SCHEMA", "PROCEDURE_NAME", "REMARKS",
"PROCEDURE_TYPE", "SPECIFIC_NAME");
return retVal;
}
/**
* @see java.sql.DatabaseMetaData#getProcedureColumns(java.lang.String, java.lang.String, java.lang.String,
* java.lang.String)
*/
@Override
public ResultSet getProcedureColumns(String catalogName, String schemaPattern, String procedureNamePattern,
String columnNamePattern) {
return empty();
}
private static ResultSet empty() {
return new ListResultSet();
}
/**
* @see java.sql.DatabaseMetaData#getTableTypes()
*/
@Override
public ResultSet getTableTypes() {
ListResultSet result = new ListResultSet();
result.addRow(new String[]{"COLLECTION"});
return result;
}
@Override
public ResultSet getColumnPrivileges(String catalogName, String schemaName, String table, String columnNamePattern) {
return null;
}
@Override
public ResultSet getTablePrivileges(String catalogName, String schemaPattern, String tableNamePattern) {
return null;
}
@Override
public ResultSet getBestRowIdentifier(String catalogName, String schemaName, String table, int scope,
boolean nullable) {
return null;
}
/**
* @see java.sql.DatabaseMetaData#getVersionColumns(java.lang.String, java.lang.String, java.lang.String)
*/
@Override
public ResultSet getVersionColumns(String catalogName, String schemaName, String table) {
return empty();
}
@Override
public ResultSet getExportedKeys(String catalogName, String schemaName, String tableNamePattern) {
return null;
}
/**
* @see java.sql.DatabaseMetaData#getExportedKeys(java.lang.String, java.lang.String, java.lang.String)
*/
@Override
public ResultSet getImportedKeys(String catalogName, String schemaName, String tableNamePattern) {
return null;
}
/**
* @see java.sql.DatabaseMetaData#getCrossReference(java.lang.String, java.lang.String, java.lang.String,
* java.lang.String, java.lang.String, java.lang.String)
*/
@Override
public ResultSet getCrossReference(String parentCatalog, String parentSchema, String parentTable,
String foreignCatalog, String foreignSchema, String foreignTable) {
return empty();
}
/**
* @see java.sql.DatabaseMetaData#supportsResultSetType(int)
*/
@Override
public boolean supportsResultSetType(int type) {
return type == ResultSet.TYPE_FORWARD_ONLY;
}
/**
* @see java.sql.DatabaseMetaData#supportsResultSetConcurrency(int, int)
*/
@Override
public boolean supportsResultSetConcurrency(int type, int concurrency) {
return false;
}
@Override
public boolean ownUpdatesAreVisible(int type) {
return false;
}
@Override
public boolean ownDeletesAreVisible(int type) {
return false;
}
@Override
public boolean ownInsertsAreVisible(int type) {
return false;
}
@Override
public boolean othersUpdatesAreVisible(int type) {
return false;
}
@Override
public boolean othersDeletesAreVisible(int type) {
return false;
}
@Override
public boolean othersInsertsAreVisible(int type) {
return false;
}
@Override
public boolean updatesAreDetected(int type) {
return false;
}
@Override
public boolean deletesAreDetected(int type) {
return false;
}
@Override
public boolean insertsAreDetected(int type) {
return false;
}
@Override
public boolean supportsBatchUpdates() {
return false;
}
/**
* @see java.sql.DatabaseMetaData#getUDTs(java.lang.String, java.lang.String, java.lang.String, int[])
*/
@Override
public ResultSet getUDTs(String catalogName, String schemaPattern, String typeNamePattern, int[] types) {
ListResultSet retVal = new ListResultSet();
retVal.setColumnNames("TYPE_CAT", "TYPE_SCHEM", "TYPE_NAME", "CLASS_NAME", "DATA_TYPE", "REMARKS", "BASE_TYPE");
return retVal;
}
/**
* @see java.sql.DatabaseMetaData#getConnection()
*/
@Override
public Connection getConnection() {
return con;
}
/**
* @see java.sql.DatabaseMetaData#supportsSavepoints()
*/
@Override
public boolean supportsSavepoints() {
return false;
}
@Override
public boolean supportsNamedParameters() {
return false;
}
/**
* @see java.sql.DatabaseMetaData#supportsMultipleOpenResults()
*/
@Override
public boolean supportsMultipleOpenResults() {
return false;
}
/**
* @see java.sql.DatabaseMetaData#supportsGetGeneratedKeys()
*/
@Override
public boolean supportsGetGeneratedKeys() {
return false;
}
/**
* @see java.sql.DatabaseMetaData#getSuperTypes(java.lang.String, java.lang.String, java.lang.String)
*/
@Override
public ResultSet getSuperTypes(String catalogName, String schemaPattern, String typeNamePattern) {
ListResultSet retVal = new ListResultSet();
retVal.setColumnNames("TYPE_CAT", "TYPE_SCHEM", "TYPE_NAME", "SUPERTYPE_CAT", "SUPERTYPE_SCHEM", "SUPERTYPE_NAME");
return retVal;
}
/**
* @see java.sql.DatabaseMetaData#getSuperTables(java.lang.String, java.lang.String, java.lang.String)
*/
@Override
public ResultSet getSuperTables(String catalogName, String schemaPattern, String tableNamePattern) {
ListResultSet retVal = new ListResultSet();
retVal.setColumnNames("TABLE_CAT", "TABLE_SCHEM", "TABLE_NAME", "SUPERTABLE_NAME");
return retVal;
}
/**
* @see java.sql.DatabaseMetaData#getAttributes(java.lang.String, java.lang.String, java.lang.String,
* java.lang.String)
*/
@Override
public ResultSet getAttributes(String catalogName, String schemaPattern, String typeNamePattern,
String attributeNamePattern) {
ListResultSet retVal = new ListResultSet();
retVal.setColumnNames("TYPE_CAT", "TYPE_SCHEM", "TYPE_NAME", "ATTR_NAME", "DATA_TYPE",
"ATTR_TYPE_NAME", "ATTR_SIZE", "DECIMAL_DIGITS", "NUM_PREC_RADIX", "NULLABLE", "REMARKS",
"ATTR_DEF", "SQL_DATA_TYPE", "SQL_DATETIME_SUB", "CHAR_OCTET_LENGTH", "ORDINAL_POSITION",
"IS_NULLABLE", "SCOPE_CATALOG", "SCOPE_SCHEMA", "SCOPE_TABLE", "SOURCE_DATA_TYPE");
return retVal;
}
/**
* @see java.sql.DatabaseMetaData#supportsResultSetHoldability(int)
*/
@Override
public boolean supportsResultSetHoldability(int holdability) {
return false;
}
/**
* @see java.sql.DatabaseMetaData#getResultSetHoldability()
*/
@Override
public int getResultSetHoldability() {
return ResultSet.HOLD_CURSORS_OVER_COMMIT;
}
/**
* @see java.sql.DatabaseMetaData#getDatabaseMajorVersion()
*/
@Override
public int getDatabaseMajorVersion() throws SQLException {
String version = getDatabaseProductVersion();
try {
String[] parts = version.split("\\.");
if (parts.length >= 1) return Integer.parseInt(parts[0]);
else {
System.err.println("WARNING: cannot extract major version from string: " + version);
}
}
catch (NumberFormatException e) {
e.printStackTrace();
}
return 0;
}
/**
* @see java.sql.DatabaseMetaData#getDatabaseMinorVersion()
*/
@Override
public int getDatabaseMinorVersion() throws SQLException {
String version = getDatabaseProductVersion();
try {
String[] parts = version.split("\\.");
if (parts.length >= 2) return Integer.parseInt(parts[1]);
else {
System.err.println("WARNING: cannot extract minor version from string: " + version);
}
}
catch (NumberFormatException e) {
e.printStackTrace();
}
return 0;
}
/**
* @see java.sql.DatabaseMetaData#getJDBCMajorVersion()
*/
@Override
public int getJDBCMajorVersion() {
return 4;
}
/**
* @see java.sql.DatabaseMetaData#getJDBCMinorVersion()
*/
@Override
public int getJDBCMinorVersion() {
return 2;
}
/**
* @see java.sql.DatabaseMetaData#getSQLStateType()
*/
@Override
public int getSQLStateType() {
return DatabaseMetaData.sqlStateXOpen;
}
@Override
public boolean locatorsUpdateCopy() {
return false;
}
/**
* @see java.sql.DatabaseMetaData#supportsStatementPooling()
*/
@Override
public boolean supportsStatementPooling() {
return false;
}
/**
* @see java.sql.DatabaseMetaData#getRowIdLifetime()
*/
@Override
public RowIdLifetime getRowIdLifetime() {
return null;
}
/**
* @see java.sql.DatabaseMetaData#getSchemas(java.lang.String, java.lang.String)
*/
@Override
public ResultSet getSchemas(String catalogName, String schemaPattern) throws SQLAlreadyClosedException {
List<String> mongoDbs = con.getService().getDatabaseNames();
ListResultSet retVal = new ListResultSet();
MongoNamePattern p = MongoNamePattern.create(schemaPattern);
retVal.setColumnNames("TABLE_SCHEM", "TABLE_CATALOG");
for (String mongoDb : mongoDbs) {
if (p.matches(mongoDb))
retVal.addRow(new String[]{mongoDb, DB_NAME});
}
return retVal;
}
/**
* @see java.sql.DatabaseMetaData#supportsStoredFunctionsUsingCallSyntax()
*/
@Override
public boolean supportsStoredFunctionsUsingCallSyntax() {
return false;
}
@Override
public boolean autoCommitFailureClosesAllResultSets() {
return false;
}
@Override
public ResultSet getClientInfoProperties() {
return null;
}
@Override
public ResultSet getFunctions(String catalogName, String schemaPattern, String functionNamePattern) {
return null;
}
@Override
public ResultSet getFunctionColumns(String catalogName, String schemaPattern, String functionNamePattern,
String columnNamePattern) {
return null;
}
@Override
public ResultSet getPseudoColumns(String catalogName, String schemaPattern, String tableNamePattern, String columnNamePattern) {
return null;
}
@Override
public boolean generatedKeyAlwaysReturned() {
return false;
}
}