All Downloads are FREE. Search and download functionalities are using the official Maven repository.

dev.miku.r2dbc.mysql.MySqlColumnMetadata Maven / Gradle / Ivy

/*
 * Copyright 2018-2020 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package dev.miku.r2dbc.mysql;

import dev.miku.r2dbc.mysql.codec.FieldInformation;
import dev.miku.r2dbc.mysql.collation.CharCollation;
import dev.miku.r2dbc.mysql.constant.ColumnDefinitions;
import dev.miku.r2dbc.mysql.constant.DataTypes;
import dev.miku.r2dbc.mysql.message.server.DefinitionMetadataMessage;
import io.r2dbc.spi.ColumnMetadata;
import io.r2dbc.spi.Nullability;
import reactor.util.annotation.NonNull;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.Objects;

import static dev.miku.r2dbc.mysql.util.AssertUtils.require;
import static dev.miku.r2dbc.mysql.util.AssertUtils.requireNonNull;

/**
 * An implementation of {@link ColumnMetadata} for MySQL database.
 * 

* Note: same as parameter metadata in MySQL, but parameter metadata is useless for the SPI of R2DBC. */ final class MySqlColumnMetadata implements ColumnMetadata, FieldInformation { private final int index; private final short type; private final String name; private final short definitions; private final Nullability nullability; private final long size; private final int decimals; private final int collationId; private MySqlColumnMetadata(int index, short type, String name, short definitions, boolean nonNull, long size, int decimals, int collationId) { require(index >= 0, "index must not be a negative integer"); require(size >= 0, "size must not be a negative integer"); require(decimals >= 0, "decimals must not be a negative integer"); requireNonNull(name, "name must not be null"); require(collationId > 0, "collationId must be a positive integer"); this.index = index; this.type = type; this.name = name; this.definitions = definitions; if (nonNull) { this.nullability = Nullability.NON_NULL; } else { this.nullability = Nullability.NULLABLE; } this.size = size; this.decimals = decimals; this.collationId = collationId; } static MySqlColumnMetadata create(int index, DefinitionMetadataMessage message) { short definitions = message.getDefinitions(); return new MySqlColumnMetadata( index, message.getType(), message.getColumn(), definitions, (definitions & ColumnDefinitions.NOT_NULL) != 0, message.getSize(), message.getDecimals(), message.getCollationId() ); } int getIndex() { return index; } public short getType() { return type; } public short getDefinitions() { return definitions; } @Override public Class getJavaType() { switch (type) { case DataTypes.DECIMAL: case DataTypes.NEW_DECIMAL: return BigDecimal.class; case DataTypes.TINYINT: if ((definitions & ColumnDefinitions.UNSIGNED) != 0) { return Short.class; } else { return Byte.class; } case DataTypes.SMALLINT: if ((definitions & ColumnDefinitions.UNSIGNED) != 0) { return Integer.class; } else { return Short.class; } case DataTypes.INT: if ((definitions & ColumnDefinitions.UNSIGNED) != 0) { return Long.class; } else { return Integer.class; } case DataTypes.FLOAT: return Float.class; case DataTypes.DOUBLE: return Double.class; case DataTypes.TIMESTAMP: case DataTypes.DATETIME: case DataTypes.TIMESTAMP2: return LocalDateTime.class; case DataTypes.BIGINT: if ((definitions & ColumnDefinitions.UNSIGNED) != 0) { return BigInteger.class; } else { return Long.class; } case DataTypes.MEDIUMINT: return Integer.class; case DataTypes.DATE: return LocalDate.class; case DataTypes.TIME: return LocalTime.class; case DataTypes.YEAR: // MySQL return 2-bytes in binary result for type YEAR. return Short.class; case DataTypes.VARCHAR: case DataTypes.JSON: case DataTypes.ENUMERABLE: case DataTypes.VARBINARY: case DataTypes.STRING: case DataTypes.TINY_BLOB: case DataTypes.MEDIUM_BLOB: case DataTypes.LONG_BLOB: case DataTypes.BLOB: if (collationId == CharCollation.BINARY_ID) { return ByteBuffer.class; } else { return String.class; } case DataTypes.BIT: return ByteBuffer.class; case DataTypes.GEOMETRY: // Most of Geometry libraries were using byte[] to encode/decode which based on WKT (includes Extended-WKT) or WKB // MySQL using WKB for encoding/decoding, so use byte[] instead of ByteBuffer by default type. // It maybe change after R2DBC SPI specify default type for GEOMETRY. return byte[].class; case DataTypes.SET: return String[].class; default: return null; } } @Override public String getName() { return name; } public Integer getNativeTypeMetadata() { return (int) type; } @Override public Nullability getNullability() { return nullability; } @NonNull @Override public Integer getPrecision() { return (int) size; } @Override public long getSize() { return size; } @Override public Integer getScale() { // 0x00 means it is an integer or a static string. // 0x1f means it is a dynamic string, an original-double or an original-float. // 0x00 to 0x51 for the number of digits to right of the decimal point. if (type == DataTypes.DECIMAL || type == DataTypes.NEW_DECIMAL || type == DataTypes.DOUBLE || type == DataTypes.FLOAT) { if (decimals >= 0 && decimals <= 0x51) { return decimals; } } return null; } public int getCollationId() { return collationId; } @Override public boolean equals(Object o) { if (this == o) { return true; } if (!(o instanceof MySqlColumnMetadata)) { return false; } MySqlColumnMetadata metadata = (MySqlColumnMetadata) o; return index == metadata.index && type == metadata.type && definitions == metadata.definitions && size == metadata.size && decimals == metadata.decimals && collationId == metadata.collationId && name.equals(metadata.name) && nullability == metadata.nullability; } @Override public int hashCode() { return Objects.hash(index, type, name, definitions, nullability, size, decimals, collationId); } @Override public String toString() { return String.format("MySqlColumnMetadata{index=%d, type=%d, name='%s', definitions=%x, nullability=%s, size=%d, decimals=%d, collationId=%d}", index, type, name, definitions, nullability, size, decimals, collationId); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy