@Test public void bindStructWithArrayOfStructField() { Struct arrayElement1 = Struct.newBuilder().set("ff1").to("abc").build(); Struct arrayElement2 = Struct.newBuilder().set("ff1").to("def").build(); Struct p = Struct.newBuilder() .set("f1") .toStructArray(arrayElement1.getType(), asList(arrayElement1, arrayElement2)) .build(); List<Struct> rows = resultRows( Statement.newBuilder("SELECT * FROM UNNEST(@p.f1)").bind("p").to(p).build(), arrayElement1.getType()); assertThat(rows.get(0).getString(0)).isEqualTo("abc"); assertThat(rows.get(1).getString(0)).isEqualTo("def"); }
private static Struct s(String a, long b) { return Struct.newBuilder().set("a").to(a).set("b").to(b).build(); }
@Test public void pointRead() { Struct row = client.singleUse(TimestampBound.strong()).readRow(TABLE_NAME, Key.of("k1"), ALL_COLUMNS); assertThat(row).isNotNull(); assertThat(row.getString(0)).isEqualTo("k1"); assertThat(row.getString(1)).isEqualTo("v1"); // Ensure that the Struct implementation supports equality properly. assertThat(row) .isEqualTo(Struct.newBuilder().set("Key").to("k1").set("StringValue").to("v1").build()); }
@Test public void bindStructWithStructField() { Struct nestedStruct = Struct.newBuilder().set("ff1").to("abc").build(); Struct p = Struct.newBuilder().set("f1").to(nestedStruct).build(); Struct row = executeWithRowResultType( Statement.newBuilder("SELECT @p.f1.ff1").bind("p").to(p).build(), nestedStruct.getType()); assertThat(row.getString(0)).isEqualTo("abc"); }
@Test public void bindEmptyStruct() { Struct p = Struct.newBuilder().build(); Struct row = execute(Statement.newBuilder("SELECT @p IS NULL").bind("p").to(p).build(), Type.bool()); assertThat(row.getBoolean(0)).isFalse(); }
@Test public void bindStructWithNullStructField() { Type emptyStructType = Type.struct(new ArrayList<StructField>()); Struct p = Struct.newBuilder().set("f1").to(emptyStructType, null).build(); Struct row = execute(Statement.newBuilder("SELECT @p.f1 IS NULL").bind("p").to(p).build(), Type.bool()); assertThat(row.getBoolean(0)).isTrue(); }
@Test public void exceptionIfNextIsNotCalled() { ResultSet rs = ResultSets.forRows( Type.struct(Type.StructField.of("f1", Type.string())), Arrays.asList(Struct.newBuilder().set("f1").to("x").build())); expected.expect(IllegalStateException.class); rs.getCurrentRowAsStruct(); } }
@Test public void structArray() { Type elementType = Type.struct( Arrays.asList( Type.StructField.of("ff1", Type.string()), Type.StructField.of("ff2", Type.int64()))); List<Struct> arrayElements = Arrays.asList( Struct.newBuilder().set("ff1").to("v1").set("ff2").to(1).build(), null, null, Struct.newBuilder().set("ff1").to("v3").set("ff2").to(3).build()); Value v = Value.structArray(elementType, arrayElements); assertThat(v.isNull()).isFalse(); assertThat(v.getType().getArrayElementType()).isEqualTo(elementType); assertThat(v.getStructArray()).isEqualTo(arrayElements); assertThat(v.toString()).isEqualTo("[[v1, 1],NULL,NULL,[v3, 3]]"); }
@Test public void struct() { Struct struct = Struct.newBuilder().set("f1").to("v1").set("f2").to(30).build(); Value v1 = Value.struct(struct); assertThat(v1.getType()).isEqualTo(struct.getType()); assertThat(v1.isNull()).isFalse(); assertThat(v1.getStruct()).isEqualTo(struct); assertThat(v1.toString()).isEqualTo("[v1, 30]"); Value v2 = Value.struct(struct.getType(), struct); assertThat(v2).isEqualTo(v1); expectedException.expect(IllegalArgumentException.class); expectedException.expectMessage("Mismatch between struct value and type."); Value.struct(Type.struct(Arrays.asList(StructField.of("f3", Type.string()))), struct); }
@Test public void closeResultSet() { ResultSet rs = ResultSets.forRows( Type.struct(Type.StructField.of("f1", Type.string())), Arrays.asList(Struct.newBuilder().set("f1").to("x").build())); rs.close(); expected.expect(IllegalStateException.class); rs.getCurrentRowAsStruct(); }
@Test public void duplicateFields() { // Duplicate fields are allowed - some SQL queries produce this type of value. Struct struct = Struct.newBuilder().set("").to("x").set("").to(Value.int64(2)).build(); assertThat(struct.getType()) .isEqualTo( Type.struct( Type.StructField.of("", Type.string()), Type.StructField.of("", Type.int64()))); assertThat(struct.isNull(0)).isFalse(); assertThat(struct.isNull(1)).isFalse(); assertThat(struct.getString(0)).isEqualTo("x"); assertThat(struct.getLong(1)).isEqualTo(2); }
@Test public void unnamedFields() { Struct struct = Struct.newBuilder().add(Value.int64(2)).add(Value.int64(3)).build(); assertThat(struct.getType()) .isEqualTo( Type.struct( Type.StructField.of("", Type.int64()), Type.StructField.of("", Type.int64()))); assertThat(struct.getLong(0)).isEqualTo(2); assertThat(struct.getLong(1)).isEqualTo(3); }
@Test public void resultSetIterationWithStructColumns() { Type nestedStructType = Type.struct(Type.StructField.of("g1", Type.string())); Type type = Type.struct( Type.StructField.of("f1", nestedStructType), Type.StructField.of("f2", Type.int64())); Struct value1 = Struct.newBuilder().set("g1").to("abc").build(); Struct struct1 = Struct.newBuilder().set("f1").to(value1).set("f2").to((Long) null).build(); expected.expect(UnsupportedOperationException.class); expected.expectMessage("STRUCT-typed columns are not supported inside ResultSets."); ResultSets.forRows(type, Arrays.asList(struct1)); }
@Test public void structArrayInvalidType() { Type elementType = Type.struct( Arrays.asList( Type.StructField.of("ff1", Type.string()), Type.StructField.of("ff2", Type.int64()))); // Second element has INT64 first field, not STRING. List<Struct> arrayElements = Arrays.asList( Struct.newBuilder().set("ff1").to("1").set("ff2").to(1).build(), Struct.newBuilder().set("ff1").to(2).set("ff2").to(3).build()); expectedException.expect(IllegalArgumentException.class); expectedException.expectMessage("must have type STRUCT<ff1 STRING, ff2 INT64>"); Value.structArray(elementType, arrayElements); }
@Test public void bindStructWithUnnamedFields() { Struct p = Struct.newBuilder().add(Value.int64(1337)).add(Value.int64(7331)).build(); Struct row = executeWithRowResultType( Statement.newBuilder("SELECT * FROM UNNEST([@p])").bind("p").to(p).build(), p.getType()); assertThat(row.getLong(0)).isEqualTo(1337); assertThat(row.getLong(1)).isEqualTo(7331); }
@Test public void structArrayFieldNull() { Type elementType = Type.struct( Arrays.asList( Type.StructField.of("ff1", Type.string()), Type.StructField.of("ff2", Type.int64()))); Struct struct = Struct.newBuilder().set("f1").to("x").set("f2").toStructArray(elementType, null).build(); assertThat(struct.getType()) .isEqualTo( Type.struct( Type.StructField.of("f1", Type.string()), Type.StructField.of("f2", Type.array(elementType)))); assertThat(struct.isNull(0)).isFalse(); assertThat(struct.isNull(1)).isTrue(); }
@Test public void builder() { // These tests are basic: AbstractStructReaderTypesTest already covers all type getters. Struct struct = Struct.newBuilder() .set("f1") .to("x") .set("f2") .to(2) .set("f3") .to(Value.bool(null)) .build(); assertThat(struct.getType()) .isEqualTo( Type.struct( Type.StructField.of("f1", Type.string()), Type.StructField.of("f2", Type.int64()), Type.StructField.of("f3", Type.bool()))); assertThat(struct.isNull(0)).isFalse(); assertThat(struct.isNull(1)).isFalse(); assertThat(struct.isNull(2)).isTrue(); assertThat(struct.getString(0)).isEqualTo("x"); assertThat(struct.getLong(1)).isEqualTo(2); }
@Test public void bindStructWithDuplicateFieldNames() { Struct p = Struct.newBuilder() .set("f1") .to(Value.int64(1337)) .set("f1") .to(Value.string("1337")) .build(); Struct row = executeWithRowResultType( Statement.newBuilder("SELECT * FROM UNNEST([@p])").bind("p").to(p).build(), p.getType()); assertThat(row.getLong(0)).isEqualTo(1337); assertThat(row.getString(1)).isEqualTo("1337"); }
@Test public void invalidAmbiguousFieldAccess() { Struct p = Struct.newBuilder().set("f1").to(20).set("f1").to("abc").build(); expectedException.expect(isSpannerException(ErrorCode.INVALID_ARGUMENT)); expectedException.expectMessage("Struct field name f1 is ambiguous"); execute(Statement.newBuilder("SELECT @p.f1").bind("p").to(p).build(), Type.int64()); }
private Struct structValue() { return Struct.newBuilder() .set("f_int") .to(10) .set("f_bool") .to(false) .set("f_double") .to(3.4) .set("f_timestamp") .to(Timestamp.ofTimeMicroseconds(20)) .set("f_date") .to(Date.fromYearMonthDay(1, 3, 1)) .set("f_string") .to("hello") .set("f_bytes") .to(ByteArray.copyFrom("bytes")) .build(); }