[ https://issues.apache.org/jira/browse/CALCITE-4708?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17935308#comment-17935308 ]
Artem Simeshin commented on CALCITE-4708: ----------------------------------------- [~mbudiu] Im sure that talking about the same problem as Vladimir! At the moment ReflectiveSchema does not support List and other Iterables, Arrays only. >If your proposed solution, does not affect public APIs, what is the downside? I dont see any real downsides, but Im personally a bit confused, because there is already possible support, that does not work at all, but why that lines were coded? Can correctly deduce a class type for Iterables break any other functionality? [https://github.com/apache/calcite/blob/main/core/src/main/java/org/apache/calcite/adapter/java/ReflectiveSchema.java#L224] {code:java} if (Iterable.class.isAssignableFrom(clazz)) { return Object.class; } {code} >Do you plan to submit a PR? Sure! > Infer list generic type while Table instance is created at ReflectiveSchema > class > --------------------------------------------------------------------------------- > > Key: CALCITE-4708 > URL: https://issues.apache.org/jira/browse/CALCITE-4708 > Project: Calcite > Issue Type: Improvement > Components: core > Affects Versions: 1.27.0 > Environment: Ubuntu 18.04 > Java 11 > Maven 3.6.0 > Reporter: Vladimir Polukeev > Priority: Major > Labels: pull-request-available > Time Spent: 10m > Remaining Estimate: 0h > > I have such code: > {code:java} > // > public class Main { > public static void main(String[] args) throws SQLException { > // 1. Create calcite connection > Properties info = new Properties(); > info.setProperty("lex", "JAVA"); > try(Connection connection = > DriverManager.getConnection("jdbc:calcite:", info)) { > Employee employee1 = new Employee("first name 1", "last name 1"); > Employee employee2 = new Employee("first name 2", "last name 2"); > Employee employee3 = new Employee("first name 3", "last name 3"); > > > List<Employee> employeeList = new LinkedList<>(); > employeeList.add(employee1); > employeeList.add(employee2); > employeeList.add(employee3); > MyScheme myScheme = new MyScheme(); > myScheme.employees = employeeList; > Schema schema = new ReflectiveSchema(myScheme); > // 2. add scheme with data to root scheme > CalciteConnection calciteConnection = > connection.unwrap(CalciteConnection.class); > SchemaPlus rootSchema = calciteConnection.getRootSchema(); > rootSchema.add("cache", schema); > // 3. execute sql query against scheme > String sql = "select e.* from cache.employees e"; > ResultSet resultSet = > calciteConnection.createStatement().executeQuery(sql); > > // 4. read data from result set > while (resultSet.next()) { > printValues(resultSet); > } > } > } > public static class MyScheme { > public List<Employee> employees; > } > @AllArgsConstructor > public static class Employee { > public String firstName; > public String lastName; > } > public static void printValues(ResultSet resultSet) throws SQLException { > System.out.println("--------------- row " + resultSet.getRow() + " > ---------------"); > ResultSetMetaData metaData = resultSet.getMetaData(); > for (int i = 1; i <= metaData.getColumnCount(); i++) { > String columnName = metaData.getColumnName(i); > System.out.println(columnName + " : " + > resultSet.getObject(columnName)); > } > } > } > {code} > > Code execution output: > {noformat} > --------------- row 1 --------------- > --------------- row 2 --------------- > --------------- row 3 ---------------{noformat} > > Calcite correctly gets 3 rows, but there is no information about columns at > output due to item class at Iterable collection infer as Object.class. Here > is code from ReflectiveSchema.class: > > {code:java} > // > private static @Nullable Type getElementType(Class clazz) { > if (clazz.isArray()) { > return clazz.getComponentType(); > } > if (Iterable.class.isAssignableFrom(clazz)) { > return Object.class; > } > return null; // not a collection/array/iterable > } > {code} > > > Information about columns is retured If I change List<Employee> to Employee[] > at MyScheme.class. But I have to use List due to my task requirement. > I manage this issue such way: > Java compiler erise information about generic type at compile time. Therefore > I supply information about class using annotation > org.apache.calcite.adapter.java.Array: > {code:java} > // > public static class MyScheme { > + @Array(component = Employee.class) > public List<Employee> employees; > } > {code} > Than I read element type from annotation at runtime. Here is code from > improved ReflectiveSchema.class: > {code:java} > // > private <T> @Nullable Table fieldRelation(final Field field) { > + Array arrayAnnotation = field.getAnnotation(Array.class); > + Class<?> elementListClass = arrayAnnotation != null ? > arrayAnnotation.component() : null; > + final Type elementType = getElementType(field.getType(), > elementListClass); > ... // redundant method code is omitted > } > {code} > Finally, I return type according to information retrieved from Array > annotation: > {code:java} > // > + private static @Nullable Type getElementType(Class clazz, Class<?> > elementListClass) { > if (clazz.isArray()) { > return clazz.getComponentType(); > } > if (Iterable.class.isAssignableFrom(clazz)) { > + return elementListClass != null ? elementListClass : Object.class; > } > return null; // not a collection/array/iterable > } > {code} > > Now, code execution output: > {noformat} > --------------- row 1 --------------- > firstName : first name 1 > lastName : last name 1 > --------------- row 2 --------------- > firstName : first name 2 > lastName : last name 2 > --------------- row 3 --------------- > firstName : first name 3 > lastName : last name 3{noformat} > > Does such improvement fit to framework design? Can I create pull request in > order to make such improvement? -- This message was sent by Atlassian Jira (v8.20.10#820010)