Skip to content

Commit cf68d8d

Browse files
feat: add support for javascript UDFs determinism level (#1094)
Fixes #1083
1 parent 86cba8b commit cf68d8d

File tree

6 files changed

+75
-9
lines changed

6 files changed

+75
-9
lines changed
Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,10 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22
<!-- see http://www.mojohaus.org/clirr-maven-plugin/examples/ignored-differences.html -->
33
<differences>
4-
<!-- TODO: REMOVE AFTER RELEASE OF CONNECTION_ID FEAT -->
4+
<!-- TODO: REMOVE AFTER RELEASE -->
55
<difference>
66
<differenceType>7013</differenceType>
7-
<className>com/google/cloud/bigquery/ExternalTableDefinition</className>
8-
<method>java.lang.String getConnectionId()</method>
9-
</difference>
10-
<difference>
11-
<differenceType>7013</differenceType>
12-
<className>com/google/cloud/bigquery/ExternalTableDefinition$Builder</className>
13-
<method>com.google.cloud.bigquery.ExternalTableDefinition$Builder setConnectionId(java.lang.String)</method>
7+
<className>com/google/cloud/bigquery/RoutineInfo$Builder</className>
8+
<method>com.google.cloud.bigquery.RoutineInfo$Builder setDeterminismLevel(java.lang.String)</method>
149
</difference>
1510
</differences>

google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/Routine.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,12 @@ Builder setLastModifiedTime(Long lastModifiedMillis) {
8787
return this;
8888
}
8989

90+
@Override
91+
public Builder setDeterminismLevel(String determinismLevel) {
92+
infoBuilder.setDeterminismLevel(determinismLevel);
93+
return this;
94+
}
95+
9096
@Override
9197
public Builder setLanguage(String language) {
9298
infoBuilder.setLanguage(language);

google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/RoutineInfo.java

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ public Routine apply(RoutineInfo routineInfo) {
6262
private final String routineType;
6363
private final Long creationTime;
6464
private final String description;
65+
private final String determinismLevel;
6566
private final Long lastModifiedTime;
6667
private final String language;
6768
private final List<RoutineArgument> argumentList;
@@ -89,6 +90,12 @@ public abstract static class Builder {
8990

9091
abstract Builder setLastModifiedTime(Long lastModifiedMillis);
9192

93+
/**
94+
* Sets the JavaScript UDF determinism levels (e.g. DETERMINISM_LEVEL_UNSPECIFIED,
95+
* DETERMINISTIC, NOT_DETERMINISTIC) only applicable to Javascript UDFs.
96+
*/
97+
public abstract Builder setDeterminismLevel(String determinismLevel);
98+
9299
/** Sets the language for the routine (e.g. SQL or JAVASCRIPT) */
93100
public abstract Builder setLanguage(String language);
94101

@@ -147,6 +154,7 @@ static class BuilderImpl extends Builder {
147154
private String routineType;
148155
private Long creationTime;
149156
private String description;
157+
private String determinismLevel;
150158
private Long lastModifiedTime;
151159
private String language;
152160
private List<RoutineArgument> argumentList;
@@ -162,6 +170,7 @@ static class BuilderImpl extends Builder {
162170
this.routineType = routineInfo.routineType;
163171
this.creationTime = routineInfo.creationTime;
164172
this.description = routineInfo.description;
173+
this.determinismLevel = routineInfo.determinismLevel;
165174
this.lastModifiedTime = routineInfo.lastModifiedTime;
166175
this.language = routineInfo.language;
167176
this.argumentList = routineInfo.argumentList;
@@ -176,6 +185,7 @@ static class BuilderImpl extends Builder {
176185
this.routineType = routinePb.getRoutineType();
177186
this.creationTime = routinePb.getCreationTime();
178187
this.description = routinePb.getDescription();
188+
this.determinismLevel = routinePb.getDeterminismLevel();
179189
this.lastModifiedTime = routinePb.getLastModifiedTime();
180190
this.language = routinePb.getLanguage();
181191
if (routinePb.getArguments() != null) {
@@ -223,6 +233,12 @@ public Builder setDescription(String description) {
223233
return this;
224234
}
225235

236+
@Override
237+
public Builder setDeterminismLevel(String determinismLevel) {
238+
this.determinismLevel = determinismLevel;
239+
return this;
240+
}
241+
226242
@Override
227243
Builder setLastModifiedTime(Long lastModifiedMillis) {
228244
this.lastModifiedTime = lastModifiedMillis;
@@ -271,6 +287,7 @@ public RoutineInfo build() {
271287
this.routineType = builder.routineType;
272288
this.creationTime = builder.creationTime;
273289
this.description = builder.description;
290+
this.determinismLevel = builder.determinismLevel;
274291
this.lastModifiedTime = builder.lastModifiedTime;
275292
this.language = builder.language;
276293
this.argumentList = builder.argumentList;
@@ -304,6 +321,11 @@ public String getDescription() {
304321
return description;
305322
}
306323

324+
/** Returns the determinism level of the JavaScript UDF if defined. */
325+
public String getDeterminismLevel() {
326+
return determinismLevel;
327+
}
328+
307329
/**
308330
* Returns the last modification time of the routine, represented as milliseconds since the epoch.
309331
*/
@@ -354,6 +376,7 @@ public String toString() {
354376
.add("routineType", routineType)
355377
.add("creationTime", creationTime)
356378
.add("description", description)
379+
.add("determinismLevel", determinismLevel)
357380
.add("lastModifiedTime", lastModifiedTime)
358381
.add("language", language)
359382
.add("arguments", argumentList)
@@ -371,6 +394,7 @@ public int hashCode() {
371394
routineType,
372395
creationTime,
373396
description,
397+
determinismLevel,
374398
lastModifiedTime,
375399
language,
376400
argumentList,
@@ -412,6 +436,7 @@ Routine toPb() {
412436
.setDefinitionBody(getBody())
413437
.setCreationTime(getCreationTime())
414438
.setDescription(getDescription())
439+
.setDeterminismLevel(getDeterminismLevel())
415440
.setLastModifiedTime(getLastModifiedTime())
416441
.setLanguage(getLanguage());
417442
if (getRoutineId() != null) {
@@ -420,6 +445,9 @@ Routine toPb() {
420445
if (getArguments() != null) {
421446
routinePb.setArguments(Lists.transform(getArguments(), RoutineArgument.TO_PB_FUNCTION));
422447
}
448+
if (getReturnType() != null) {
449+
routinePb.setReturnType(getReturnType().toPb());
450+
}
423451
return routinePb;
424452
}
425453

google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/RoutineInfoTest.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ public class RoutineInfoTest {
2929
private static final String ROUTINE_TYPE = "SCALAR_FUNCTION";
3030
private static final Long CREATION_TIME = 10L;
3131
private static final String DESCRIPTION = "description";
32+
private static final String DETERMINISM = "DETERMINISTIC";
3233
private static final Long LAST_MODIFIED_TIME = 20L;
3334
private static final String LANGUAGE = "SQL";
3435

@@ -55,6 +56,7 @@ public class RoutineInfoTest {
5556
.setRoutineType(ROUTINE_TYPE)
5657
.setCreationTime(CREATION_TIME)
5758
.setDescription(DESCRIPTION)
59+
.setDeterminismLevel(DETERMINISM)
5860
.setLastModifiedTime(LAST_MODIFIED_TIME)
5961
.setLanguage(LANGUAGE)
6062
.setArguments(ARGUMENT_LIST)
@@ -81,6 +83,7 @@ public void testBuilder() {
8183
assertEquals(ROUTINE_TYPE, ROUTINE_INFO.getRoutineType());
8284
assertEquals(CREATION_TIME, ROUTINE_INFO.getCreationTime());
8385
assertEquals(DESCRIPTION, ROUTINE_INFO.getDescription());
86+
assertEquals(DETERMINISM, ROUTINE_INFO.getDeterminismLevel());
8487
assertEquals(LAST_MODIFIED_TIME, ROUTINE_INFO.getLastModifiedTime());
8588
assertEquals(LANGUAGE, ROUTINE_INFO.getLanguage());
8689
assertEquals(ARGUMENT_LIST, ROUTINE_INFO.getArguments());
@@ -97,6 +100,7 @@ public void testOf() {
97100
assertNull(routineInfo.getRoutineType());
98101
assertNull(routineInfo.getCreationTime());
99102
assertNull(routineInfo.getDescription());
103+
assertNull(routineInfo.getDeterminismLevel());
100104
assertNull(routineInfo.getLastModifiedTime());
101105
assertNull(routineInfo.getLanguage());
102106
assertNull(routineInfo.getArguments());
@@ -121,6 +125,7 @@ public void compareRoutineInfo(RoutineInfo expected, RoutineInfo value) {
121125
assertEquals(expected.getRoutineType(), value.getRoutineType());
122126
assertEquals(expected.getCreationTime(), value.getCreationTime());
123127
assertEquals(expected.getDescription(), value.getDescription());
128+
assertEquals(expected.getDeterminismLevel(), value.getDeterminismLevel());
124129
assertEquals(expected.getLastModifiedTime(), value.getLastModifiedTime());
125130
assertEquals(expected.getLanguage(), value.getLanguage());
126131
assertEquals(expected.getArguments(), value.getArguments());

google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/RoutineTest.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
public class RoutineTest {
3939

4040
private static final RoutineId ROUTINE_ID = RoutineId.of("dataset", "routine");
41+
private static final String DETERMINISM_LEVEL = "DETERMINISTIC";
4142
private static final String ETAG = "etag";
4243
private static final String ROUTINE_TYPE = "SCALAR_FUNCTION";
4344
private static final Long CREATION_TIME = 10L;
@@ -65,6 +66,7 @@ public class RoutineTest {
6566
.setEtag(ETAG)
6667
.setRoutineType(ROUTINE_TYPE)
6768
.setCreationTime(CREATION_TIME)
69+
.setDeterminismLevel(DETERMINISM_LEVEL)
6870
.setLastModifiedTime(LAST_MODIFIED_TIME)
6971
.setLanguage(LANGUAGE)
7072
.setArguments(ARGUMENT_LIST)
@@ -96,6 +98,7 @@ public void testBuilder() {
9698
.setEtag(ETAG)
9799
.setRoutineType(ROUTINE_TYPE)
98100
.setCreationTime(CREATION_TIME)
101+
.setDeterminismLevel(DETERMINISM_LEVEL)
99102
.setLastModifiedTime(LAST_MODIFIED_TIME)
100103
.setLanguage(LANGUAGE)
101104
.setArguments(ARGUMENT_LIST)
@@ -104,6 +107,7 @@ public void testBuilder() {
104107
.setBody(BODY)
105108
.build();
106109
assertEquals(ETAG, builtRoutine.getEtag());
110+
assertEquals(DETERMINISM_LEVEL, builtRoutine.getDeterminismLevel());
107111
assertSame(bigquery, builtRoutine.getBigQuery());
108112
}
109113

@@ -191,6 +195,7 @@ public void compareRoutineInfo(RoutineInfo expected, RoutineInfo value) {
191195
assertEquals(expected.getEtag(), value.getEtag());
192196
assertEquals(expected.getRoutineType(), value.getRoutineType());
193197
assertEquals(expected.getCreationTime(), value.getCreationTime());
198+
assertEquals(expected.getDeterminismLevel(), value.getDeterminismLevel());
194199
assertEquals(expected.getLastModifiedTime(), value.getLastModifiedTime());
195200
assertEquals(expected.getLanguage(), value.getLanguage());
196201
assertEquals(expected.getArguments(), value.getArguments());

google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/it/ITBigQueryTest.java

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1522,7 +1522,6 @@ public void testEmptyListRoutines() {
15221522

15231523
@Test
15241524
public void testRoutineLifecycle() throws InterruptedException {
1525-
15261525
String routineName = RemoteBigQueryHelper.generateRoutineName();
15271526
// Create a routine using SQL.
15281527
String sql =
@@ -1587,6 +1586,34 @@ public void testRoutineAPICreation() {
15871586
assertEquals(routine.getRoutineType(), "SCALAR_FUNCTION");
15881587
}
15891588

1589+
@Test
1590+
public void testRoutineAPICreationJavascriptUDF() {
1591+
String routineName = RemoteBigQueryHelper.generateRoutineName();
1592+
RoutineId routineId = RoutineId.of(ROUTINE_DATASET, routineName);
1593+
RoutineInfo routineInfo =
1594+
RoutineInfo.newBuilder(routineId)
1595+
.setLanguage("JAVASCRIPT")
1596+
.setRoutineType("SCALAR_FUNCTION")
1597+
.setDeterminismLevel("DETERMINISTIC")
1598+
.setArguments(
1599+
ImmutableList.of(
1600+
RoutineArgument.newBuilder()
1601+
.setName("instr")
1602+
.setKind("FIXED_TYPE")
1603+
.setDataType(StandardSQLDataType.newBuilder("STRING").build())
1604+
.build()))
1605+
.setReturnType(StandardSQLDataType.newBuilder("STRING").build())
1606+
.setBody("return instr.toUpperCase();")
1607+
.build();
1608+
1609+
Routine routine = bigquery.create(routineInfo);
1610+
assertNotNull(routine);
1611+
assertEquals(routine.getLanguage(), "JAVASCRIPT");
1612+
assertEquals(routine.getDeterminismLevel(), "DETERMINISTIC");
1613+
assertEquals(routine.getRoutineType(), "SCALAR_FUNCTION");
1614+
assertEquals(routine.getReturnType(), StandardSQLDataType.newBuilder("STRING").build());
1615+
}
1616+
15901617
@Test
15911618
public void testAuthorizeRoutine() {
15921619
String routineName = RemoteBigQueryHelper.generateRoutineName();

0 commit comments

Comments
 (0)