[jOOQ/jOOQ#9791] Meta.getTables() returns the same table for each catalog in SQL Server

This commit is contained in:
Lukas Eder 2020-02-05 13:48:17 +01:00
parent 1418586753
commit 808d3c7ae1

View File

@ -160,7 +160,7 @@ final class MetaImpl extends AbstractMeta {
super(configuration);
this.databaseMetaData = databaseMetaData;
this.inverseSchemaCatalog = INVERSE_SCHEMA_CATALOG.contains(configuration.family());
this.inverseSchemaCatalog = INVERSE_SCHEMA_CATALOG.contains(family());
}
private interface MetaFunction {
@ -291,6 +291,12 @@ final class MetaImpl extends AbstractMeta {
@Override
public Result<Record> run(DatabaseMetaData meta) throws SQLException {
return dsl().fetch(
meta.getSchemas(),
// [#2681] Work around a flaw in the MySQL JDBC driver
@ -346,7 +352,7 @@ final class MetaImpl extends AbstractMeta {
public Result<Record> run(DatabaseMetaData meta) throws SQLException {
String[] types = null;
switch (configuration.family()) {
switch (family()) {
// [#3977] PostgreSQL returns other object types, too
@ -384,13 +390,15 @@ final class MetaImpl extends AbstractMeta {
if (!inverseSchemaCatalog)
rs = meta.getTables(null, getName(), "%", types);
// [#2760] MySQL JDBC confuses "catalog" and "schema"
else
else if (inverseSchemaCatalog)
rs = meta.getTables(getName(), null, "%", types);
else
rs = meta.getTables(null, getName(), "%", types);
return dsl().fetch(
rs,
@ -409,11 +417,7 @@ final class MetaImpl extends AbstractMeta {
String schema = table.get(1, String.class);
String name = table.get(2, String.class);
// [#2760] MySQL JDBC confuses "catalog" and "schema"
result.add(new MetaTable(name, this, getColumns(
inverseSchemaCatalog ? catalog : schema,
name
)));
result.add(new MetaTable(name, this, getColumns(catalog, schema, name)));
// TODO: Find a more efficient way to do this
// Result<Record> pkColumns = executor.fetch(meta().getPrimaryKeys(catalog, schema, name))
@ -426,50 +430,52 @@ final class MetaImpl extends AbstractMeta {
}
@SuppressWarnings("unchecked")
private final Result<Record> getColumns(String schema, String table) {
private final Result<Record> getColumns(String catalog, String schema, String table) {
// SQLite JDBC's DatabaseMetaData.getColumns() can only return a single
// table's columns
if (columnCache == null && configuration.family() != SQLITE) {
Result<Record> columns = getColumns0(schema, "%");
if (columnCache == null && family() != SQLITE) {
Result<Record> columns = getColumns0(catalog, schema, "%");
Field<String> tableCat = (Field<String>) columns.field(0); // TABLE_CAT
Field<String> tableSchem = (Field<String>) columns.field(1); // TABLE_SCHEM
Field<String> tableName = (Field<String>) columns.field(2); // TABLE_NAME
Map<Record, Result<Record>> groups =
columns.intoGroups(new Field[] {
inverseSchemaCatalog ? tableCat : tableSchem,
tableName
});
Map<Record, Result<Record>> groups = columns.intoGroups(new Field[] { tableCat, tableSchem, tableName });
columnCache = new LinkedHashMap<>();
for (Entry<Record, Result<Record>> entry : groups.entrySet()) {
Record key = entry.getKey();
Result<Record> value = entry.getValue();
columnCache.put(name(key.get(inverseSchemaCatalog ? tableCat : tableSchem), key.get(tableName)), value);
columnCache.put(name(key.get(tableCat), key.get(tableSchem), key.get(tableName)), value);
}
}
if (columnCache != null)
return columnCache.get(name(schema, table));
return columnCache.get(name(catalog, schema, table));
else
return getColumns0(schema, table);
return getColumns0(catalog, schema, table);
}
private final Result<Record> getColumns0(final String schema, final String table) {
private final Result<Record> getColumns0(final String catalog, final String schema, final String table) {
return meta(new MetaFunction() {
@Override
public Result<Record> run(DatabaseMetaData meta) throws SQLException {
ResultSet rs;
if (!inverseSchemaCatalog)
// [#2760] MySQL JDBC confuses "catalog" and "schema"
if (inverseSchemaCatalog)
rs = meta.getColumns(catalog, null, table, "%");
else
rs = meta.getColumns(null, schema, table, "%");
// [#2760] MySQL JDBC confuses "catalog" and "schema"
else
rs = meta.getColumns(schema, null, table, "%");
// Work around a bug in the SQL Server JDBC driver by
// coercing data types to the expected types
@ -571,13 +577,19 @@ final class MetaImpl extends AbstractMeta {
public Result<Record> run(DatabaseMetaData meta) throws SQLException {
ResultSet rs;
if (!inverseSchemaCatalog)
rs = meta.getIndexInfo(null, schema, getName(), false, true);
// [#2760] MySQL JDBC confuses "catalog" and "schema"
else
if (inverseSchemaCatalog)
rs = meta.getIndexInfo(schema, null, getName(), false, true);
else
rs = meta.getIndexInfo(null, schema, getName(), false, true);
return dsl().fetch(
rs,
String.class, // TABLE_CAT
@ -610,7 +622,6 @@ final class MetaImpl extends AbstractMeta {
@Override
public final UniqueKey<Record> getPrimaryKey() {
SQLDialect family = configuration.family();
@ -623,13 +634,19 @@ final class MetaImpl extends AbstractMeta {
public Result<Record> run(DatabaseMetaData meta) throws SQLException {
ResultSet rs;
if (!inverseSchemaCatalog)
rs = meta.getPrimaryKeys(null, schema, getName());
// [#2760] MySQL JDBC confuses "catalog" and "schema"
else
if (inverseSchemaCatalog)
rs = meta.getPrimaryKeys(schema, null, getName());
else
rs = meta.getPrimaryKeys(null, schema, getName());
return dsl().fetch(
rs,
String.class, // TABLE_CAT
@ -765,7 +782,7 @@ final class MetaImpl extends AbstractMeta {
f[i] = (TableField<Record, ?>) field(name);
// [#5097] Work around a bug in the Xerial JDBC driver for SQLite
if (f[i] == null && configuration.family() == SQLITE)
if (f[i] == null && family() == SQLITE)
// [#2656] Use native support for case-insensitive column
// lookup, once this is implemented
@ -844,7 +861,7 @@ final class MetaImpl extends AbstractMeta {
// TODO: Exception handling should be moved inside SQLDataType
DataType type = null;
try {
type = DefaultDataType.getDataType(configuration.family(), typeName, precision, scale);
type = DefaultDataType.getDataType(family(), typeName, precision, scale);
// JDBC doesn't distinguish between precision and length
type = type.precision(precision, scale);
@ -859,11 +876,11 @@ final class MetaImpl extends AbstractMeta {
try {
// [#7194] Some databases report all default values as expressions, not as values
if (EXPRESSION_COLUMN_DEFAULT.contains(configuration.family()))
if (EXPRESSION_COLUMN_DEFAULT.contains(family()))
type = type.defaultValue(DSL.field(defaultValue, type));
// [#5574] MySQL mixes constant value expressions with other column expressions here
else if (CURRENT_TIMESTAMP_COLUMN_DEFAULT.contains(configuration.family()) && "CURRENT_TIMESTAMP".equalsIgnoreCase(defaultValue))
else if (CURRENT_TIMESTAMP_COLUMN_DEFAULT.contains(family()) && "CURRENT_TIMESTAMP".equalsIgnoreCase(defaultValue))
type = type.defaultValue(DSL.field(defaultValue, type));
else
type = type.defaultValue(DSL.inline(defaultValue, type));