Skip to content

Commit 536df8b

Browse files
committed
feat: core type registry matrix (Phase 1)
1 parent 94fd293 commit 536df8b

1 file changed

Lines changed: 38 additions & 94 deletions

File tree

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

Lines changed: 38 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -128,99 +128,10 @@ final class BigQueryTypeRegistry {
128128
throw new BigQueryJdbcException("Cannot convert to NUMERIC: " + val);
129129
}));
130130

131-
// DATE
132-
register(
133-
new TypeDescriptor<>(
134-
Types.DATE,
135-
Date.class,
136-
StandardSQLTypeName.DATE,
137-
Arrays.asList(Date.class, LocalDate.class),
138-
(val, targetClass, zone) -> {
139-
Date sqlDate;
140-
if (val instanceof Date) sqlDate = (Date) val;
141-
else if (val instanceof java.util.Date)
142-
sqlDate = new Date(((java.util.Date) val).getTime());
143-
else if (val instanceof LocalDate) sqlDate = Date.valueOf((LocalDate) val);
144-
else if (val instanceof String)
145-
sqlDate = BigQueryTimezoneUtility.boxDate((String) val, zone);
146-
else throw new BigQueryJdbcException("Cannot convert to DATE: " + val);
147-
148-
if (targetClass == LocalDate.class) return sqlDate.toLocalDate();
149-
return sqlDate;
150-
}));
151-
152-
// DATETIME
153-
register(
154-
new TypeDescriptor<>(
155-
Types.TIMESTAMP,
156-
Timestamp.class,
157-
StandardSQLTypeName.DATETIME,
158-
Arrays.asList(Timestamp.class, LocalDateTime.class),
159-
(val, targetClass, zone) -> {
160-
Timestamp ts;
161-
if (val instanceof Timestamp) ts = (Timestamp) val;
162-
else if (val instanceof java.util.Date)
163-
ts = new Timestamp(((java.util.Date) val).getTime());
164-
else if (val instanceof LocalDateTime) ts = Timestamp.valueOf((LocalDateTime) val);
165-
else if (val instanceof String)
166-
ts = BigQueryTimezoneUtility.boxDateTime((String) val, zone);
167-
else throw new BigQueryJdbcException("Cannot convert to DATETIME: " + val);
168-
169-
if (targetClass == LocalDateTime.class) return ts.toLocalDateTime();
170-
return ts;
171-
}));
172-
173-
// TIMESTAMP
174-
register(
175-
new TypeDescriptor<>(
176-
Types.TIMESTAMP,
177-
Timestamp.class,
178-
StandardSQLTypeName.TIMESTAMP,
179-
Arrays.asList(
180-
Timestamp.class, OffsetDateTime.class, Instant.class, ZonedDateTime.class),
181-
(val, targetClass, zone) -> {
182-
Timestamp ts;
183-
if (val instanceof Timestamp) ts = (Timestamp) val;
184-
else if (val instanceof java.util.Date)
185-
ts = new Timestamp(((java.util.Date) val).getTime());
186-
else if (val instanceof Instant) ts = Timestamp.from((Instant) val);
187-
else if (val instanceof OffsetDateTime)
188-
ts = Timestamp.from(((OffsetDateTime) val).toInstant());
189-
else if (val instanceof ZonedDateTime)
190-
ts = Timestamp.from(((ZonedDateTime) val).toInstant());
191-
else if (val instanceof String)
192-
ts = BigQueryTimezoneUtility.boxTimestamp((String) val);
193-
else throw new BigQueryJdbcException("Cannot convert to TIMESTAMP: " + val);
194-
195-
if (targetClass == Instant.class) return ts.toInstant();
196-
if (targetClass == OffsetDateTime.class)
197-
return ts.toInstant().atOffset(java.time.ZoneOffset.UTC);
198-
if (targetClass == ZonedDateTime.class)
199-
return ts.toInstant().atZone(java.time.ZoneOffset.UTC);
200-
return ts;
201-
}));
202-
203-
// TIME
204-
register(
205-
new TypeDescriptor<>(
206-
Types.TIME,
207-
Time.class,
208-
StandardSQLTypeName.TIME,
209-
Arrays.asList(Time.class, LocalTime.class),
210-
(val, targetClass, zone) -> {
211-
Time sqlTime;
212-
if (val instanceof Time) sqlTime = (Time) val;
213-
else if (val instanceof java.util.Date)
214-
sqlTime = new Time(((java.util.Date) val).getTime());
215-
else if (val instanceof LocalTime) sqlTime = Time.valueOf((LocalTime) val);
216-
else if (val instanceof String)
217-
sqlTime = BigQueryTimezoneUtility.boxTime((String) val, zone);
218-
else throw new BigQueryJdbcException("Cannot convert to TIME: " + val);
219-
220-
if (targetClass == LocalTime.class) return sqlTime.toLocalTime();
221-
return sqlTime;
222-
}));
223-
131+
// --- TEMPORAL TYPES MOVED TO PHASE 2 PR ---
132+
// DATE, DATETIME, TIMESTAMP, and TIME descriptors require BigQueryTemporalUtility
133+
// which will be introduced in the stacked Phase 2 PR.
134+
224135
// BYTES
225136
register(
226137
new TypeDescriptor<>(
@@ -341,7 +252,9 @@ public static Class<?> toJavaClass(int jdbcType) {
341252
return String.class; // fallback
342253
}
343254

344-
/** Converts the input value to the target class type. */
255+
/**
256+
* Converts the input value to the target class type by looking up the target class descriptor.
257+
*/
345258
@SuppressWarnings("unchecked")
346259
public static <T> T convert(Object input, Class<T> targetClass) throws BigQueryJdbcException {
347260
if (input == null) {
@@ -354,6 +267,37 @@ public static <T> T convert(Object input, Class<T> targetClass) throws BigQueryJ
354267
return (T) descriptor.convert(input, targetClass, null);
355268
}
356269

270+
/**
271+
* High-performance hotpath convert for ResultSets. Converts the input value using the default
272+
* mapping for the given BigQuery type via O(1) array indexing.
273+
*/
274+
public static Object convert(Object input, StandardSQLTypeName bqType, ZoneId zoneId)
275+
throws BigQueryJdbcException {
276+
if (input == null) return null;
277+
int ordinal = bqType.ordinal();
278+
if (ordinal >= DESCRIPTORS_BY_ORDINAL.length || DESCRIPTORS_BY_ORDINAL[ordinal] == null) {
279+
throw new BigQueryJdbcException("No type descriptor registered for BigQuery type: " + bqType);
280+
}
281+
TypeDescriptor<?> descriptor = DESCRIPTORS_BY_ORDINAL[ordinal];
282+
return descriptor.convert(input, descriptor.getDefaultJavaClass(), zoneId);
283+
}
284+
285+
/**
286+
* High-performance hotpath convert for ResultSets. Converts the input value to the target class
287+
* using the descriptor for the given BigQuery type via O(1) array indexing.
288+
*/
289+
@SuppressWarnings("unchecked")
290+
public static <T> T convert(
291+
Object input, StandardSQLTypeName bqType, Class<T> targetClass, ZoneId zoneId)
292+
throws BigQueryJdbcException {
293+
if (input == null) return null;
294+
int ordinal = bqType.ordinal();
295+
if (ordinal >= DESCRIPTORS_BY_ORDINAL.length || DESCRIPTORS_BY_ORDINAL[ordinal] == null) {
296+
throw new BigQueryJdbcException("No type descriptor registered for BigQuery type: " + bqType);
297+
}
298+
return (T) DESCRIPTORS_BY_ORDINAL[ordinal].convert(input, targetClass, zoneId);
299+
}
300+
357301
private static TypeDescriptor<?> getDescriptorForClass(Class<?> clazz) {
358302
TypeDescriptor<?> descriptor = DESCRIPTORS_BY_CLASS.get(clazz);
359303
if (descriptor != null) {

0 commit comments

Comments
 (0)