From 47b2201362cc85f09ed09b5a170c03b8c11bbe2e Mon Sep 17 00:00:00 2001 From: candiduslynx Date: Mon, 14 Aug 2023 17:58:27 +0300 Subject: [PATCH 1/2] duration --- .../java/io/cloudquery/scalar/Binary.java | 5 +- .../main/java/io/cloudquery/scalar/Bool.java | 5 +- .../java/io/cloudquery/scalar/DateDay.java | 4 +- .../java/io/cloudquery/scalar/DateMilli.java | 4 +- .../java/io/cloudquery/scalar/Duration.java | 99 +++++++++++++ .../io/cloudquery/scalar/DurationTest.java | 133 ++++++++++++++++++ 6 files changed, 241 insertions(+), 9 deletions(-) create mode 100644 lib/src/main/java/io/cloudquery/scalar/Duration.java create mode 100644 lib/src/test/java/io/cloudquery/scalar/DurationTest.java diff --git a/lib/src/main/java/io/cloudquery/scalar/Binary.java b/lib/src/main/java/io/cloudquery/scalar/Binary.java index c21259f..3e0c0de 100644 --- a/lib/src/main/java/io/cloudquery/scalar/Binary.java +++ b/lib/src/main/java/io/cloudquery/scalar/Binary.java @@ -59,9 +59,8 @@ public void set(Object value) throws ValidationException { return; } - if (value instanceof String string) { - this.valid = true; - this.value = Base64.decodeBase64(string); + if (value instanceof CharSequence sequence) { + this.value = Base64.decodeBase64(sequence.toString()); return; } diff --git a/lib/src/main/java/io/cloudquery/scalar/Bool.java b/lib/src/main/java/io/cloudquery/scalar/Bool.java index 2fb4f03..aac8f39 100644 --- a/lib/src/main/java/io/cloudquery/scalar/Bool.java +++ b/lib/src/main/java/io/cloudquery/scalar/Bool.java @@ -1,6 +1,7 @@ package io.cloudquery.scalar; import org.apache.arrow.vector.types.pojo.ArrowType; +import org.apache.commons.codec.binary.Base64; public class Bool implements Scalar { protected boolean value; @@ -56,9 +57,9 @@ public void set(Object value) throws ValidationException { return; } - if (value instanceof String string) { + if (value instanceof CharSequence sequence) { this.valid = true; - this.value = Boolean.parseBoolean(string); + this.value = Boolean.parseBoolean(sequence.toString()); return; } diff --git a/lib/src/main/java/io/cloudquery/scalar/DateDay.java b/lib/src/main/java/io/cloudquery/scalar/DateDay.java index 843c0bb..cfd3d7f 100644 --- a/lib/src/main/java/io/cloudquery/scalar/DateDay.java +++ b/lib/src/main/java/io/cloudquery/scalar/DateDay.java @@ -63,9 +63,9 @@ public void set(Object value) throws ValidationException { return; } - if (value instanceof String string) { + if (value instanceof CharSequence sequence) { this.valid = true; - this.value = Integer.parseInt(string); + this.value = Integer.parseInt(sequence.toString()); return; } diff --git a/lib/src/main/java/io/cloudquery/scalar/DateMilli.java b/lib/src/main/java/io/cloudquery/scalar/DateMilli.java index 0201eef..eb6c9fa 100644 --- a/lib/src/main/java/io/cloudquery/scalar/DateMilli.java +++ b/lib/src/main/java/io/cloudquery/scalar/DateMilli.java @@ -69,9 +69,9 @@ public void set(Object value) throws ValidationException { return; } - if (value instanceof String string) { + if (value instanceof CharSequence sequence) { this.valid = true; - this.value = Long.parseLong(string); + this.value = Long.parseLong(sequence.toString()); return; } diff --git a/lib/src/main/java/io/cloudquery/scalar/Duration.java b/lib/src/main/java/io/cloudquery/scalar/Duration.java new file mode 100644 index 0000000..3691428 --- /dev/null +++ b/lib/src/main/java/io/cloudquery/scalar/Duration.java @@ -0,0 +1,99 @@ +package io.cloudquery.scalar; + +import org.apache.arrow.vector.types.TimeUnit; +import org.apache.arrow.vector.types.pojo.ArrowType; + +public class Duration implements Scalar { + protected java.time.Duration value; + + // TODO: add more units support later + private static final ArrowType dt = new ArrowType.Duration(TimeUnit.MILLISECOND); + + public Duration() { + } + + public Duration(Object value) throws ValidationException { + this.set(value); + } + + @Override + public String toString() { + if (this.value != null) { + return this.value.toString(); + } + return NULL_VALUE_STRING; + } + + @Override + public boolean isValid() { + return this.value != null; + } + + @Override + public ArrowType dataType() { + return dt; + } + + @Override + public void set(Object value) throws ValidationException { + if (value == null) { + this.value = null; + return; + } + + if (value instanceof Scalar scalar) { + if (!scalar.isValid()) { + this.value = null; + return; + } + + if (scalar instanceof Duration duration) { + this.value = duration.value; + return; + } + + this.set(scalar.get()); + return; + } + + if (value instanceof java.time.Duration duration) { + this.value = duration; + return; + } + + if (value instanceof Integer integer) { + this.value = java.time.Duration.ofMillis(integer); + return; + } + + if (value instanceof Long longValue) { + this.value = java.time.Duration.ofMillis(longValue); + return; + } + + if (value instanceof CharSequence sequence) { + this.value = java.time.Duration.parse(sequence); + return; + } + + throw new ValidationException(ValidationException.NO_CONVERSION_AVAILABLE, this.dataType(), value); + } + + @Override + public Object get() { + return this.value; // null or proper value + } + + @Override + public boolean equals(Object other) { + if (other == null) { + return false; + } + + if (!(other instanceof Duration o)) { + return false; + } + + return this.value == o.value || this.value.equals(o.value); + } +} diff --git a/lib/src/test/java/io/cloudquery/scalar/DurationTest.java b/lib/src/test/java/io/cloudquery/scalar/DurationTest.java new file mode 100644 index 0000000..1003226 --- /dev/null +++ b/lib/src/test/java/io/cloudquery/scalar/DurationTest.java @@ -0,0 +1,133 @@ +package io.cloudquery.scalar; + +import org.apache.arrow.vector.types.TimeUnit; +import org.apache.arrow.vector.types.pojo.ArrowType; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + + +public class DurationTest { + @Test + public void testNew() { + assertDoesNotThrow(() -> { + new Duration(); + }); + } + + @Test + public void testNewWithValidParam() { + assertDoesNotThrow(() -> { + new Duration(1); + new Duration("PT8H6M12.345S"); + new Duration(java.time.Duration.ZERO); + new Duration(java.time.Duration.ofNanos(1)); + + Scalar s = new Duration(java.time.Duration.ZERO); + new Duration(s); + }); + } + + @Test + public void testNewWithInvalidParam() { + assertThrows(ValidationException.class, () -> { + new Duration(false); + }); + } + + @Test + public void testToString() { + Duration duration = new Duration(); + assertEquals(Scalar.NULL_VALUE_STRING, duration.toString()); + + assertDoesNotThrow(() -> { + duration.set(1); + }); + assertEquals("PT0.001S", duration.toString()); + + assertDoesNotThrow(() -> { + duration.set(java.time.Duration.ofDays(1L)); + }); + assertEquals("PT24H", duration.toString()); + } + + @Test + public void testDataType() { + Duration duration = new Duration(); + assertEquals(new ArrowType.Duration(TimeUnit.MILLISECOND), duration.dataType()); + } + + @Test + public void testIsValid() { + Duration duration = new Duration(); + assertFalse(duration.isValid()); + + assertDoesNotThrow(() -> { + duration.set(1L); + }); + assertTrue(duration.isValid()); + } + + @Test + public void testSet() { + Duration duration = new Duration(); + assertDoesNotThrow(() -> { + duration.set(1); + duration.set(1L); + duration.set("PT8H6M12.345S"); + duration.set(java.time.Duration.ZERO); + + Scalar s = new Duration(java.time.Duration.ZERO); + duration.set(s); + }); + } + + @Test + public void testSetWithInvalidParam() { + Duration duration = new Duration(); + assertThrows(ValidationException.class, () -> { + duration.set(false); + }); + } + + @Test + public void testGet() { + Duration duration = new Duration(); + assertFalse(duration.isValid()); + assertNull(duration.get()); + + assertDoesNotThrow(() -> { + duration.set(-1L); + }); + assertTrue(duration.isValid()); + assertEquals(java.time.Duration.ofMillis(-1L), duration.get()); + + assertDoesNotThrow(() -> { + duration.set(java.time.Duration.ZERO); + }); + assertTrue(duration.isValid()); + assertEquals(java.time.Duration.ZERO, duration.get()); + } + + @Test + public void testEquals() { + Duration a = new Duration(); + Duration b = new Duration(); + assertEquals(a, b); + assertNotEquals(a, null); + assertNotEquals(a, new Bool()); // we can't cast Bool to Duration + assertNotEquals(null, a); + + assertDoesNotThrow(() -> { + a.set(-1L); + }); + assertNotEquals(a, b); + + assertDoesNotThrow(() -> { + for (Object obj : new Object[]{null, 0, 0L, -1, -1L, 1, 1L, "PT8H6M12.345S", java.time.Duration.ZERO}) { + a.set(obj); + assertEquals(a, new Duration(obj)); + } + }); + } +} From e93a624c829de5f726f0a6bc9a737dd8f0874cc9 Mon Sep 17 00:00:00 2001 From: candiduslynx Date: Mon, 14 Aug 2023 18:11:23 +0300 Subject: [PATCH 2/2] char sequence fix --- lib/src/main/java/io/cloudquery/scalar/Binary.java | 1 + lib/src/main/java/io/cloudquery/scalar/Bool.java | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/main/java/io/cloudquery/scalar/Binary.java b/lib/src/main/java/io/cloudquery/scalar/Binary.java index 3e0c0de..76844ae 100644 --- a/lib/src/main/java/io/cloudquery/scalar/Binary.java +++ b/lib/src/main/java/io/cloudquery/scalar/Binary.java @@ -60,6 +60,7 @@ public void set(Object value) throws ValidationException { } if (value instanceof CharSequence sequence) { + this.valid = true; this.value = Base64.decodeBase64(sequence.toString()); return; } diff --git a/lib/src/main/java/io/cloudquery/scalar/Bool.java b/lib/src/main/java/io/cloudquery/scalar/Bool.java index aac8f39..27b2955 100644 --- a/lib/src/main/java/io/cloudquery/scalar/Bool.java +++ b/lib/src/main/java/io/cloudquery/scalar/Bool.java @@ -1,7 +1,6 @@ package io.cloudquery.scalar; import org.apache.arrow.vector.types.pojo.ArrowType; -import org.apache.commons.codec.binary.Base64; public class Bool implements Scalar { protected boolean value;