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 @@ -8,7 +8,6 @@

import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Types;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
Expand Down Expand Up @@ -113,7 +112,7 @@ public boolean isSigned(int column) throws SQLException {
}
// An expression column has no declared type, so signedness follows the
// storage class of the current value, as xerial does.
return switch (storageType(runtimeValue(column))) {
return switch (XerialColumnType.storageClass(runtimeValue(column))) {
case INTEGER, FLOAT, NULL -> true;
case TEXT, BLOB -> false;
};
Expand Down Expand Up @@ -185,91 +184,7 @@ public int getColumnType(int column) throws SQLException {
getCol(column);
String typeName = getColumnTypeName(column);
Value value = runtimeValue(column);
SampleType valueType = storageType(value);

if (valueType == SampleType.INTEGER || valueType == SampleType.NULL) {
if ("BOOLEAN".equals(typeName)) {
return Types.BOOLEAN;
}
if ("TINYINT".equals(typeName)) {
return Types.TINYINT;
}
if ("SMALLINT".equals(typeName) || "INT2".equals(typeName)) {
return Types.SMALLINT;
}
if ("BIGINT".equals(typeName)
|| "INT8".equals(typeName)
|| "UNSIGNED BIG INT".equals(typeName)) {
return Types.BIGINT;
}
if ("DATE".equals(typeName)) {
return Types.DATE;
}
if ("DATETIME".equals(typeName) || "TIMESTAMP".equals(typeName)) {
return Types.TIMESTAMP;
}
if (valueType == SampleType.INTEGER
|| "INT".equals(typeName)
|| "INTEGER".equals(typeName)
|| "MEDIUMINT".equals(typeName)) {
long val = integer(value);
return val > Integer.MAX_VALUE || val < Integer.MIN_VALUE ? Types.BIGINT : Types.INTEGER;
}
}

if (valueType == SampleType.FLOAT || valueType == SampleType.NULL) {
if ("DECIMAL".equals(typeName)) {
return Types.DECIMAL;
}
if ("DOUBLE".equals(typeName) || "DOUBLE PRECISION".equals(typeName)) {
return Types.DOUBLE;
}
if ("NUMERIC".equals(typeName)) {
return Types.NUMERIC;
}
if ("REAL".equals(typeName)) {
return Types.REAL;
}
if (valueType == SampleType.FLOAT || "FLOAT".equals(typeName)) {
return Types.FLOAT;
}
}

if (valueType == SampleType.TEXT || valueType == SampleType.NULL) {
if ("CHARACTER".equals(typeName)
|| "NCHAR".equals(typeName)
|| "NATIVE CHARACTER".equals(typeName)
|| "CHAR".equals(typeName)) {
return Types.CHAR;
}
if ("CLOB".equals(typeName)) {
return Types.CLOB;
}
if ("DATE".equals(typeName)) {
return Types.DATE;
}
if ("DATETIME".equals(typeName) || "TIMESTAMP".equals(typeName)) {
return Types.TIMESTAMP;
}
if (valueType == SampleType.TEXT
|| "VARCHAR".equals(typeName)
|| "VARYING CHARACTER".equals(typeName)
|| "NVARCHAR".equals(typeName)
|| "TEXT".equals(typeName)) {
return Types.VARCHAR;
}
}

if (valueType == SampleType.BLOB || valueType == SampleType.NULL) {
if ("BINARY".equals(typeName)) {
return Types.BINARY;
}
if (valueType == SampleType.BLOB || "BLOB".equals(typeName)) {
return Types.BLOB;
}
}

return Types.NUMERIC;
return XerialColumnType.jdbcType(value, typeName);
}

@Override
Expand Down Expand Up @@ -305,23 +220,7 @@ public boolean isDefinitelyWritable(int column) throws SQLException {
@Override
public String getColumnClassName(int column) throws SQLException {
getCol(column);
return className(runtimeValue(column));
}

private static String className(Value value) {
if (value instanceof Value.Integer i) {
long val = i.value();
return val > Integer.MAX_VALUE || val < Integer.MIN_VALUE
? Long.class.getName()
: Integer.class.getName();
}
if (value instanceof Value.Float) {
return Double.class.getName();
}
if (value instanceof Value.Text) {
return String.class.getName();
}
return Object.class.getName();
return XerialColumnType.className(runtimeValue(column));
}

private String declType(int column) throws SQLException {
Expand Down Expand Up @@ -363,22 +262,6 @@ private Value sampleValue(int column) {
return null;
}

private static SampleType storageType(Value value) {
if (value instanceof Value.Integer) {
return SampleType.INTEGER;
}
if (value instanceof Value.Float) {
return SampleType.FLOAT;
}
if (value instanceof Value.Blob) {
return SampleType.BLOB;
}
if (value instanceof Value.Text) {
return SampleType.TEXT;
}
return SampleType.NULL;
}

private TableInfo tableForColumn(int column) throws SQLException {
getCol(column);
SqlTableReference.TableRef reference = originTable(column);
Expand Down Expand Up @@ -505,7 +388,9 @@ private static TableInfo toTableInfo(StmtResult result, String fallbackName) {
if (columnName != null) {
columns.put(
columnName.toLowerCase(Locale.ROOT),
new ColumnInfo(integer(values.get(3)) != 0, integer(values.get(4)) != 0));
new ColumnInfo(
XerialColumnType.integer(values.get(3)) != 0,
XerialColumnType.integer(values.get(4)) != 0));
}
}
return new TableInfo(tableName != null ? tableName : fallbackName, createSql, columns);
Expand All @@ -515,18 +400,6 @@ private static String text(Value value) {
return value instanceof Value.Text t ? t.value() : null;
}

private static long integer(Value value) {
return value instanceof Value.Integer i ? i.value() : 0L;
}

private enum SampleType {
INTEGER,
FLOAT,
BLOB,
TEXT,
NULL
}

private record ColumnInfo(boolean notNull, boolean primaryKey) {}

private record TableInfo(String name, String createSql, Map<String, ColumnInfo> columns) {}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
package com.github.magnusp.libsql.jdbc;

import com.github.magnusp.libsql.hrana.codec.Value;

import java.sql.Types;

/** xerial 3.53.4.0 column type mapping. */
final class XerialColumnType {

private XerialColumnType() {}

static int jdbcType(Value value, String typeName) {
StorageClass valueType = storageClass(value);

if (valueType == StorageClass.INTEGER || valueType == StorageClass.NULL) {
if ("BOOLEAN".equals(typeName)) {
return Types.BOOLEAN;
}
if ("TINYINT".equals(typeName)) {
return Types.TINYINT;
}
if ("SMALLINT".equals(typeName) || "INT2".equals(typeName)) {
return Types.SMALLINT;
}
if ("BIGINT".equals(typeName)
|| "INT8".equals(typeName)
|| "UNSIGNED BIG INT".equals(typeName)) {
return Types.BIGINT;
}
if ("DATE".equals(typeName)) {
return Types.DATE;
}
if ("DATETIME".equals(typeName) || "TIMESTAMP".equals(typeName)) {
return Types.TIMESTAMP;
}
if (valueType == StorageClass.INTEGER
|| "INT".equals(typeName)
|| "INTEGER".equals(typeName)
|| "MEDIUMINT".equals(typeName)) {
long val = integer(value);
return val > Integer.MAX_VALUE || val < Integer.MIN_VALUE ? Types.BIGINT : Types.INTEGER;
}
}

if (valueType == StorageClass.FLOAT || valueType == StorageClass.NULL) {
if ("DECIMAL".equals(typeName)) {
return Types.DECIMAL;
}
if ("DOUBLE".equals(typeName) || "DOUBLE PRECISION".equals(typeName)) {
return Types.DOUBLE;
}
if ("NUMERIC".equals(typeName)) {
return Types.NUMERIC;
}
if ("REAL".equals(typeName)) {
return Types.REAL;
}
if (valueType == StorageClass.FLOAT || "FLOAT".equals(typeName)) {
return Types.FLOAT;
}
}

if (valueType == StorageClass.TEXT || valueType == StorageClass.NULL) {
if ("CHARACTER".equals(typeName)
|| "NCHAR".equals(typeName)
|| "NATIVE CHARACTER".equals(typeName)
|| "CHAR".equals(typeName)) {
return Types.CHAR;
}
if ("CLOB".equals(typeName)) {
return Types.CLOB;
}
if ("DATE".equals(typeName)) {
return Types.DATE;
}
if ("DATETIME".equals(typeName) || "TIMESTAMP".equals(typeName)) {
return Types.TIMESTAMP;
}
if (valueType == StorageClass.TEXT
|| "VARCHAR".equals(typeName)
|| "VARYING CHARACTER".equals(typeName)
|| "NVARCHAR".equals(typeName)
|| "TEXT".equals(typeName)) {
return Types.VARCHAR;
}
}

if (valueType == StorageClass.BLOB || valueType == StorageClass.NULL) {
if ("BINARY".equals(typeName)) {
return Types.BINARY;
}
if (valueType == StorageClass.BLOB || "BLOB".equals(typeName)) {
return Types.BLOB;
}
}

return Types.NUMERIC;
}

static String className(Value value) {
if (value instanceof Value.Integer i) {
long val = i.value();
return val > Integer.MAX_VALUE || val < Integer.MIN_VALUE
? Long.class.getName()
: Integer.class.getName();
}
if (value instanceof Value.Float) {
return Double.class.getName();
}
if (value instanceof Value.Text) {
return String.class.getName();
}
return Object.class.getName();
}

static StorageClass storageClass(Value value) {
if (value instanceof Value.Integer) {
return StorageClass.INTEGER;
}
if (value instanceof Value.Float) {
return StorageClass.FLOAT;
}
if (value instanceof Value.Blob) {
return StorageClass.BLOB;
}
if (value instanceof Value.Text) {
return StorageClass.TEXT;
}
return StorageClass.NULL;
}

static long integer(Value value) {
return value instanceof Value.Integer i ? i.value() : 0L;
}

enum StorageClass {
INTEGER,
FLOAT,
BLOB,
TEXT,
NULL
}
}
Loading