Skip to content

Commit

Permalink
[CALCITE-5982] Allow implementations of CalciteMeta to return extra c…
Browse files Browse the repository at this point in the history
…olumns in their responses to DatabaseMetaData.getTables and getColumns requests

A JDBC provider based on Calcite may wish to return extended
metadata. To accomplish this, we add parameters to the
CalciteMetaImpl whose types are the new interfaces
CalciteMetaTableFactory and CalciteMetaColumnFactory.

The default implementation of interface
CalciteMetaTableFactory returns a collection MetaTable
objects; an alternative implementation could return some
subclass that has extra columns, and those extra columns
will be carried through the Avatica RPC protocol and appear
in the ResultSet returned from DatabaseMetaData.getTables.
Similarly CalciteMetaColumnFactory and
DatabaseMetaData.getColumns.

Various fix-ups: (Julian Hyde)
* Make the CalciteMetaDataTableFactory and
  CalciteMetaColumnFactory parameters to the CalciteMetaImpl
  constructor mandatory;
* Add CalciteMetaImpl.create;
* Make CalciteMetaTableFactoryImpl and
  CalciteMetaColumnFactoryImpl singletons (with a protected
  constructor to allow subclassing);
* Rename factory methods ('newMetaColumn' to 'createColumn',
  'newMetaTable' to 'createTable');
* Convert some lambdas into functions.

Add a lint rule to ensure that the 'implements' keyword is
not at end of a line. (Julian Hyde)

Close #3421
  • Loading branch information
olivrlee authored and julianhyde committed Sep 27, 2023
1 parent 1245db6 commit 436ae7d
Show file tree
Hide file tree
Showing 13 changed files with 578 additions and 150 deletions.
1 change: 1 addition & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -605,6 +605,7 @@ allprojects {
replaceRegex("Method argument list should not end in whitespace or newline", "(?<!;)(\\s+)(\\)+)[.]", "$2$1.")
replaceRegex("Long assignment should be broken after '='", "^([^/*\"\\n]*) = ([^@\\n]*)\\(\n( *)", "$1 =\n$3$2(")
replaceRegex("Long assignment should be broken after '='", "^([^/*\"\\n]*) = ([^@\\n]*)\\((.*,)\n( *)", "$1 =\n$4$2($3 ")
replaceRegex("trailing keyword: implements", "^([^*]*) (implements)\\n( *)", "$1\n$3$2 ")
// Assume developer copy-pasted the link, and updated text only, so the url is old, and we replace it with the proper one
replaceRegex(">[CALCITE-...] link styles: 1", "<a(?:(?!CALCITE-)[^>])++CALCITE-\\d+[^>]++>\\s*+\\[?(CALCITE-\\d+)\\]?", "<a href=\"https://issues.apache.org/jira/browse/\$1\">[\$1]")
// If the link was crafted manually, ensure it has [CALCITE-...] in the link text
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,4 +110,16 @@ public interface CalciteConnectionConfig extends ConnectionConfig {
boolean lenientOperatorLookup();
/** Returns the value of {@link CalciteConnectionProperty#TOPDOWN_OPT}. */
boolean topDownOpt();

/** Returns the value of {@link CalciteConnectionProperty#META_TABLE_FACTORY},
* or a default meta table factory if not set. If
* {@code defaultMetaTableFactory} is not null, the result is never null. */
<T> @PolyNull T metaTableFactory(Class<T> metaTableFactoryClass,
@PolyNull T defaultMetaTableFactory);

/** Returns the value of {@link CalciteConnectionProperty#META_COLUMN_FACTORY},
* or a default meta column factory if not set. If
* {@code defaultMetaColumnFactory} is not null, the result is never null. */
<T> @PolyNull T metaColumnFactory(Class<T> metaColumnFactoryClass,
@PolyNull T defaultMetaColumnFactory);
}
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,21 @@ public boolean isSet(CalciteConnectionProperty property) {
}

@Override public boolean topDownOpt() {
return CalciteConnectionProperty.TOPDOWN_OPT.wrap(properties).getBoolean();
return CalciteConnectionProperty.TOPDOWN_OPT.wrap(properties)
.getBoolean();
}

@Override public <T> @PolyNull T metaTableFactory(
Class<T> metaTableFactoryClass,
@PolyNull T defaultMetaTableFactory) {
return CalciteConnectionProperty.META_TABLE_FACTORY.wrap(properties)
.getPlugin(metaTableFactoryClass, defaultMetaTableFactory);
}

@Override public <T> @PolyNull T metaColumnFactory(
Class<T> metaColumnFactoryClass,
@PolyNull T defaultMetaColumnFactory) {
return CalciteConnectionProperty.META_COLUMN_FACTORY.wrap(properties)
.getPlugin(metaColumnFactoryClass, defaultMetaColumnFactory);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,12 @@ public enum CalciteConnectionProperty implements ConnectionProperty {
* {@link org.apache.calcite.sql.parser.SqlParserImplFactory}. */
PARSER_FACTORY("parserFactory", Type.PLUGIN, null, false),

/** MetaTableFactory plugin. */
META_TABLE_FACTORY("metaTableFactory", Type.PLUGIN, null, false),

/** MetaColumnFactory plugin. */
META_COLUMN_FACTORY("metaColumnFactory", Type.PLUGIN, null, false),

/** Name of initial schema. */
SCHEMA("schema", Type.STRING, null, false),

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to you under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.calcite.jdbc;

import org.apache.calcite.avatica.MetaImpl.MetaColumn;
import org.apache.calcite.schema.Table;

import org.checkerframework.checker.nullness.qual.Nullable;

import java.util.List;

/** Factory for creating instances of {@link MetaColumn}.
*
* @see java.sql.DatabaseMetaData#getColumns */
public interface CalciteMetaColumnFactory {
/** Instantiates a MetaColumn. */
MetaColumn createColumn(Table table, String tableCat, String tableSchem,
String tableName, String columnName, int dataType, String typeName,
Integer columnSize, @Nullable Integer decimalDigits, int numPrecRadix,
int nullable, Integer charOctetLength, int ordinalPosition,
String isNullable);

/** Returns the list of expected column names.
*
* <p>The default implementation returns the columns described in the JDBC
* specification. */
default List<String> getColumnNames() {
return CalciteMetaImpl.COLUMN_COLUMNS;
}

/** Returns the type of object created. Must be a subclass of MetaColumn. */
Class<? extends MetaColumn> getMetaColumnClass();

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to you under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.calcite.jdbc;

import org.apache.calcite.avatica.MetaImpl.MetaColumn;
import org.apache.calcite.schema.Table;

import org.checkerframework.checker.nullness.qual.Nullable;

/** Default implementation of CalciteMetaColumnFactoryImpl. */
public class CalciteMetaColumnFactoryImpl
implements CalciteMetaColumnFactory {

/** Singleton instance. */
public static final CalciteMetaColumnFactoryImpl INSTANCE =
new CalciteMetaColumnFactoryImpl();

/** Internal constructor; protected to allow subclassing. */
protected CalciteMetaColumnFactoryImpl() {}

@Override public MetaColumn createColumn(
Table table,
String tableCat,
String tableSchem,
String tableName,
String columnName,
int dataType,
String typeName,
Integer columnSize,
@Nullable Integer decimalDigits,
int numPrecRadix,
int nullable,
Integer charOctetLength,
int ordinalPosition,
String isNullable) {
return new MetaColumn(
tableCat,
tableSchem,
tableName,
columnName,
dataType,
typeName,
columnSize,
decimalDigits,
numPrecRadix,
nullable,
charOctetLength,
ordinalPosition,
isNullable);
}

@Override public Class<? extends MetaColumn> getMetaColumnClass() {
return MetaColumn.class;
}
}
Loading

0 comments on commit 436ae7d

Please sign in to comment.