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}