Skip to content

Commit 7ef469d

Browse files
committed
Properly downcast unsigned OID to Integer.
We now downcast unsigned OIDs to integer to avoid exceptions during reading OIDs. [resolves #470] Signed-off-by: Mark Paluch <[email protected]>
1 parent c5aab66 commit 7ef469d

File tree

4 files changed

+65
-17
lines changed

4 files changed

+65
-17
lines changed

src/main/java/io/r2dbc/postgresql/codec/BuiltinDynamicCodecs.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ public Publisher<Void> register(PostgresqlConnection connection, ByteBufAllocato
7777
return statement.execute()
7878
.flatMap(it -> it.map((row, rowMetadata) -> {
7979

80-
Integer oid = row.get("oid", Integer.class);
80+
int oid = PostgresqlObjectId.toInt(row.get("oid", Long.class));
8181
String typname = row.get("typname", String.class);
8282

8383
BuiltinCodec lookup = BuiltinCodec.lookup(typname);

src/main/java/io/r2dbc/postgresql/codec/PostgresTypes.java

+37-10
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,11 @@ public Mono<PostgresType> lookupType(String typeName) {
7474

7575
return this.connection.createStatement(String.format(SELECT_PG_TYPE, "=", "'" + typeName + "'", "LIMIT 1")).execute()
7676
.flatMap(it -> it.map((row, rowMetadata) -> {
77-
return new PostgresType(row.get("oid", Integer.class), row.get("typarray", Integer.class), row.get("typname", String.class), row.get("typcategory", String.class));
77+
78+
Long oid = row.get("oid", Long.class);
79+
Long typarrayOid = row.get("typarray", Long.class);
80+
return new PostgresType(PostgresqlObjectId.toInt(oid), oid.longValue(), PostgresqlObjectId.toInt(typarrayOid), typarrayOid, row.get("typname", String.class), row.get("typcategory",
81+
String.class));
7882
})).singleOrEmpty();
7983
}
8084

@@ -93,26 +97,36 @@ public Flux<PostgresType> lookupTypes(Iterable<String> typeNames) {
9397

9498
return this.connection.createStatement(String.format(SELECT_PG_TYPE, "IN", joiner, "")).execute()
9599
.flatMap(it -> it.map((row, rowMetadata) -> {
96-
return new PostgresType(row.get("oid", Integer.class), row.get("typarray", Integer.class), row.get("typname", String.class), row.get("typcategory", String.class));
100+
101+
Long oid = row.get("oid", Long.class);
102+
Long typarrayOid = row.get("typarray", Long.class);
103+
return new PostgresType(PostgresqlObjectId.toInt(oid), oid.longValue(), PostgresqlObjectId.toInt(typarrayOid), typarrayOid, row.get("typname", String.class), row.get("typcategory",
104+
String.class));
97105
}));
98106
}
99107

100108
public static class PostgresType implements Type, PostgresTypeIdentifier {
101109

102110
private final int oid;
103111

112+
private final long unsignedOid;
113+
104114
private final int typarray;
105115

116+
private final long unsignedTyparray;
117+
106118
private final String name;
107119

108120
private final String category;
109121

110122
@Nullable
111123
private final PostgresqlObjectId objectId;
112124

113-
public PostgresType(int oid, int typarray, String name, String category) {
125+
public PostgresType(int oid, long unsignedOid, int typarray, long unsignedTyparray, String name, String category) {
114126
this.oid = oid;
127+
this.unsignedOid = unsignedOid;
115128
this.typarray = typarray;
129+
this.unsignedTyparray = unsignedTyparray;
116130
this.name = name;
117131
this.category = category;
118132
this.objectId = PostgresqlObjectId.isValid(oid) ? PostgresqlObjectId.valueOf(oid) : null;
@@ -123,10 +137,6 @@ public int getObjectId() {
123137
return getOid();
124138
}
125139

126-
public int getArrayObjectId() {
127-
return this.typarray;
128-
}
129-
130140
/**
131141
* Return the type as array type.
132142
*
@@ -140,7 +150,7 @@ public PostgresType asArrayType() {
140150

141151
if (this.typarray > 0) {
142152

143-
return new PostgresType(this.typarray, this.typarray, this.name, this.category);
153+
return new PostgresType(this.typarray, this.unsignedTyparray, this.typarray, this.unsignedTyparray, this.name, this.category);
144154
}
145155

146156
throw new IllegalStateException("No array type available for " + this);
@@ -155,7 +165,18 @@ public Class<?> getJavaType() {
155165
return this.objectId != null ? this.objectId.getJavaType() : Object.class;
156166
}
157167

158-
@Override
168+
public int getArrayObjectId() {
169+
return this.typarray;
170+
}
171+
172+
public long getUnsignedObjectId() {
173+
return this.unsignedOid;
174+
}
175+
176+
public long getUnsignedArrayObjectId() {
177+
return this.unsignedTyparray;
178+
}
179+
159180
public String getName() {
160181
return this.name;
161182
}
@@ -268,19 +289,25 @@ public boolean equals(Object o) {
268289
}
269290
PostgresType that = (PostgresType) o;
270291
return this.oid == that.oid &&
292+
this.unsignedOid == that.unsignedOid &&
293+
this.typarray == that.typarray &&
294+
this.unsignedTyparray == that.unsignedTyparray &&
271295
Objects.equals(this.name, that.name) &&
272296
Objects.equals(this.category, that.category);
273297
}
274298

275299
@Override
276300
public int hashCode() {
277-
return Objects.hash(this.oid, this.name, this.category);
301+
return Objects.hash(this.oid, this.unsignedOid, this.typarray, this.unsignedTyparray, this.name, this.category);
278302
}
279303

280304
@Override
281305
public String toString() {
282306
return "PostgresType{" +
283307
"oid=" + this.oid +
308+
"unsignedOid=" + this.unsignedOid +
309+
"typarray=" + this.typarray +
310+
"unsignedTyparray=" + this.unsignedTyparray +
284311
", name='" + this.name + '\'' +
285312
", category='" + this.category + '\'' +
286313
'}';

src/main/java/io/r2dbc/postgresql/codec/PostgresqlObjectId.java

+21
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@
3131
import java.time.OffsetDateTime;
3232
import java.time.OffsetTime;
3333

34+
import io.r2dbc.postgresql.util.Assert;
35+
import reactor.util.annotation.Nullable;
36+
3437
/**
3538
* Object IDs for well know PostgreSQL data types.
3639
* <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}.
@@ -573,4 +576,22 @@ public int getObjectId() {
573576
return this.objectId;
574577
}
575578

579+
public static int toInt(@Nullable Long oid) {
580+
Assert.requireNonNull(oid, "OID must not be null");
581+
582+
return toInt(oid.longValue());
583+
}
584+
585+
public static int toInt(long oid) {
586+
if ((oid & 0xFFFFFFFF00000000L) != 0) {
587+
throw new IllegalArgumentException("Value is not an OID:" + oid);
588+
}
589+
590+
return (int) oid;
591+
}
592+
593+
public static long toLong(int oid) {
594+
return Integer.toUnsignedLong(oid);
595+
}
596+
576597
}

src/test/java/io/r2dbc/postgresql/codec/EnumCodecUnitTests.java

+6-6
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,8 @@ void shouldRegisterCodecAsFirst() {
9797
MockPostgresqlStatement mockPostgresqlStatement = MockPostgresqlStatement.builder()
9898
.result(MockPostgresqlResult.builder()
9999
.row(MockRow.builder()
100-
.identified("oid", Integer.class, 42)
101-
.identified("typarray", Integer.class, 0)
100+
.identified("oid", Long.class, 42L)
101+
.identified("typarray", Long.class, 0L)
102102
.identified("typname", String.class, "foo")
103103
.identified("typcategory", String.class, "E")
104104
.build())
@@ -128,14 +128,14 @@ void shouldRegisterCodecAsLast() {
128128
MockPostgresqlStatement mockPostgresqlStatement = MockPostgresqlStatement.builder()
129129
.result(MockPostgresqlResult.builder()
130130
.row(MockRow.builder()
131-
.identified("oid", Integer.class, 42)
132-
.identified("typarray", Integer.class, 0)
131+
.identified("oid", Long.class, 42L)
132+
.identified("typarray", Long.class, 0L)
133133
.identified("typname", String.class, "foo")
134134
.identified("typcategory", String.class, "E")
135135
.build())
136136
.row(MockRow.builder()
137-
.identified("oid", Integer.class, 43)
138-
.identified("typarray", Integer.class, 0)
137+
.identified("oid", Long.class, 43L)
138+
.identified("typarray", Long.class, 0L)
139139
.identified("typname", String.class, "bar")
140140
.identified("typcategory", String.class, "E")
141141
.build())

0 commit comments

Comments
 (0)