001package de.bytefish.pgbulkinsert.row;
002
003import de.bytefish.pgbulkinsert.pgsql.PgBinaryWriter;
004import de.bytefish.pgbulkinsert.pgsql.constants.DataType;
005import de.bytefish.pgbulkinsert.pgsql.constants.ObjectIdentifier;
006import de.bytefish.pgbulkinsert.pgsql.handlers.CollectionValueHandler;
007import de.bytefish.pgbulkinsert.pgsql.handlers.IValueHandler;
008import de.bytefish.pgbulkinsert.pgsql.handlers.RangeValueHandler;
009import de.bytefish.pgbulkinsert.pgsql.handlers.ValueHandlerProvider;
010import de.bytefish.pgbulkinsert.pgsql.model.geometric.*;
011import de.bytefish.pgbulkinsert.pgsql.model.interval.Interval;
012import de.bytefish.pgbulkinsert.pgsql.model.network.MacAddress;
013import de.bytefish.pgbulkinsert.pgsql.model.range.Range;
014
015import java.net.Inet4Address;
016import java.net.Inet6Address;
017import java.time.LocalDate;
018import java.time.LocalDateTime;
019import java.time.LocalTime;
020import java.time.ZonedDateTime;
021import java.util.*;
022import java.util.function.Consumer;
023import java.util.function.Function;
024import java.util.stream.Collectors;
025
026public class SimpleRow {
027
028    private final ValueHandlerProvider provider;
029    private final Map<String, Integer> lookup;
030    private final Map<Integer, Consumer<PgBinaryWriter>> actions;
031    private final Function<String, String> nullCharacterHandler;
032
033    public SimpleRow(ValueHandlerProvider provider, Map<String, Integer> lookup, Function<String, String> nullCharacterHandler) {
034        this.provider = provider;
035        this.lookup = lookup;
036        this.actions = new HashMap<>();
037        this.nullCharacterHandler = nullCharacterHandler;
038    }
039
040    public <TTargetType> void setValue(String columnName, DataType type, TTargetType value) {
041        final int ordinal = Objects.requireNonNull(lookup.get(columnName), columnName + " not found");
042
043        setValue(ordinal, type, value);
044    }
045
046    public <TTargetType> void setValue(int ordinal, DataType type, TTargetType value) {
047        final IValueHandler<TTargetType> handler = provider.resolve(type);
048
049        actions.put(ordinal, (writer) -> writer.write(handler, value));
050    }
051
052    public <TTargetType> void setValue(String columnName, IValueHandler<TTargetType> handler, TTargetType value) {
053        final int ordinal = Objects.requireNonNull(lookup.get(columnName), columnName + " not found");
054
055        setValue(ordinal, handler, value);
056    }
057
058    public <TTargetType> void setValue(int ordinal, IValueHandler<TTargetType> handler, TTargetType value) {
059        actions.put(ordinal, (writer) -> writer.write(handler, value));
060    }
061
062    public <TElementType, TCollectionType extends Collection<TElementType>> void setCollection(String columnName, DataType type, TCollectionType value) {
063        final int ordinal = Objects.requireNonNull(lookup.get(columnName), columnName + " not found");
064
065        setCollection(ordinal, type, value);
066    }
067
068
069    public <TElementType, TCollectionType extends Collection<TElementType>> void setCollection(int ordinal, DataType type, TCollectionType value) {
070        final CollectionValueHandler<TElementType, TCollectionType> handler = new CollectionValueHandler<>(ObjectIdentifier.mapFrom(type), provider.resolve(type));
071
072        actions.put(ordinal, (writer) -> writer.write(handler, value));
073    }
074
075
076    public void writeRow(PgBinaryWriter writer) {
077        for (int ordinalIdx = 0; ordinalIdx < lookup.keySet().size(); ordinalIdx++) {
078
079            // If this Ordinal wasn't set, we assume a NULL:
080            final Consumer<PgBinaryWriter> action = actions.get(ordinalIdx);
081            if (action == null) {
082                writer.writeNull();
083            } else {
084                action.accept(writer);
085            }
086        }
087    }
088
089    // region Numeric
090
091    public void setBoolean(String columnName, Boolean value) {
092        setValue(columnName, DataType.Boolean, value);
093    }
094
095    public void setBoolean(int ordinal, Boolean value) {
096        setValue(ordinal, DataType.Boolean, value);
097    }
098
099    public void setByte(String columnName, Byte value) {
100        setValue(columnName, DataType.Char, value);
101    }
102
103    public void setByte(int ordinal, Byte value) {
104        setValue(ordinal, DataType.Char, value);
105    }
106
107    public void setShort(String columnName, Short value) {
108        setValue(columnName, DataType.Int2, value);
109    }
110
111    public void setShort(int ordinal, Short value) {
112        setValue(ordinal, DataType.Int2, value);
113    }
114
115    public void setInteger(String columnName, Integer value) {
116        setValue(columnName, DataType.Int4, value);
117    }
118
119    public void setInteger(int ordinal, Integer value) {
120        setValue(ordinal, DataType.Int4, value);
121    }
122
123    public void setNumeric(String columnName, Number value) {
124        setValue(columnName, DataType.Numeric, value);
125    }
126
127    public void setNumeric(int ordinal, Number value) {
128        setValue(ordinal, DataType.Numeric, value);
129    }
130
131    public void setLong(String columnName, Long value) {
132        setValue(columnName, DataType.Int8, value);
133    }
134
135    public void setLong(int ordinal, Long value) {
136        setValue(ordinal, DataType.Int8, value);
137    }
138
139    public void setFloat(String columnName, Float value) {
140        setValue(columnName, DataType.SinglePrecision, value);
141    }
142
143    public void setFloat(int ordinal, Float value) {
144        setValue(ordinal, DataType.SinglePrecision, value);
145    }
146
147    public void setDouble(String columnName, Double value) {
148        setValue(columnName, DataType.DoublePrecision, value);
149    }
150
151        public void setDouble(int ordinal, Double value) {
152                setValue(ordinal, DataType.DoublePrecision, value);
153        }
154
155    // endregion
156
157    // region Temporal
158
159    public void setInterval(String columnName, Interval value) {
160        setValue(columnName, DataType.Interval, value);
161    }
162
163    public void setTime(String columnName, LocalTime value) {
164        setValue(columnName, DataType.Time, value);
165    }
166
167    public void setTime(int ordinal, LocalTime value) {
168        setValue(ordinal, DataType.Time, value);
169    }
170
171    public void setDate(String columnName, LocalDate value) {
172        setValue(columnName, DataType.Date, value);
173    }
174
175    public void setDate(int ordinal, LocalDate value) {
176        setValue(ordinal, DataType.Date, value);
177    }
178
179    public void setTimeStamp(String columnName, LocalDateTime value) {
180        setValue(columnName, DataType.Timestamp, value);
181    }
182
183    public void setTimeStamp(int ordinal, LocalDateTime value) {
184
185        setValue(ordinal, DataType.Timestamp, value);
186    }
187
188    public void setTimeStampTz(String columnName, ZonedDateTime value) {
189        setValue(columnName, DataType.TimestampTz, value);
190    }
191
192    public void setTimeStampTz(int ordinal, ZonedDateTime value) {
193        setValue(ordinal, DataType.TimestampTz, value);
194    }
195
196    // endregion
197
198    // region Network
199
200    public void setInet6Addr(String columnName, Inet6Address value) {
201        setValue(columnName, DataType.Inet6, value);
202    }
203
204    public void setInet6Addr(int ordinal, Inet6Address value) {
205        setValue(ordinal, DataType.Inet6, value);
206    }
207
208    public void setInet4Addr(String columnName, Inet4Address value) {
209        setValue(columnName, DataType.Inet4, value);
210    }
211
212    public void setInet4Addr(int ordinal, Inet4Address value) {
213        setValue(ordinal, DataType.Inet4, value);
214    }
215
216    public void setMacAddress(String columnName, MacAddress value) {
217        setValue(columnName, DataType.MacAddress, value);
218    }
219
220    public void setMacAddress(int ordinal, MacAddress value) {
221        setValue(ordinal, DataType.MacAddress, value);
222    }
223
224
225    // endregion
226
227    // region Text
228
229    public void setText(String columnName, String value) {
230        setValue(columnName, DataType.Text, nullCharacterHandler.apply(value));
231    }
232
233    public void setText(int ordinal, String value) {
234        setValue(ordinal, DataType.Text, nullCharacterHandler.apply(value));
235    }
236
237    public void setVarChar(String columnName, String value) {
238        setValue(columnName, DataType.Text, nullCharacterHandler.apply(value));
239    }
240
241    public void setVarChar(int ordinal, String value) {
242        setValue(ordinal, DataType.Text, nullCharacterHandler.apply(value));
243    }
244
245    // endregion
246
247    // region UUID
248
249    public void setUUID(String columnName, UUID value) {
250        setValue(columnName, DataType.Uuid, value);
251    }
252
253    public void setUUID(int ordinal, UUID value) {
254        setValue(ordinal, DataType.Uuid, value);
255    }
256
257    // endregion
258
259    // region JSON
260
261    public void setJsonb(String columnName, String value) {
262        setValue(columnName, DataType.Jsonb, nullCharacterHandler.apply(value));
263    }
264
265    public void setJsonb(int ordinal, String value) {
266        setValue(ordinal, DataType.Jsonb, nullCharacterHandler.apply(value));
267    }
268
269    // endregion
270
271    // region hstore
272
273    public void setHstore(String columnName, Map<String, String> value) {
274        setValue(columnName, DataType.Hstore, value);
275    }
276
277    public void setHstore(int ordinal, Map<String, String> value) {
278        setValue(ordinal, DataType.Hstore, value);
279    }
280
281    // endregion
282
283    // region Geo
284
285    public void setPoint(String columnName, Point value) {
286        setValue(columnName, DataType.Point, value);
287    }
288
289    public void setPoint(int ordinal, Point value) {
290        setValue(ordinal, DataType.Point, value);
291    }
292
293    public void setBox(String columnName, Box value) {
294        setValue(columnName, DataType.Box, value);
295    }
296
297    public void setBox(int ordinal, Box value) {
298        setValue(ordinal, DataType.Box, value);
299    }
300
301    public void setPath(String columnName, Path value) {
302        setValue(columnName, DataType.Path, value);
303    }
304
305    public void setPath(int ordinal, Path value) {
306        setValue(ordinal, DataType.Path, value);
307    }
308
309    public void setPolygon(String columnName, Polygon value) {
310        setValue(columnName, DataType.Polygon, value);
311    }
312
313    public void setPolygon(int ordinal, Polygon value) {
314        setValue(ordinal, DataType.Polygon, value);
315    }
316
317    public void setLine(String columnName, Line value) {
318        setValue(columnName, DataType.Line, value);
319    }
320
321    public void setLine(int ordinal, Line value) {
322        setValue(ordinal, DataType.Line, value);
323    }
324
325    public void setLineSegment(String columnName, LineSegment value) {
326        setValue(columnName, DataType.LineSegment, value);
327    }
328
329    public void setLineSegment(int ordinal, LineSegment value) {
330        setValue(ordinal, DataType.LineSegment, value);
331    }
332
333    public void setCircle(String columnName, Circle value) {
334        setValue(columnName, DataType.Circle, value);
335    }
336
337    public void setCircle(int ordinal, Circle value) {
338        setValue(ordinal, DataType.Circle, value);
339    }
340
341    // endregion
342
343    // region Arrays
344
345    public void setByteArray(String columnName, byte[] value) {
346        setValue(columnName, DataType.Bytea, value);
347    }
348
349    public void setByteArray(int ordinal, byte[] value) {
350        setValue(ordinal, DataType.Bytea, value);
351    }
352
353    public void setBooleanArray(String columnName, Collection<Boolean> value) {
354        setCollection(columnName, DataType.Boolean, value);
355    }
356
357    public void setBooleanArray(int ordinal, Collection<Boolean> value) {
358        setCollection(ordinal, DataType.Boolean, value);
359    }
360
361    public <T extends Number> void setShortArray(String columnName, Collection<T> value) {
362        setCollection(columnName, DataType.Int2, value);
363    }
364
365    public <T extends Number> void setShortArray(int ordinal, Collection<T> value) {
366        setCollection(ordinal, DataType.Int2, value);
367    }
368
369    public <T extends Number> void setIntegerArray(String columnName, Collection<T> value) {
370        setCollection(columnName, DataType.Int4, value);
371    }
372
373    public <T extends Number> void setIntegerArray(int ordinal, Collection<T> value) {
374        setCollection(ordinal, DataType.Int4, value);
375    }
376
377    public <T extends Number> void setLongArray(String columnName, Collection<T> value) {
378        setCollection(columnName, DataType.Int8, value);
379    }
380
381    public <T extends Number> void setLongArray(int ordinal, Collection<T> value) {
382        setCollection(ordinal, DataType.Int8, value);
383    }
384
385    public void setTextArray(String columnName, Collection<String> value) {
386        setCollection(columnName, DataType.Text,
387            value == null ? null : value.stream()
388                .map(nullCharacterHandler)
389                .collect(Collectors.toList()));
390    }
391
392    public void setTextArray(int ordinal, Collection<String> value) {
393        setCollection(ordinal, DataType.Text,
394            value == null ? null : value.stream()
395            .map(nullCharacterHandler)
396            .collect(Collectors.toList())
397        );
398    }
399
400    public void setVarCharArray(String columnName, Collection<String> value) {
401
402        Collection<String> values = value.stream()
403                .map(x -> nullCharacterHandler.apply(x))
404                .collect(Collectors.toList());
405
406        setCollection(columnName, DataType.VarChar, values);
407    }
408
409    public void setVarCharArray(int ordinal, Collection<String> value) {
410        Collection<String> values = value.stream()
411                .map(x -> nullCharacterHandler.apply(x))
412                .collect(Collectors.toList());
413
414        setCollection(ordinal, DataType.VarChar, values);
415    }
416
417    public <T extends Number> void setFloatArray(String columnName, Collection<T> value) {
418        setCollection(columnName, DataType.SinglePrecision, value);
419    }
420
421    public <T extends Number> void setFloatArray(int ordinal, Collection<T> value) {
422        setCollection(ordinal, DataType.SinglePrecision, value);
423    }
424
425    public <T extends Number> void setDoubleArray(String columnName, Collection<T> value) {
426        setCollection(columnName, DataType.DoublePrecision, value);
427    }
428
429    public <T extends Number> void setDoubleArray(int ordinal, Collection<T> value) {
430        setCollection(ordinal, DataType.DoublePrecision, value);
431    }
432
433    public <T extends Number> void setNumericArray(String columnName, Collection<T> value) {
434        setCollection(columnName, DataType.Numeric, value);
435    }
436
437    public <T extends Number> void setNumericArray(int ordinal, Collection<T> value) {
438        setCollection(ordinal, DataType.Numeric, value);
439    }
440
441    public void setUUIDArray(String columnName, Collection<UUID> value) {
442        setCollection(columnName, DataType.Uuid, value);
443    }
444
445    public void setUUIDArray(int ordinal, Collection<UUID> value) {
446        setCollection(ordinal, DataType.Uuid, value);
447    }
448
449    public void setInet4Array(String columnName, Collection<Inet4Address> value) {
450        setCollection(columnName, DataType.Inet4, value);
451    }
452
453    public void setInet4Array(int ordinal, Collection<Inet4Address> value) {
454        setCollection(ordinal, DataType.Inet4, value);
455    }
456
457    public void setInet6Array(String columnName, Collection<Inet6Address> value) {
458        setCollection(columnName, DataType.Inet6, value);
459    }
460
461    public void setInet6Array(int ordinal, Collection<Inet6Address> value) {
462        setCollection(ordinal, DataType.Inet6, value);
463    }
464
465    // endregion
466
467    // region Ranges
468
469    public <TElementType> void setRange(String columnName, DataType dataType, Range<TElementType> value) {
470
471        final IValueHandler<TElementType> valueHandler = provider.resolve(dataType);
472
473        setValue(columnName, new RangeValueHandler<>(valueHandler), value);
474    }
475
476    public <TElementType> void setRange(int ordinal, DataType dataType, Range<TElementType> value) {
477
478        final IValueHandler<TElementType> valueHandler = provider.resolve(dataType);
479
480        setValue(ordinal, new RangeValueHandler<>(valueHandler), value);
481    }
482
483    public void setTsRange(String columnName, Range<LocalDateTime> value) {
484        setValue(columnName, DataType.TsRange, value);
485    }
486
487    public void setTsRange(int ordinal, Range<LocalDateTime> value) {
488        setValue(ordinal, DataType.TsRange, value);
489    }
490
491    public void setTsTzRange(String columnName, Range<ZonedDateTime> value) {
492        setValue(columnName, DataType.TsTzRange, value);
493    }
494
495    public void setTsTzRange(int ordinal, Range<ZonedDateTime> value) {
496        setValue(ordinal, DataType.TsTzRange, value);
497    }
498
499    public void setInt4Range(String columnName, Range<Integer> value) {
500        setValue(columnName, DataType.Int4Range, value);
501    }
502
503    public void setInt4Range(int ordinal, Range<Integer> value) {
504        setValue(ordinal, DataType.Int4Range, value);
505    }
506
507    public void setInt8Range(String columnName, Range<Long> value) {
508        setValue(columnName, DataType.Int8Range, value);
509    }
510
511    public void setInt8Range(int ordinal, Range<Long> value) {
512        setValue(ordinal, DataType.Int8Range, value);
513    }
514
515    public void setNumRange(String columnName, Range<Number> value) {
516        setValue(columnName, DataType.NumRange, value);
517    }
518
519    public void setNumRange(int ordinal, Range<Number> value) {
520        setValue(ordinal, DataType.NumRange, value);
521    }
522
523
524    public void setDateRange(String columnName, Range<LocalDate> value) {
525        setValue(columnName, DataType.DateRange, value);
526    }
527
528    public void setDateRange(int ordinal, Range<LocalDate> value) {
529        setValue(ordinal, DataType.DateRange, value);
530    }
531
532
533    // endregion
534}