Skip to content

Commit

Permalink
Properly downcast unsigned OID to Integer.
Browse files Browse the repository at this point in the history
We now downcast unsigned OIDs to integer to avoid exceptions during reading OIDs.

[resolves #470]

Signed-off-by: Mark Paluch <[email protected]>
  • Loading branch information
mp911de committed Nov 22, 2021
1 parent 3d30064 commit 92de4b0
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ T decodeNumber(ByteBuf buffer, PostgresqlObjectId dataType, @Nullable Format for
public Iterable<PostgresqlObjectId> getDataTypes() {
return SUPPORTED_TYPES;
}

/**
* Returns the {@link PostgresqlObjectId} for to identify whether this codec is the default codec.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import io.r2dbc.postgresql.api.PostgresqlConnection;
import io.r2dbc.postgresql.api.PostgresqlStatement;
import io.r2dbc.postgresql.extension.CodecRegistrar;
import io.r2dbc.postgresql.type.PostgresqlObjectId;
import org.reactivestreams.Publisher;
import reactor.util.annotation.Nullable;

Expand Down Expand Up @@ -77,8 +78,8 @@ public Publisher<Void> register(PostgresqlConnection connection, ByteBufAllocato
return statement.execute()
.flatMap(it -> it.map((row, rowMetadata) -> {

Integer oid = row.get("oid", Integer.class);
String typname = row.get("typname", String.class);
int oid = PostgresqlObjectId.toInt(row.get("oid", Long.class));
String typname = row.get("typname", String.class);

BuiltinCodec lookup = BuiltinCodec.lookup(typname);
registry.addLast(lookup.createCodec(byteBufAllocator, oid));
Expand Down
27 changes: 24 additions & 3 deletions src/main/java/io/r2dbc/postgresql/codec/PostgresTypes.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package io.r2dbc.postgresql.codec;

import io.r2dbc.postgresql.api.PostgresqlConnection;
import io.r2dbc.postgresql.type.PostgresqlObjectId;
import io.r2dbc.postgresql.util.Assert;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
Expand Down Expand Up @@ -72,7 +73,9 @@ public Mono<PostgresType> lookupType(String typeName) {

return this.connection.createStatement(String.format(SELECT_PG_TYPE, "=", "'" + typeName + "'", "LIMIT 1")).execute()
.flatMap(it -> it.map((row, rowMetadata) -> {
return new PostgresType(row.get("oid", Integer.class), row.get("typname", String.class), row.get("typcategory", String.class));

Long oid = row.get("oid", Long.class);
return new PostgresType(PostgresqlObjectId.toInt(oid), oid.longValue(), row.get("typname", String.class), row.get("typcategory", String.class));
})).singleOrEmpty();
}

Expand All @@ -91,7 +94,9 @@ public Flux<PostgresType> lookupTypes(Iterable<String> typeNames) {

return this.connection.createStatement(String.format(SELECT_PG_TYPE, "IN", joiner, "")).execute()
.flatMap(it -> it.map((row, rowMetadata) -> {
return new PostgresType(row.get("oid", Integer.class), row.get("typname", String.class), row.get("typcategory", String.class));

Long oid = row.get("oid", Long.class);
return new PostgresType(PostgresqlObjectId.toInt(oid), oid.longValue(), row.get("typname", String.class), row.get("typcategory", String.class));
}));

}
Expand All @@ -100,12 +105,22 @@ public static class PostgresType {

private final int oid;

private final long unsignedOid;

private final String name;

private final String category;

public PostgresType(int oid, String name, String category) {
this.oid = oid;
this.unsignedOid = oid;
this.name = name;
this.category = category;
}

public PostgresType(int oid, long unsignedOid, String name, String category) {
this.oid = oid;
this.unsignedOid = unsignedOid;
this.name = name;
this.category = category;
}
Expand All @@ -114,6 +129,10 @@ public int getOid() {
return this.oid;
}

public long getUnsignedOid() {
return this.unsignedOid;
}

public String getName() {
return this.name;
}
Expand Down Expand Up @@ -226,19 +245,21 @@ public boolean equals(Object o) {
}
PostgresType that = (PostgresType) o;
return this.oid == that.oid &&
this.unsignedOid == that.unsignedOid &&
Objects.equals(this.name, that.name) &&
Objects.equals(this.category, that.category);
}

@Override
public int hashCode() {
return Objects.hash(this.oid, this.name, this.category);
return Objects.hash(this.oid, this.unsignedOid, this.name, this.category);
}

@Override
public String toString() {
return "PostgresType{" +
"oid=" + this.oid +
"unsignedOid=" + this.unsignedOid +
", name='" + this.name + '\'' +
", category='" + this.category + '\'' +
'}';
Expand Down
21 changes: 21 additions & 0 deletions src/main/java/io/r2dbc/postgresql/type/PostgresqlObjectId.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@

package io.r2dbc.postgresql.type;

import io.r2dbc.postgresql.util.Assert;
import reactor.util.annotation.Nullable;

/**
* Object IDs for well know PostgreSQL data types.
* <p>Extension Object IDs that are provided by Postgres extensions such as PostGIS are not constants of this enumeration and must be looked up from {@code pg_type}.
Expand Down Expand Up @@ -436,4 +439,22 @@ public int getObjectId() {
return this.objectId;
}

public static int toInt(@Nullable Long oid) {
Assert.requireNonNull(oid, "OID must not be null");

return toInt(oid.longValue());
}

public static int toInt(long oid) {
if ((oid & 0xFFFFFFFF00000000L) != 0) {
throw new IllegalArgumentException("Value is not an OID:" + oid);
}

return (int) oid;
}

public static long toLong(int oid) {
return Integer.toUnsignedLong(oid);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ void shouldRegisterCodecAsFirst() {
.result(MockPostgresqlResult.builder()
.rowMetadata(MockRowMetadata.empty())
.row(MockRow.builder()
.identified("oid", Integer.class, 42)
.identified("oid", Long.class, 42L)
.identified("typname", String.class, "foo")
.identified("typcategory", String.class, "E")
.build())
Expand Down Expand Up @@ -130,12 +130,12 @@ void shouldRegisterCodecAsLast() {
.result(MockPostgresqlResult.builder()
.rowMetadata(MockRowMetadata.empty())
.row(MockRow.builder()
.identified("oid", Integer.class, 42)
.identified("oid", Long.class, 42L)
.identified("typname", String.class, "foo")
.identified("typcategory", String.class, "E")
.build())
.row(MockRow.builder()
.identified("oid", Integer.class, 43)
.identified("oid", Long.class, 43L)
.identified("typname", String.class, "bar")
.identified("typcategory", String.class, "E")
.build())
Expand Down

0 comments on commit 92de4b0

Please sign in to comment.