Skip to content
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
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
import java.sql.SQLException;
import java.sql.Types;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
Expand All @@ -30,7 +30,8 @@ public class LibsqlResultSetMetaData implements ResultSetMetaData {
private final LibsqlResultSet resultSet;

private boolean tableContextResolved;
private TableInfo tableContext;
private SqlTableReference.Resolution columnOrigins;
private final Map<String, TableInfo> tableInfoCache = new LinkedHashMap<>();

public LibsqlResultSetMetaData(List<Col> cols) {
this(cols, List.of(), null, null, null);
Expand Down Expand Up @@ -63,8 +64,7 @@ private Col getCol(int column) throws SQLException {

@Override
public boolean isAutoIncrement(int column) throws SQLException {
getCol(column);
TableInfo table = resolveTableContext();
TableInfo table = tableForColumn(column);
ColumnInfo info = table != null ? table.columns().get(columnName(column)) : null;
return info != null && info.primaryKey() && isAutoIncrementColumn(table.createSql(), columnName(column));
}
Expand Down Expand Up @@ -106,12 +106,14 @@ public boolean isCurrency(int column) throws SQLException {

@Override
public int isNullable(int column) throws SQLException {
getCol(column);
TableInfo table = resolveTableContext();
ColumnInfo info = table != null ? table.columns().get(columnName(column)) : null;
if (info == null) {
TableInfo table = tableForColumn(column);
if (table == null) {
return columnNullableUnknown;
}
ColumnInfo info = table.columns().get(columnName(column));
if (info == null) {
return columnNullable;
}
return info.notNull() ? columnNoNulls : columnNullable;
}

Expand Down Expand Up @@ -193,12 +195,8 @@ public int getScale(int column) throws SQLException {

@Override
public String getTableName(int column) throws SQLException {
getCol(column);
TableInfo table = resolveTableContext();
if (table == null || !table.columns().containsKey(columnName(column))) {
return "";
}
return table.name();
TableInfo table = tableForColumn(column);
return table != null ? table.name() : "";
}

@Override
Expand Down Expand Up @@ -423,19 +421,46 @@ private static SampleType storageType(Value value) {
return SampleType.NULL;
}

private TableInfo resolveTableContext() throws SQLException {
private TableInfo tableForColumn(int column) throws SQLException {
getCol(column);
SqlTableReference.TableRef reference = originTable(column);
return reference != null ? tableInfo(reference) : null;
}

private SqlTableReference.TableRef originTable(int column) throws SQLException {
SqlTableReference.Resolution resolution = resolveColumnOrigins();
return resolution != null ? resolution.table(column - 1) : null;
}

private SqlTableReference.Resolution resolveColumnOrigins() throws SQLException {
if (!tableContextResolved) {
TableInfo resolved = null;
SqlTableReference.Resolution resolved = null;
if (connection != null && sql != null) {
SqlTableReference.TableRef reference = SqlTableReference.parse(sql);
if (reference != null) {
resolved = loadTableInfo(reference);
}
}
tableContext = resolved;
resolved = SqlTableReference.resolve(sql, reference -> {
TableInfo info = tableInfo(reference);
if (info == null) {
return null;
}
return new SqlTableReference.TableDefinition(
info.createSql(), new ArrayList<>(info.columns().keySet()));
});
}
columnOrigins = resolved;
tableContextResolved = true;
}
return tableContext;
return columnOrigins;
}

private TableInfo tableInfo(SqlTableReference.TableRef reference) throws SQLException {
String schema = reference.schema() != null ? reference.schema().toLowerCase(Locale.ROOT) : "";
String table = reference.table() != null ? reference.table().toLowerCase(Locale.ROOT) : "";
String key = schema + "." + table;
if (tableInfoCache.containsKey(key)) {
return tableInfoCache.get(key);
}
TableInfo info = loadTableInfo(reference);
tableInfoCache.put(key, info);
return info;
}

private TableInfo loadTableInfo(SqlTableReference.TableRef reference) throws SQLException {
Expand All @@ -459,7 +484,8 @@ private TableInfo loadTableInfo(String schema, String table) throws SQLException
String master = schema.equals("temp") ? "sqlite_temp_master" : "sqlite_master";
String query = "SELECT m.name, m.sql, p.name, p.\"notnull\", p.pk "
+ "FROM " + master + " m JOIN pragma_table_info(?, ?) p "
+ "WHERE m.type IN ('table', 'view') AND m.name COLLATE NOCASE = ?";
+ "WHERE m.type IN ('table', 'view') AND m.name COLLATE NOCASE = ? "
+ "ORDER BY p.cid";
StmtResult result = connection.executeStatement(
new Stmt(query, List.of(Value.of(table), Value.of(schema), Value.of(table))));
return toTableInfo(result, table);
Expand All @@ -473,7 +499,8 @@ private TableInfo loadAttachedTableInfo(String schema, String table) throws SQLE
String quotedSchema = "\"" + actualSchema.replace("\"", "\"\"") + "\"";
String query = "SELECT m.name, m.sql, p.name, p.\"notnull\", p.pk "
+ "FROM " + quotedSchema + ".sqlite_master m JOIN pragma_table_info(?, ?) p "
+ "WHERE m.type IN ('table', 'view') AND m.name COLLATE NOCASE = ?";
+ "WHERE m.type IN ('table', 'view') AND m.name COLLATE NOCASE = ? "
+ "ORDER BY p.cid";
StmtResult result = connection.executeStatement(new Stmt(
query, List.of(Value.of(table), Value.of(actualSchema), Value.of(table))));
return toTableInfo(result, table);
Expand Down Expand Up @@ -504,7 +531,7 @@ private static TableInfo toTableInfo(StmtResult result, String fallbackName) {
}
String tableName = null;
String createSql = null;
Map<String, ColumnInfo> columns = new HashMap<>();
Map<String, ColumnInfo> columns = new LinkedHashMap<>();
for (Row row : result.rows()) {
List<Value> values = row.values();
if (values == null || values.size() < 5) {
Expand Down
Loading
Loading