-
-
Notifications
You must be signed in to change notification settings - Fork 336
/
PostgresPlugin.java
170 lines (161 loc) · 7.65 KB
/
PostgresPlugin.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
/*
* 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 org.jdbi.v3.postgres;
import java.sql.Connection;
import java.util.Map;
import java.util.UUID;
import org.jdbi.v3.core.Handle;
import org.jdbi.v3.core.Jdbi;
import org.jdbi.v3.core.argument.ArgumentFactory;
import org.jdbi.v3.core.generic.GenericType;
import org.jdbi.v3.core.internal.JdbiClassUtils;
import org.jdbi.v3.core.internal.exceptions.Unchecked;
import org.jdbi.v3.core.spi.JdbiPlugin;
import org.jdbi.v3.postgres.internal.BitStringEnumSetArgumentFactory;
import org.jdbi.v3.postgres.internal.BitStringEnumSetMapperFactory;
import org.postgresql.PGConnection;
import org.postgresql.geometric.PGbox;
import org.postgresql.geometric.PGcircle;
import org.postgresql.geometric.PGline;
import org.postgresql.geometric.PGlseg;
import org.postgresql.geometric.PGpath;
import org.postgresql.geometric.PGpoint;
import org.postgresql.geometric.PGpolygon;
import org.postgresql.util.PGInterval;
import org.postgresql.util.PGmoney;
/**
* Postgres plugin. Adds support for binding and mapping the following data types:
*
* <ul>
* <li>{@link java.net.InetAddress} (including {@link java.net.Inet4Address} and {@link java.net.Inet6Address})</li>
* <li>{@link java.time.LocalDate}</li>
* <li>{@link java.time.LocalTime}</li>
* <li>{@link java.time.LocalDateTime}</li>
* <li>{@link java.time.OffsetDateTime}</li>
* <li>{@link java.time.Duration} (see notes below)</li>
* <li>{@link java.time.Period} (see notes below)</li>
* <li>{@link java.util.Map Map<String, String>} (for {@code HSTORE} columns)</li>
* <li>{@link java.util.UUID}</li>
* <li>{@link java.io.InputStream} and {@link java.io.Reader} from {@code oid} large object columns</li>
* </ul>
*
* <p>
* The following qualified types have {@link org.jdbi.v3.meta.Beta} support for binding and mapping:
*
* <ul>
* <li>{@link MacAddr @MacAddr java.lang.String} (for MACADDR columns)</li>
* <li>{@link HStore @HStore Map<String, String>} (for HSTORE columns)</li>
* </ul>
*
* <p>
* Also sets up SQL array support for the following types:
*
* <ul>
* <li>{@code double}</li>
* <li>{@code float}</li>
* <li>{@code int}</li>
* <li>{@code long}</li>
* <li>{@link java.lang.Double}</li>
* <li>{@link java.lang.Float}</li>
* <li>{@link java.lang.Integer}</li>
* <li>{@link java.lang.Long}</li>
* <li>{@link java.lang.String}</li>
* <li>{@link java.util.UUID}</li>
* </ul>
*
* <p>
* A note about the mapping between the Postgres {@code interval} type and the Java {@link java.time.Period} and
* {@link java.time.Duration} types:
* The Java library authors are much more strict about the temporal amounts representable by Periods and Durations than
* Postgres is with its {@code interval} type. The argument factories and column mapper factories implemented in this
* package respect this spirit of unambiguous strictness. Consequently:
* <ul>
* <li>All {@link java.time.Period}s can be mapped to {@code interval}s.</li>
* <li>Not all {@link java.time.Duration}s can be mapped to {@code interval}s.</li>
* <li>Not all {@code interval}s can be mapped to {@link java.time.Period}s.</li>
* <li>Not all {@code interval}s can be mapped to {@link java.time.Duration}s.</li>
* </ul>
* For more specific detail, see the caveats in the documentation for {@link DurationArgumentFactory},
* {@link PeriodColumnMapperFactory}, and {@link DurationColumnMapperFactory}.
*
* <p>
* In addition, some potentially unexpected implicit conversions can occur by virtue of the Postgres <em>server</em>
* logic. For example, at the time of writing, storing a Period of -3 years, 2 months, and -1 days results in an
* interval (and consequently, a column-mapped Period) of <em>-2 years, -10 months</em>, and -1 days.
*/
public class PostgresPlugin extends JdbiPlugin.Singleton {
@Override
public void customizeJdbi(Jdbi jdbi) {
jdbi.registerArgument(new TypedEnumArgumentFactory());
jdbi.registerArgument(new JavaTimeArgumentFactory());
jdbi.registerArgument(new DurationArgumentFactory());
jdbi.registerArgument(new PeriodArgumentFactory());
jdbi.registerArgument(new InetArgumentFactory());
jdbi.registerArgument(new HStoreArgumentFactory());
jdbi.registerArgument(new MacAddrArgumentFactory());
jdbi.registerArgument(new UUIDArgumentFactory());
jdbi.registerArgument(new PGobjectArgumentFactory());
jdbi.registerArgument(new BitStringEnumSetArgumentFactory());
jdbi.registerArgument(new BlobInputStreamArgumentFactory());
jdbi.registerArgument(new ClobReaderArgumentFactory());
jdbi.registerArrayType(short.class, "smallint");
jdbi.registerArrayType(Short.class, "smallint");
jdbi.registerArrayType(int.class, "integer");
jdbi.registerArrayType(Integer.class, "integer");
jdbi.registerArrayType(long.class, "bigint");
jdbi.registerArrayType(Long.class, "bigint");
jdbi.registerArrayType(String.class, "varchar");
jdbi.registerArrayType(UUID.class, "uuid");
jdbi.registerArrayType(float.class, "float4");
jdbi.registerArrayType(Float.class, "float4");
jdbi.registerArrayType(double.class, "float8");
jdbi.registerArrayType(Double.class, "float8");
// built-in PGobject types
jdbi.registerArrayType(PGbox.class, "box");
jdbi.registerArrayType(PGcircle.class, "circle");
jdbi.registerArrayType(PGInterval.class, "interval");
jdbi.registerArrayType(PGline.class, "line");
jdbi.registerArrayType(PGlseg.class, "lseg");
jdbi.registerArrayType(PGmoney.class, "money");
jdbi.registerArrayType(PGpath.class, "path");
jdbi.registerArrayType(PGpoint.class, "point");
jdbi.registerArrayType(PGpolygon.class, "polygon");
jdbi.registerColumnMapper(new JavaTimeMapperFactory());
jdbi.registerColumnMapper(new HStoreColumnMapper());
jdbi.registerColumnMapper(new MacAddrColumnMapper());
jdbi.registerColumnMapper(new DurationColumnMapperFactory());
jdbi.registerColumnMapper(new PeriodColumnMapperFactory());
jdbi.registerColumnMapper(new PGobjectColumnMapperFactory());
jdbi.registerColumnMapper(new BitStringEnumSetMapperFactory());
jdbi.registerColumnMapper(new BlobInputStreamColumnMapperFactory());
jdbi.registerColumnMapper(new ClobReaderColumnMapperFactory());
// legacy unqualified HSTORE
jdbi.registerArgument((ArgumentFactory) new HStoreArgumentFactory()::build);
jdbi.registerColumnMapper(new GenericType<Map<String, String>>() {}, new HStoreColumnMapper());
// optional integration
if (JdbiClassUtils.isPresent("org.jdbi.v3.json.JsonConfig")) {
jdbi.registerArgument(new JsonArgumentFactory());
}
}
@Override
@SuppressWarnings("PMD.CloseResource")
public Handle customizeHandle(Handle handle) {
Connection conn = handle.getConnection();
PGConnection pgConnection = Unchecked.supplier(() -> conn.unwrap(PGConnection.class)).get();
return handle.configure(PostgresTypes.class, pt -> {
pt.addTypesToConnection(pgConnection);
pt.setLobApi(new PgLobApiImpl(conn));
});
}
}