Skip to content

LibreOfficeBase ResultSet metadata issues #202

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Aug 7, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion src/main/java/org/tarantool/Key.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@ public enum Key implements Callable<Integer> {
DATA(0x30),
ERROR(0x31),

SQL_FIELD_NAME(0),
SQL_FIELD_NAME(0x0),
SQL_FIELD_TYPE(0x1),

SQL_METADATA(0x32),
SQL_TEXT(0x40),
SQL_BIND(0x41),
Expand Down
45 changes: 39 additions & 6 deletions src/main/java/org/tarantool/SqlProtoUtils.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package org.tarantool;

import org.tarantool.jdbc.type.TarantoolSqlType;
import org.tarantool.jdbc.type.TarantoolType;
import org.tarantool.protocol.TarantoolPacket;

import java.util.ArrayList;
Expand Down Expand Up @@ -30,8 +32,11 @@ public static List<List<Object>> getSQLData(TarantoolPacket pack) {
public static List<SQLMetaData> getSQLMetadata(TarantoolPacket pack) {
List<Map<Integer, Object>> meta = (List<Map<Integer, Object>>) pack.getBody().get(Key.SQL_METADATA.getId());
List<SQLMetaData> values = new ArrayList<>(meta.size());
for (Map<Integer, Object> c : meta) {
values.add(new SQLMetaData((String) c.get(Key.SQL_FIELD_NAME.getId())));
for (Map<Integer, Object> item : meta) {
values.add(new SQLMetaData(
(String) item.get(Key.SQL_FIELD_NAME.getId()),
(String) item.get(Key.SQL_FIELD_TYPE.getId()))
);
}
return values;
}
Expand All @@ -46,21 +51,49 @@ public static Long getSqlRowCount(TarantoolPacket pack) {
}

public static class SQLMetaData {
protected String name;
private String name;
private TarantoolSqlType type;

public SQLMetaData(String name) {
/**
* Constructs new SQL metadata based on a raw Tarantool
* type.
*
* Tarantool returns a raw type instead of SQL one.
* This leads a type mapping ambiguity between raw and
* SQL types and a default SQL type will be chosen.
*
* @param name column name
* @param tarantoolType raw Tarantool type name
*
* @see TarantoolSqlType#getDefaultSqlType(TarantoolType)
*/
public SQLMetaData(String name, String tarantoolType) {
this(
name,
TarantoolSqlType.getDefaultSqlType(TarantoolType.of(tarantoolType))
);
}

public SQLMetaData(String name, TarantoolSqlType type) {
this.name = name;
this.type = type;
}

public String getName() {
return name;
}

public TarantoolSqlType getType() {
return type;
}

@Override
public String toString() {
return "SQLMetaData{" +
"name='" + name + '\'' +
'}';
"name='" + name + '\'' +
", type=" + type +
'}';
}

}
}
15 changes: 9 additions & 6 deletions src/main/java/org/tarantool/jdbc/SQLDatabaseMetadata.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

import org.tarantool.SqlProtoUtils;
import org.tarantool.Version;
import org.tarantool.jdbc.type.TarantoolSqlType;
import org.tarantool.util.TupleTwo;

import java.sql.Connection;
import java.sql.DatabaseMetaData;
Expand Down Expand Up @@ -1087,16 +1089,17 @@ public ResultSet getPseudoColumns(String catalog,
return asEmptyMetadataResultSet(DatabaseMetadataTable.PSEUDO_COLUMNS);
}

private ResultSet asMetadataResultSet(List<String> columnNames, List<List<Object>> rows) throws SQLException {
List<SqlProtoUtils.SQLMetaData> meta = columnNames.stream()
.map(SqlProtoUtils.SQLMetaData::new)
private ResultSet asMetadataResultSet(List<TupleTwo<String, TarantoolSqlType>> meta, List<List<Object>> rows)
throws SQLException {
List<SqlProtoUtils.SQLMetaData> sqlMeta = meta.stream()
.map(tuple -> new SqlProtoUtils.SQLMetaData(tuple.getFirst(), tuple.getSecond()))
.collect(Collectors.toList());
SQLResultHolder holder = SQLResultHolder.ofQuery(meta, rows);
SQLResultHolder holder = SQLResultHolder.ofQuery(sqlMeta, rows);
return createMetadataStatement().executeMetadata(holder);
}

private ResultSet asEmptyMetadataResultSet(List<String> columnNames) throws SQLException {
return asMetadataResultSet(columnNames, Collections.emptyList());
private ResultSet asEmptyMetadataResultSet(List<TupleTwo<String, TarantoolSqlType>> meta) throws SQLException {
return asMetadataResultSet(meta, Collections.emptyList());
}

@Override
Expand Down
8 changes: 7 additions & 1 deletion src/main/java/org/tarantool/jdbc/SQLPreparedStatement.java
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,13 @@ public void setArray(int parameterIndex, Array x) throws SQLException {

@Override
public ResultSetMetaData getMetaData() throws SQLException {
return getResultSet().getMetaData();
if (resultSet != null && !resultSet.isClosed()) {
return resultSet.getMetaData();
}
// XXX: it's required a support of dry-run mode to obtain
// a statement metadata without real query execution.
// see https://github.com/tarantool/tarantool/issues/3292
return null;
}

@Override
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/org/tarantool/jdbc/SQLResultSet.java
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ public class SQLResultSet implements ResultSet {
private final int holdability;

public SQLResultSet(SQLResultHolder holder, TarantoolStatement ownerStatement) throws SQLException {
metaData = new SQLResultSetMetaData(holder.getSqlMetadata());
metaData = new SQLResultSetMetaData(holder.getSqlMetadata(), ownerStatement.getConnection().isReadOnly());
statement = ownerStatement;
scrollType = statement.getResultSetType();
concurrencyLevel = statement.getResultSetConcurrency();
Expand Down
91 changes: 67 additions & 24 deletions src/main/java/org/tarantool/jdbc/SQLResultSetMetaData.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,17 @@

import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.sql.SQLNonTransientException;
import java.sql.Types;
import java.util.List;

public class SQLResultSetMetaData implements ResultSetMetaData {

private final List<SqlProtoUtils.SQLMetaData> sqlMetadata;
private final boolean readOnly;

public SQLResultSetMetaData(List<SqlProtoUtils.SQLMetaData> sqlMetaData) {
public SQLResultSetMetaData(List<SqlProtoUtils.SQLMetaData> sqlMetaData, boolean readOnly) {
this.sqlMetadata = sqlMetaData;
this.readOnly = readOnly;
}

@Override
Expand All @@ -25,37 +25,59 @@ public int getColumnCount() throws SQLException {

@Override
public boolean isAutoIncrement(int column) throws SQLException {
throw new SQLFeatureNotSupportedException();
checkColumnIndex(column);
// XXX: extra flag or, at least table ID is required in meta
// to be able to fetch an the flag indirectly.
return false;
}

@Override
public boolean isCaseSensitive(int column) throws SQLException {
throw new SQLFeatureNotSupportedException();
checkColumnIndex(column);
return sqlMetadata.get(column - 1).getType().isCaseSensitive();
}

/**
* {@inheritDoc}
* <p>
* All the types can be used in {@literal WHERE} clause.
*/
@Override
public boolean isSearchable(int column) throws SQLException {
throw new SQLFeatureNotSupportedException();
checkColumnIndex(column);
return true;
}

/**
* {@inheritDoc}
* <p>
* Always {@literal false} because
* Tarantool does not have monetary types.
*/
@Override
public boolean isCurrency(int column) throws SQLException {
throw new SQLFeatureNotSupportedException();
checkColumnIndex(column);
return false;
}

@Override
public int isNullable(int column) throws SQLException {
throw new SQLFeatureNotSupportedException();
checkColumnIndex(column);
// XXX: extra nullability flag or, at least table ID is required in meta
// to be able to fetch an the flag indirectly.
return ResultSetMetaData.columnNullableUnknown;
}

@Override
public boolean isSigned(int column) throws SQLException {
throw new SQLFeatureNotSupportedException();
checkColumnIndex(column);
return sqlMetadata.get(column - 1).getType().isSigned();
}

@Override
public int getColumnDisplaySize(int column) throws SQLException {
throw new SQLFeatureNotSupportedException();
checkColumnIndex(column);
return sqlMetadata.get(column - 1).getType().getDisplaySize();
}

@Override
Expand All @@ -64,6 +86,15 @@ public String getColumnLabel(int column) throws SQLException {
return sqlMetadata.get(column - 1).getName();
}

/**
* {@inheritDoc}
* <p>
* Name always has the same value as label
* because Tarantool does not differentiate
* column names and aliases.
*
* @see #getColumnLabel(int)
*/
@Override
public String getColumnName(int column) throws SQLException {
checkColumnIndex(column);
Expand All @@ -72,65 +103,77 @@ public String getColumnName(int column) throws SQLException {

@Override
public String getSchemaName(int column) throws SQLException {
return null;
checkColumnIndex(column);
return "";
}

@Override
public int getPrecision(int column) throws SQLException {
throw new SQLFeatureNotSupportedException();
checkColumnIndex(column);
return sqlMetadata.get(column - 1).getType().getPrecision();
}


@Override
public int getScale(int column) throws SQLException {
throw new SQLFeatureNotSupportedException();
checkColumnIndex(column);
return sqlMetadata.get(column - 1).getType().getScale();
}

@Override
public String getTableName(int column) throws SQLException {
throw new SQLFeatureNotSupportedException();
checkColumnIndex(column);
// XXX: extra table name or, at least table ID is required in meta
// to be able to fetch the table name.
return "";
}

@Override
public String getCatalogName(int column) throws SQLException {
return null;
checkColumnIndex(column);
return "";
}

@Override
public int getColumnType(int column) throws SQLException {
return Types.OTHER;
checkColumnIndex(column);
return sqlMetadata.get(column - 1).getType().getJdbcType().getTypeNumber();
}

@Override
public String getColumnTypeName(int column) throws SQLException {
return "scalar";
checkColumnIndex(column);
return sqlMetadata.get(column - 1).getType().getTypeName();
}

@Override
public boolean isReadOnly(int column) throws SQLException {
throw new SQLFeatureNotSupportedException();
checkColumnIndex(column);
return readOnly;
}

@Override
public boolean isWritable(int column) throws SQLException {
throw new SQLFeatureNotSupportedException();
return !isReadOnly(column);
}

@Override
public boolean isDefinitelyWritable(int column) throws SQLException {
throw new SQLFeatureNotSupportedException();
return false;
}

@Override
public String getColumnClassName(int column) throws SQLException {
throw new SQLFeatureNotSupportedException();
checkColumnIndex(column);
return sqlMetadata.get(column - 1).getType().getJdbcType().getJavaType().getName();
}

@Override
public <T> T unwrap(Class<T> type) throws SQLException {
if (isWrapperFor(type)) {
return type.cast(this);
}
throw new SQLNonTransientException("ResultSetMetadata does not wrap " + type.getName());
throw new SQLNonTransientException("SQLResultSetMetadata does not wrap " + type.getName());
}

@Override
Expand All @@ -150,7 +193,7 @@ void checkColumnIndex(int columnIndex) throws SQLException {
@Override
public String toString() {
return "SQLResultSetMetaData{" +
"sqlMetadata=" + sqlMetadata +
'}';
"sqlMetadata=" + sqlMetadata +
'}';
}
}
Loading