ProtoJdbi.java

package net.morimekta.proto.jdbi;

import com.google.protobuf.Descriptors;
import net.morimekta.proto.ProtoField;
import net.morimekta.proto.jdbi.MorimektaJdbiOptions.SqlType;
import net.morimekta.strings.StringUtil;

import java.sql.Types;

public class ProtoJdbi {
    /**
     * Get the default enum name from an enum value descriptor.
     *
     * @param value The enum value descriptor.
     * @return The enum value name.
     */
    public static String getDefaultEnumName(Descriptors.EnumValueDescriptor value) {
        var name = value.getOptions().getExtension(MorimektaJdbiOptions.sqlName);
        if (StringUtil.isNotEmpty(name)) {
            return name;
        }
        return value.getName();
    }

    /**
     * Get the default column name from a field descriptor.
     *
     * @param field The field descriptor.
     * @return The column name.
     */
    public static String getDefaultColumnName(Descriptors.FieldDescriptor field) {
        var name = field.getOptions().getExtension(MorimektaJdbiOptions.sqlColumn);
        if (StringUtil.isNotEmpty(name)) {
            return name;
        }
        return field.getName();
    }

    /**
     * Get the default column SQL type from a field descriptor.
     *
     * @param field The field descriptor.
     * @return The column SQL type.
     */
    public static SqlType getDefaultColumnType(Descriptors.FieldDescriptor field) {
        var type = field.getOptions().getExtension(MorimektaJdbiOptions.sqlType);
        if (type != SqlType.UNSPECIFIED) {
            return type;
        }
        if (field.isRepeated()) {
            throw new IllegalArgumentException(
                    "No default column type for " + ProtoField.toString(field));
        }
        switch (field.getType()) {
            case BOOL:
                return SqlType.BIT;
            case INT32:
            case UINT32:
            case SINT32:
            case FIXED32:
            case SFIXED32:
            case ENUM:
                return SqlType.INTEGER;
            case INT64:
            case UINT64:
            case SINT64:
            case FIXED64:
            case SFIXED64:
                return SqlType.BIGINT;
            case FLOAT:
                return SqlType.FLOAT;
            case DOUBLE:
                return SqlType.DOUBLE;
            case STRING:
                return SqlType.VARCHAR;
            case BYTES:
                return SqlType.VARBINARY;
            case MESSAGE: // Binary serialized message.
                if (field.getMessageType().equals(com.google.protobuf.Timestamp.getDescriptor())) {
                    // Default is timestamp as Timestamp UTC.
                    return SqlType.TIMESTAMP;
                }
                if (field.getMessageType().equals(com.google.protobuf.Duration.getDescriptor())) {
                    // default is duration in seconds and fractional seconds (decimal notation).
                    return SqlType.DECIMAL;
                }
                return SqlType.BLOB;
            default: {
                throw new IllegalArgumentException(
                        "No default column type for " +
                        field.getType() +
                        " field " +
                        field.getContainingType().getFullName() +
                        "#" +
                        field.getFullName());
            }
        }
    }

    /**
     * Map a java SQL type value to the proto SQL type enum. See
     * {@link java.sql.SQLType} for valid values.
     *
     * @param sqlType The java SQL type.
     * @return The proto SQL type.
     */
    public static SqlType getSqlType(int sqlType) {
        switch (sqlType) {
            case Types.BIT:
                return SqlType.BIT;
            case Types.TINYINT:
                return SqlType.TINYINT;
            case Types.SMALLINT:
                return SqlType.SMALLINT;
            case Types.INTEGER:
                return SqlType.INTEGER;
            case Types.BIGINT:
                return SqlType.BIGINT;
            case Types.FLOAT:
                return SqlType.FLOAT;
            case Types.REAL:
                return SqlType.REAL;
            case Types.DOUBLE:
                return SqlType.DOUBLE;
            case Types.NUMERIC:
                return SqlType.NUMERIC;
            case Types.DECIMAL:
                return SqlType.DECIMAL;
            case Types.CHAR:
                return SqlType.CHAR;
            case Types.VARCHAR:
                return SqlType.VARCHAR;
            case Types.LONGVARCHAR:
                return SqlType.LONG_VARCHAR;
            case Types.DATE:
                return SqlType.DATE;
            case Types.TIME:
                return SqlType.TIME;
            case Types.TIMESTAMP:
                return SqlType.TIMESTAMP;
            case Types.BINARY:
                return SqlType.BINARY;
            case Types.VARBINARY:
                return SqlType.VARBINARY;
            case Types.LONGVARBINARY:
                return SqlType.LONG_VARBINARY;
            case Types.NULL:
                return SqlType.UNSPECIFIED;
                // case Types.OTHER:
                // case Types.JAVA_OBJECT:
                // case Types.DISTINCT:
                // case Types.STRUCT:
                // case Types.ARRAY:
            case Types.BLOB:
                return SqlType.BLOB;
            case Types.CLOB:
                return SqlType.CLOB;
                // case Types.REF:
                // case Types.DATALINK:
            case Types.BOOLEAN:
                return SqlType.BOOLEAN;
                // case Types.ROWID:
            case Types.NCHAR:
                return SqlType.NCHAR;
            case Types.NVARCHAR:
                return SqlType.NVARCHAR;
            case Types.LONGNVARCHAR:
                return SqlType.LONG_NVARCHAR;
            case Types.NCLOB:
                return SqlType.NCLOB;
                // case Types.SQLXML:
                // case Types.REF_CURSOR:
            case Types.TIME_WITH_TIMEZONE:
                return SqlType.TIME_WITH_TIMEZONE;
            case Types.TIMESTAMP_WITH_TIMEZONE:
                return SqlType.TIMESTAMP_WITH_TIMEZONE;
            default:
                return SqlType.UNRECOGNIZED;
        }
    }

    /**
     * Get {@link java.sql.SQLType} column type for a proto SQL type enum value.
     *
     * @param type The proto SQL type.
     * @return The java SQL type.
     */
    public static int getColumnType(SqlType type) {
        if (type == null) {
            return Types.NULL;
        }
        switch (type) {
            case BIT:
                return Types.BIT;
            case TINYINT:
                return Types.TINYINT;
            case SMALLINT:
                return Types.SMALLINT;
            case INTEGER:
                return Types.INTEGER;
            case BIGINT:
                return Types.BIGINT;
            case FLOAT:
                return Types.FLOAT;
            case REAL:
                return Types.REAL;
            case DOUBLE:
                return Types.DOUBLE;
            case NUMERIC:
                return Types.NUMERIC;
            case DECIMAL:
                return Types.DECIMAL;
            case CHAR:
                return Types.CHAR;
            case VARCHAR:
                return Types.VARCHAR;
            case LONG_VARCHAR:
                return Types.LONGVARCHAR;
            case DATE:
                return Types.DATE;
            case TIME:
                return Types.TIME;
            case TIMESTAMP:
                return Types.TIMESTAMP;
            case BINARY:
                return Types.BINARY;
            case VARBINARY:
                return Types.VARBINARY;
            case LONG_VARBINARY:
                return Types.LONGVARBINARY;
            case BLOB:
                return Types.BLOB;
            case CLOB:
                return Types.CLOB;
            case BOOLEAN:
                return Types.BOOLEAN;
            case NCHAR:
                return Types.NCHAR;
            case NVARCHAR:
                return Types.NVARCHAR;
            case LONG_NVARCHAR:
                return Types.LONGNVARCHAR;
            case NCLOB:
                return Types.NCLOB;
            case TIME_WITH_TIMEZONE:
                return Types.TIME_WITH_TIMEZONE;
            case TIMESTAMP_WITH_TIMEZONE:
                return Types.TIMESTAMP_WITH_TIMEZONE;
            case UNSPECIFIED:
                return Types.NULL;
            default:
                throw new IllegalArgumentException("Unrecognized SQL type: " + type);
        }
    }
}