|
| 1 | +package de.bytefish.pgbulkinsert.test.issues; |
| 2 | + |
| 3 | +import de.bytefish.pgbulkinsert.PgBulkInsert; |
| 4 | +import de.bytefish.pgbulkinsert.mapping.AbstractMapping; |
| 5 | +import de.bytefish.pgbulkinsert.test.mapping.PersonMapping; |
| 6 | +import de.bytefish.pgbulkinsert.test.model.Person; |
| 7 | +import de.bytefish.pgbulkinsert.test.utils.TransactionalTestBase; |
| 8 | +import de.bytefish.pgbulkinsert.util.PostgreSqlUtils; |
| 9 | +import org.checkerframework.checker.nullness.qual.NonNull; |
| 10 | +import org.checkerframework.checker.nullness.qual.Nullable; |
| 11 | +import org.junit.Assert; |
| 12 | +import org.junit.Test; |
| 13 | + |
| 14 | +import java.sql.ResultSet; |
| 15 | +import java.sql.SQLException; |
| 16 | +import java.sql.Statement; |
| 17 | +import java.sql.Timestamp; |
| 18 | +import java.time.LocalDate; |
| 19 | +import java.util.ArrayList; |
| 20 | +import java.util.Date; |
| 21 | +import java.util.List; |
| 22 | + |
| 23 | +@SuppressWarnings("NullAway") |
| 24 | +public class TimestampMappingIssueTest extends TransactionalTestBase { |
| 25 | + |
| 26 | + @Override |
| 27 | + protected void onSetUpInTransaction() throws Exception { |
| 28 | + createTable(); |
| 29 | + } |
| 30 | + |
| 31 | + private enum TicketStatusEnum { |
| 32 | + NONE, |
| 33 | + NEW |
| 34 | + } |
| 35 | + |
| 36 | + private static class Ticket { |
| 37 | + public String jobId; |
| 38 | + public String entityId; |
| 39 | + public long stepNo; |
| 40 | + public String opType; |
| 41 | + public TicketStatusEnum status; |
| 42 | + public String createdBy; |
| 43 | + public String resetBy; |
| 44 | + public Timestamp scheduledStartTime; |
| 45 | + public Timestamp scheduledEndTime; |
| 46 | + public Timestamp startTime; |
| 47 | + public Timestamp endTime; |
| 48 | + public boolean retryable; |
| 49 | + public int retryCount; |
| 50 | + public int cleanupStep; |
| 51 | + public String assignedTo; |
| 52 | + public String externalRefId; |
| 53 | + public String ticketDetail; |
| 54 | + public Timestamp createdTime; |
| 55 | + public String updatedBy; |
| 56 | + public boolean dryRun; |
| 57 | + public boolean cancelRequested; |
| 58 | + public String abortCode; |
| 59 | + public String errorCode; |
| 60 | + } |
| 61 | + |
| 62 | +private static class TicketMapping extends AbstractMapping<Ticket> { |
| 63 | +public TicketMapping(String schema) { |
| 64 | + super(schema, "unit_test"); |
| 65 | + |
| 66 | + mapText("job_id", x -> x.jobId); |
| 67 | + mapText("entity_id", x -> x.entityId); |
| 68 | + mapNumeric("step_no", x -> x.stepNo); |
| 69 | + mapText("status", x -> x.status != null ? x.status.name() : null); |
| 70 | + mapText("op_type", x -> x.opType); |
| 71 | + mapText("created_by", x -> x.createdBy); |
| 72 | + mapText("reset_by", x -> x.resetBy); |
| 73 | + mapTimeStamp("scheduled_end_time", x -> x.scheduledEndTime != null ? x.scheduledEndTime.toLocalDateTime() : null); |
| 74 | + mapTimeStamp("scheduled_start_time", x -> x.scheduledStartTime != null ? x.scheduledStartTime.toLocalDateTime() : null); |
| 75 | + mapTimeStamp("start_time", x -> x.startTime != null ? x.startTime.toLocalDateTime() : null); |
| 76 | + mapTimeStamp("end_time", x -> x.endTime != null ? x.endTime.toLocalDateTime() : null); |
| 77 | + mapBoolean("retryable", x -> x != null ? x.retryable : null); |
| 78 | + mapNumeric("retry_count", x -> x.retryCount); |
| 79 | + mapNumeric("cleanup_step", x -> x.cleanupStep); |
| 80 | + mapText("assigned_to", x -> x.assignedTo); |
| 81 | + mapText("external_ref_id", x -> x.externalRefId); |
| 82 | + mapText("ticket_detail", x -> x.ticketDetail); |
| 83 | + mapTimeStamp("created_time", x -> x.createdTime != null ? x.createdTime.toLocalDateTime() : null); |
| 84 | + mapText("updated_by", x -> x.updatedBy); |
| 85 | + mapBoolean("dry_run", x -> x != null ? x.dryRun : null); |
| 86 | + mapBoolean("cancel_requested", x -> x != null ? x.cancelRequested : null); |
| 87 | + mapText("abort_code", x -> x.abortCode); |
| 88 | + mapText("error_code", x -> x.errorCode); |
| 89 | +} |
| 90 | + |
| 91 | + |
| 92 | + } |
| 93 | + |
| 94 | + @Test |
| 95 | + public void bulkInsertPersonDataTest() throws SQLException { |
| 96 | + List<Ticket> ticketList = getTicketList(100000); |
| 97 | + // Create the BulkInserter: |
| 98 | + PgBulkInsert<Ticket> bulkInsert = new PgBulkInsert<>(new TicketMapping(schema)); |
| 99 | + // Now save all entities of a given stream: |
| 100 | + bulkInsert.saveAll(PostgreSqlUtils.getPGConnection(connection), ticketList.stream()); |
| 101 | + // And assert all have been written to the database: |
| 102 | + Assert.assertEquals(100000, getRowCount()); |
| 103 | + } |
| 104 | + |
| 105 | + private List<Ticket> getTicketList(int num) { |
| 106 | + |
| 107 | + List<Ticket> ticketList = new ArrayList<>(); |
| 108 | + |
| 109 | + for (int pos = 0; pos < num; pos++) { |
| 110 | + Ticket t = new Ticket(); |
| 111 | + |
| 112 | + t.errorCode = "ERROR"; |
| 113 | + t.abortCode = "ABORT"; |
| 114 | + t.cancelRequested = true; |
| 115 | + t.dryRun = true; |
| 116 | + t.updatedBy = "Philipp"; |
| 117 | + t.createdTime = new Timestamp(new Date().getTime()); |
| 118 | + t.ticketDetail = "Ticket Detail"; |
| 119 | + t.externalRefId = "18431"; |
| 120 | + t.assignedTo = "Philipp"; |
| 121 | + t.cleanupStep = 4; |
| 122 | + t.retryCount = 8; |
| 123 | + t.retryable = true; |
| 124 | + t.endTime = new Timestamp(new Date().getTime()); |
| 125 | + t.startTime = new Timestamp(new Date().getTime()); |
| 126 | + t.scheduledStartTime = new Timestamp(new Date().getTime()); |
| 127 | + t.scheduledEndTime = new Timestamp(new Date().getTime()); |
| 128 | + t.resetBy = "Philipp"; |
| 129 | + t.createdBy = "Philipp"; |
| 130 | + t.status = TicketStatusEnum.NONE; |
| 131 | + t.opType = "OP_START"; |
| 132 | + t.stepNo = 3; |
| 133 | + t.entityId = "7814111247"; |
| 134 | + t.jobId = "7"; |
| 135 | + |
| 136 | + ticketList.add(t); |
| 137 | + } |
| 138 | + |
| 139 | + return ticketList; |
| 140 | + } |
| 141 | + |
| 142 | + private boolean createTable() throws SQLException { |
| 143 | + |
| 144 | + String sqlStatement = String.format("CREATE TABLE %s.unit_test\n", schema) + |
| 145 | + " (\n" + |
| 146 | + " ticket_id text\n" + |
| 147 | + " , abort_code text\n" + |
| 148 | + " , assigned_to text\n" + |
| 149 | + " , cancel_requested boolean\n" + |
| 150 | + " , cleanup_step numeric\n" + |
| 151 | + " , created_by text\n" + |
| 152 | + " , created_time timestamp\n" + |
| 153 | + " , dry_run boolean\n" + |
| 154 | + " , end_time timestamp\n" + |
| 155 | + " , entity_id text\n" + |
| 156 | + " , error_code text\n" + |
| 157 | + " , external_ref_id text\n" + |
| 158 | + " , job_id text\n" + |
| 159 | + " , op_type text\n" + |
| 160 | + " , reset_by text\n" + |
| 161 | + " , retry_count numeric\n" + |
| 162 | + " , retryable boolean\n" + |
| 163 | + " , scheduled_end_time timestamp\n" + |
| 164 | + " , scheduled_start_time timestamp\n" + |
| 165 | + " , start_time timestamp\n" + |
| 166 | + " , status text\n" + |
| 167 | + " , step_no numeric\n" + |
| 168 | + " , ticket_detail text\n" + |
| 169 | + " , updated_by text\n" + |
| 170 | + " );"; |
| 171 | + |
| 172 | + Statement statement = connection.createStatement(); |
| 173 | + |
| 174 | + return statement.execute(sqlStatement); |
| 175 | + } |
| 176 | + |
| 177 | + private int getRowCount() throws SQLException { |
| 178 | + |
| 179 | + Statement s = connection.createStatement(); |
| 180 | + |
| 181 | + ResultSet r = s.executeQuery(String.format("SELECT COUNT(*) AS rowcount FROM %s.unit_test", schema)); |
| 182 | + r.next(); |
| 183 | + int count = r.getInt("rowcount"); |
| 184 | + r.close(); |
| 185 | + |
| 186 | + return count; |
| 187 | + } |
| 188 | + |
| 189 | +} |
| 190 | + |
0 commit comments