Skip to content

Commit 1e293fb

Browse files
committed
fix(jdbc): clone Calendar parameter in date/time setters to prevent mutation
1 parent 12348a6 commit 1e293fb

2 files changed

Lines changed: 33 additions & 21 deletions

File tree

java-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryPreparedStatement.java

Lines changed: 24 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -543,16 +543,17 @@ public void setDate(int parameterIndex, Date x, Calendar cal) throws SQLExceptio
543543
setDate(parameterIndex, x);
544544
return;
545545
}
546+
Calendar targetCal = (Calendar) cal.clone();
546547
Calendar defaultCal = Calendar.getInstance();
547548
defaultCal.setTime(x);
548-
cal.set(Calendar.YEAR, defaultCal.get(Calendar.YEAR));
549-
cal.set(Calendar.MONTH, defaultCal.get(Calendar.MONTH));
550-
cal.set(Calendar.DAY_OF_MONTH, defaultCal.get(Calendar.DAY_OF_MONTH));
551-
cal.set(Calendar.HOUR_OF_DAY, 0);
552-
cal.set(Calendar.MINUTE, 0);
553-
cal.set(Calendar.SECOND, 0);
554-
cal.set(Calendar.MILLISECOND, 0);
555-
setDate(parameterIndex, new Date(cal.getTimeInMillis()));
549+
targetCal.set(Calendar.YEAR, defaultCal.get(Calendar.YEAR));
550+
targetCal.set(Calendar.MONTH, defaultCal.get(Calendar.MONTH));
551+
targetCal.set(Calendar.DAY_OF_MONTH, defaultCal.get(Calendar.DAY_OF_MONTH));
552+
targetCal.set(Calendar.HOUR_OF_DAY, 0);
553+
targetCal.set(Calendar.MINUTE, 0);
554+
targetCal.set(Calendar.SECOND, 0);
555+
targetCal.set(Calendar.MILLISECOND, 0);
556+
setDate(parameterIndex, new Date(targetCal.getTimeInMillis()));
556557
}
557558

558559
@Override
@@ -566,13 +567,14 @@ public void setTime(int parameterIndex, Time x, Calendar cal) throws SQLExceptio
566567
setTime(parameterIndex, x);
567568
return;
568569
}
570+
Calendar targetCal = (Calendar) cal.clone();
569571
Calendar defaultCal = Calendar.getInstance();
570572
defaultCal.setTime(x);
571-
cal.set(Calendar.HOUR_OF_DAY, defaultCal.get(Calendar.HOUR_OF_DAY));
572-
cal.set(Calendar.MINUTE, defaultCal.get(Calendar.MINUTE));
573-
cal.set(Calendar.SECOND, defaultCal.get(Calendar.SECOND));
574-
cal.set(Calendar.MILLISECOND, defaultCal.get(Calendar.MILLISECOND));
575-
setTime(parameterIndex, new Time(cal.getTimeInMillis()));
573+
targetCal.set(Calendar.HOUR_OF_DAY, defaultCal.get(Calendar.HOUR_OF_DAY));
574+
targetCal.set(Calendar.MINUTE, defaultCal.get(Calendar.MINUTE));
575+
targetCal.set(Calendar.SECOND, defaultCal.get(Calendar.SECOND));
576+
targetCal.set(Calendar.MILLISECOND, defaultCal.get(Calendar.MILLISECOND));
577+
setTime(parameterIndex, new Time(targetCal.getTimeInMillis()));
576578
}
577579

578580
@Override
@@ -586,16 +588,17 @@ public void setTimestamp(int parameterIndex, Timestamp x, Calendar cal) throws S
586588
setTimestamp(parameterIndex, x);
587589
return;
588590
}
591+
Calendar targetCal = (Calendar) cal.clone();
589592
Calendar defaultCal = Calendar.getInstance();
590593
defaultCal.setTime(x);
591-
cal.set(Calendar.YEAR, defaultCal.get(Calendar.YEAR));
592-
cal.set(Calendar.MONTH, defaultCal.get(Calendar.MONTH));
593-
cal.set(Calendar.DAY_OF_MONTH, defaultCal.get(Calendar.DAY_OF_MONTH));
594-
cal.set(Calendar.HOUR_OF_DAY, defaultCal.get(Calendar.HOUR_OF_DAY));
595-
cal.set(Calendar.MINUTE, defaultCal.get(Calendar.MINUTE));
596-
cal.set(Calendar.SECOND, defaultCal.get(Calendar.SECOND));
597-
cal.set(Calendar.MILLISECOND, defaultCal.get(Calendar.MILLISECOND));
598-
Timestamp adjustedTimestamp = new Timestamp(cal.getTimeInMillis());
594+
targetCal.set(Calendar.YEAR, defaultCal.get(Calendar.YEAR));
595+
targetCal.set(Calendar.MONTH, defaultCal.get(Calendar.MONTH));
596+
targetCal.set(Calendar.DAY_OF_MONTH, defaultCal.get(Calendar.DAY_OF_MONTH));
597+
targetCal.set(Calendar.HOUR_OF_DAY, defaultCal.get(Calendar.HOUR_OF_DAY));
598+
targetCal.set(Calendar.MINUTE, defaultCal.get(Calendar.MINUTE));
599+
targetCal.set(Calendar.SECOND, defaultCal.get(Calendar.SECOND));
600+
targetCal.set(Calendar.MILLISECOND, defaultCal.get(Calendar.MILLISECOND));
601+
Timestamp adjustedTimestamp = new Timestamp(targetCal.getTimeInMillis());
599602
adjustedTimestamp.setNanos(x.getNanos());
600603
setTimestamp(parameterIndex, adjustedTimestamp);
601604
}

java-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/BigQueryPreparedStatementSettersTest.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,28 +179,37 @@ public void testGetParameterMetaData() throws Exception {
179179
@Test
180180
public void testSetDateWithCalendar() throws Exception {
181181
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
182+
cal.setTimeInMillis(1000000L);
183+
long originalMillis = cal.getTimeInMillis();
182184
Date date = new Date(1700000000000L); // 2023-11-14
183185

184186
preparedStatement.setDate(1, date, cal);
185187
assertEquals(String.class, preparedStatement.parameterHandler.getType(1));
188+
assertEquals(originalMillis, cal.getTimeInMillis());
186189
}
187190

188191
@Test
189192
public void testSetTimeWithCalendar() throws Exception {
190193
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
194+
cal.setTimeInMillis(1000000L);
195+
long originalMillis = cal.getTimeInMillis();
191196
Time time = new Time(43200000L); // 12:00:00
192197

193198
preparedStatement.setTime(1, time, cal);
194199
assertEquals(String.class, preparedStatement.parameterHandler.getType(1));
200+
assertEquals(originalMillis, cal.getTimeInMillis());
195201
}
196202

197203
@Test
198204
public void testSetTimestampWithCalendar() throws Exception {
199205
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
206+
cal.setTimeInMillis(1000000L);
207+
long originalMillis = cal.getTimeInMillis();
200208
Timestamp ts = new Timestamp(1700000000000L);
201209

202210
preparedStatement.setTimestamp(1, ts, cal);
203211
assertEquals(String.class, preparedStatement.parameterHandler.getType(1));
212+
assertEquals(originalMillis, cal.getTimeInMillis());
204213
}
205214

206215
@Test

0 commit comments

Comments
 (0)