Skip to content

Postgresql 15 Array Type Support #1732

Closed
@nichts12

Description

@nichts12

error:

2023-08-28 18:51:12,984 ERROR [io.qua.ver.htt.run.QuarkusErrorHandler] (vert.x-eventloop-thread-0) HTTP Request to /request failed, error id: 1dea0f53-6add-4099-b03c-df768780ea1d-1: org.hibernate.HibernateException: Unable to extract JDBC value for position `4`
	at org.hibernate.reactive.sql.exec.spi.ReactiveValuesResultSet.lambda$readCurrentRowValues$2(ReactiveValuesResultSet.java:148)
	at java.base/java.util.concurrent.CompletableFuture.uniApplyNow(CompletableFuture.java:684)
	at java.base/java.util.concurrent.CompletableFuture.uniApplyStage(CompletableFuture.java:662)
	at java.base/java.util.concurrent.CompletableFuture.thenApply(CompletableFuture.java:2168)
	at java.base/java.util.concurrent.CompletableFuture.thenApply(CompletableFuture.java:144)
	at org.hibernate.reactive.sql.exec.spi.ReactiveValuesResultSet.readCurrentRowValues(ReactiveValuesResultSet.java:139)
	at java.base/java.util.concurrent.CompletableFuture$UniCompose.tryFire(CompletableFuture.java:1150)
	at java.base/java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:510)
	at java.base/java.util.concurrent.CompletableFuture.complete(CompletableFuture.java:2147)
	at io.vertx.core.Future.lambda$toCompletionStage$3(Future.java:536)
	at io.vertx.core.impl.future.FutureImpl$3.onSuccess(FutureImpl.java:141)
	at io.vertx.core.impl.future.FutureBase.emitSuccess(FutureBase.java:60)
	at io.vertx.core.impl.future.FutureImpl.tryComplete(FutureImpl.java:211)
	at io.vertx.core.impl.future.PromiseImpl.tryComplete(PromiseImpl.java:23)
	at io.vertx.sqlclient.impl.QueryResultBuilder.tryComplete(QueryResultBuilder.java:88)
	at io.vertx.sqlclient.impl.QueryResultBuilder.tryComplete(QueryResultBuilder.java:32)
	at io.vertx.core.Promise.complete(Promise.java:66)
	at io.vertx.core.Promise.handle(Promise.java:51)
	at io.vertx.core.Promise.handle(Promise.java:29)
	at io.vertx.core.impl.future.FutureImpl$3.onSuccess(FutureImpl.java:141)
	at io.vertx.core.impl.future.FutureBase.lambda$emitSuccess$0(FutureBase.java:54)
	at io.netty.util.concurrent.AbstractEventExecutor.runTask(AbstractEventExecutor.java:174)
	at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:167)
	at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:470)
	at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:569)
	at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:997)
	at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
	at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
	at java.base/java.lang.Thread.run(Thread.java:833)
Caused by: java.lang.UnsupportedOperationException
	at org.hibernate.reactive.adaptor.impl.ResultSetAdaptor.getArray(ResultSetAdaptor.java:732)
	at cn.holmescraft.wahr.jelly.sticker.config.PostgreSqlStringArrayType.nullSafeGet(PostgreSqlStringArrayType.java:40)
	at cn.holmescraft.wahr.jelly.sticker.config.PostgreSqlStringArrayType.nullSafeGet(PostgreSqlStringArrayType.java:11)
	at org.hibernate.type.internal.UserTypeSqlTypeAdapter$ValueExtractorImpl.extract(UserTypeSqlTypeAdapter.java:110)
	at org.hibernate.reactive.sql.exec.spi.ReactiveValuesResultSet.lambda$readCurrentRowValues$2(ReactiveValuesResultSet.java:145)
	... 28 more

sql:

create table tb_note
(
    id           bigserial
        primary key,
    user_id      bigint                  not null,
    title        varchar(20)             not null,
    content      text,
    tag        varchar(255)[],
);

user type impl:

import org.hibernate.HibernateException;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.usertype.UserType;

import java.io.Serializable;
import java.sql.*;
import java.util.Arrays;

public class PostgreSqlStringArrayType implements UserType {

    @Override
    public int getSqlType() {
        return Types.ARRAY;
    }

    @Override
    public Class returnedClass() {
        return String[].class;
    }

    @Override
    public boolean equals(Object x, Object y) throws HibernateException {
        if (x instanceof String[] && y instanceof String[]) {
            return Arrays.deepEquals((String[]) x, (String[]) y);
        } else {
            return false;
        }
    }

    @Override
    public int hashCode(Object x) throws HibernateException {
        return Arrays.hashCode((String[]) x);
    }

    @Override
    public String[] nullSafeGet(ResultSet rs, int position, SharedSessionContractImplementor session,
                                Object owner) throws SQLException {
        Array array = rs.getArray(position);
        return array != null ? (String[]) array.getArray() : null;
    }


    @Override
    public void nullSafeSet(PreparedStatement st, Object value, int index, SharedSessionContractImplementor session)
            throws HibernateException, SQLException {
        if (value != null && st != null) {
            Array array = session.getJdbcConnectionAccess().obtainConnection()
                    .createArrayOf("varchar", (String[]) value);
            st.setArray(index, array);
        } else {
            st.setNull(index, getSqlType());
        }
    }

    @Override
    public Object deepCopy(Object value) throws HibernateException {
        String[] a = (String[]) value;
        return Arrays.copyOf(a, a.length);
    }

    @Override
    public boolean isMutable() {
        return false;
    }

    @Override
    public Serializable disassemble(Object value) throws HibernateException {
        return (Serializable) value;
    }

    @Override
    public Object assemble(Serializable cached, Object owner) throws HibernateException {
        return cached;
    }

    @Override
    public Object replace(Object original, Object target, Object owner) throws HibernateException {
        return original;
    }

}

entity:

...
@Type(PostgreSqlStringArrayType::class)
//    @JdbcTypeCode(SqlTypes.ARRAY)
    @Column(columnDefinition = "varchar(255)[]")
    private String[] tag;
...

I implemented UserType and hoped to get Array type data through ResultSet, but this method directly returned an exception.

This is ResultSetAdaptor class source:

...


	@Override
	public Array getArray(int columnIndex) {
		throw new UnsupportedOperationException();
	}


...

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions