From a3ee5e319882479e7233079b05c868866c80ad9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Hornych?= Date: Mon, 29 Jan 2024 16:27:07 +0100 Subject: [PATCH 1/4] docs: touch --- documentation/user/en/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/documentation/user/en/index.md b/documentation/user/en/index.md index 9fe00fee5..9dac12697 100644 --- a/documentation/user/en/index.md +++ b/documentation/user/en/index.md @@ -129,4 +129,4 @@ the first version to the general public. 1. [With product listing](solve/render-referenced-brand.md#product-listing) 2. [With involved categories listing](solve/render-referenced-brand.md#category-listing) 4. [Handle images & binaries](solve/handling-images-binaries.md) -5. [Model price policies](solve/model-price-policies.md) +5. [Model price policies](solve/model-price-policies.md) \ No newline at end of file From 5e462b2df64118f0fae6cf546bbd2acc88429137 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Novotn=C3=BD?= Date: Tue, 30 Jan 2024 09:02:06 +0100 Subject: [PATCH 2/4] doc: swapped formats fix Thx. to Patrik Komurka. --- documentation/research/en/assignment/model/data_types.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/documentation/research/en/assignment/model/data_types.md b/documentation/research/en/assignment/model/data_types.md index 471e48b20..e42529f1e 100644 --- a/documentation/research/en/assignment/model/data_types.md +++ b/documentation/research/en/assignment/model/data_types.md @@ -25,8 +25,8 @@ evitaDB data types are limited to following list: - [BigDecimal](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/math/BigDecimal.html), formatted as `1.124` - [OffsetDateTime](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/time/OffsetDateTime.html), formatted as `2021-01-01T00:00:00+01:00` ([offset needs to be maintained](https://spin.atomicobject.com/2016/07/06/time-zones-offsets/)) - [LocalDateTime](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/time/LocalDateTime.html), formatted as `2021-01-01T00:00:00` -- [LocalDate](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/time/LocalDate.html), formatted as `00:00:00` -- [LocalTime](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/time/LocalTime.html), formatted as `2021-01-01` +- [LocalDate](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/time/LocalDate.html), formatted as `2021-01-01` +- [LocalTime](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/time/LocalTime.html), formatted as `00:00:00` - [DateTimeRange](#datetimerange), formatted as `[2021-01-01T00:00:00+01:00,2022-01-01T00:00:00+01:00]` - [BigDecimalNumberRange](#numberrange), formatted as `[1.24,78]` - [LongNumberRange](#numberrange), formatted as `[5,9]` From f41b5a9ccf90c9eebefe63488faaa667303df911 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Novotn=C3=BD?= Date: Tue, 30 Jan 2024 09:11:59 +0100 Subject: [PATCH 3/4] doc: swapped formats fix Thx. to Patrik Komurka. --- documentation/user/en/use/data-types.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/documentation/user/en/use/data-types.md b/documentation/user/en/use/data-types.md index e740b9c34..73db3df69 100644 --- a/documentation/user/en/use/data-types.md +++ b/documentation/user/en/use/data-types.md @@ -47,9 +47,9 @@ evitaDB data types are limited to following list: - [LocalDateTime](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/time/LocalDateTime.html), formatted as `2021-01-01T00:00:00` - [LocalDate](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/time/LocalDate.html), - formatted as `00:00:00` -- [LocalTime](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/time/LocalTime.html), formatted as `2021-01-01` +- [LocalTime](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/time/LocalTime.html), + formatted as `00:00:00` - [DateTimeRange](#datetimerange), formatted as `[2021-01-01T00:00:00+01:00,2022-01-01T00:00:00+01:00]` - [BigDecimalNumberRange](#numberrange), From 79eb6862e145ca92629d9fac4dc0b63f38550e02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Novotn=C3=BD?= Date: Tue, 30 Jan 2024 15:45:19 +0100 Subject: [PATCH 4/4] fix(#442): Regression: constraints were not excluded when provided NULL arguments This issue was connected with changes in https://github.com/FgForrest/evitaDB/issues/413. This introduced problem when null values were possible to inject into the constraint via this declaration: ```java final Integer nullInteger = null; final EntityPrimaryKeyInSet entityPrimaryKeyInSet = entityPrimaryKeyInSet(nullInteger); assertNull(entityPrimaryKeyInSet); ``` --- .../api/query/filter/AttributeInSetTest.java | 19 +++++++++++ .../filter/EntityPrimaryKeyInSetTest.java | 19 +++++++++++ .../query/filter/PriceInPriceListsTest.java | 19 +++++++++++ .../evitadb/api/query/QueryConstraints.java | 34 +++++++++++++++++-- 4 files changed, 89 insertions(+), 2 deletions(-) diff --git a/evita_functional_tests/src/test/java/io/evitadb/api/query/filter/AttributeInSetTest.java b/evita_functional_tests/src/test/java/io/evitadb/api/query/filter/AttributeInSetTest.java index 48103ea10..2ba5f031e 100644 --- a/evita_functional_tests/src/test/java/io/evitadb/api/query/filter/AttributeInSetTest.java +++ b/evita_functional_tests/src/test/java/io/evitadb/api/query/filter/AttributeInSetTest.java @@ -41,6 +41,25 @@ void shouldCreateViaFactoryClassWorkAsExpected() { assertArrayEquals(new Comparable[] {1, 5}, attributeInSet.getAttributeValues()); } + @Test + void shouldCreateViaFactoryClassWorkAsExpectedNullInArray() { + final AttributeInSet attributeInSet = attributeInSet("refs", 1, null, 5); + assertArrayEquals(new Comparable[] {1, 5}, attributeInSet.getAttributeValues()); + } + + @Test + void shouldCreateViaFactoryClassWorkAsExpectedForNullVariable() { + final Integer nullInteger = null; + final AttributeInSet attributeInSet = attributeInSet("refs", nullInteger); + assertNull(attributeInSet); + } + + @Test + void shouldCreateViaFactoryClassWorkAsExpectedNullValueInArray() { + final AttributeInSet attributeInSet = attributeInSet("refs", new Integer[0]); + assertArrayEquals(new Comparable[0], attributeInSet.getAttributeValues()); + } + @Test void shouldRecognizeApplicability() { assertFalse(new AttributeInSet(null).isApplicable()); diff --git a/evita_functional_tests/src/test/java/io/evitadb/api/query/filter/EntityPrimaryKeyInSetTest.java b/evita_functional_tests/src/test/java/io/evitadb/api/query/filter/EntityPrimaryKeyInSetTest.java index acb936ef8..b5daaece4 100644 --- a/evita_functional_tests/src/test/java/io/evitadb/api/query/filter/EntityPrimaryKeyInSetTest.java +++ b/evita_functional_tests/src/test/java/io/evitadb/api/query/filter/EntityPrimaryKeyInSetTest.java @@ -41,6 +41,25 @@ void shouldCreateViaFactoryClassWorkAsExpected() { assertArrayEquals(new int[] {1, 5, 7}, entityPrimaryKeyInSet.getPrimaryKeys()); } + @Test + void shouldCreateViaFactoryClassWorkAsExpectedNullInArray() { + final EntityPrimaryKeyInSet entityPrimaryKeyInSet = entityPrimaryKeyInSet(1, null, 7); + assertArrayEquals(new int[] {1, 7}, entityPrimaryKeyInSet.getPrimaryKeys()); + } + + @Test + void shouldCreateViaFactoryClassWorkAsExpectedForNullVariable() { + final Integer nullInteger = null; + final EntityPrimaryKeyInSet entityPrimaryKeyInSet = entityPrimaryKeyInSet(nullInteger); + assertNull(entityPrimaryKeyInSet); + } + + @Test + void shouldCreateViaFactoryClassWorkAsExpectedNullValueInArray() { + final EntityPrimaryKeyInSet entityPrimaryKeyInSet = entityPrimaryKeyInSet(new Integer[0]); + assertArrayEquals(new int[0], entityPrimaryKeyInSet.getPrimaryKeys()); + } + @Test void shouldRecognizeApplicability() { assertTrue(new EntityPrimaryKeyInSet().isApplicable()); diff --git a/evita_functional_tests/src/test/java/io/evitadb/api/query/filter/PriceInPriceListsTest.java b/evita_functional_tests/src/test/java/io/evitadb/api/query/filter/PriceInPriceListsTest.java index aa56299e8..e8e499010 100644 --- a/evita_functional_tests/src/test/java/io/evitadb/api/query/filter/PriceInPriceListsTest.java +++ b/evita_functional_tests/src/test/java/io/evitadb/api/query/filter/PriceInPriceListsTest.java @@ -41,6 +41,25 @@ void shouldCreateViaFactoryClassWorkAsExpected() { assertArrayEquals(new String[] {"basic", "reference"}, priceInPriceLists.getPriceLists()); } + @Test + void shouldCreateViaFactoryClassWorkAsExpectedNullInArray() { + final PriceInPriceLists priceInPriceLists = priceInPriceLists("basic", null, "reference"); + assertArrayEquals(new String[] {"basic", "reference"}, priceInPriceLists.getPriceLists()); + } + + @Test + void shouldCreateViaFactoryClassWorkAsExpectedForNullVariable() { + final String nullString = null; + final PriceInPriceLists priceInPriceLists = priceInPriceLists(nullString); + assertNull(priceInPriceLists); + } + + @Test + void shouldCreateViaFactoryClassWorkAsExpectedNullValueInArray() { + final PriceInPriceLists priceInPriceLists = priceInPriceLists(new String[0]); + assertArrayEquals(new String[0], priceInPriceLists.getPriceLists()); + } + @Test void shouldRecognizeApplicability() { assertTrue(new PriceInPriceLists(new String[0]).isApplicable()); diff --git a/evita_query/src/main/java/io/evitadb/api/query/QueryConstraints.java b/evita_query/src/main/java/io/evitadb/api/query/QueryConstraints.java index a8e3420c3..ac73403df 100644 --- a/evita_query/src/main/java/io/evitadb/api/query/QueryConstraints.java +++ b/evita_query/src/main/java/io/evitadb/api/query/QueryConstraints.java @@ -690,7 +690,19 @@ static PriceInPriceLists priceInPriceLists(@Nullable String... priceList) { if (priceList == null) { return null; } - return new PriceInPriceLists(priceList); + // if the array is empty - it was deliberate action which needs to produce empty result of the query + if (priceList.length == 0) { + return new PriceInPriceLists(priceList); + } + final String[] normalizeNames = Arrays.stream(priceList).filter(Objects::nonNull).filter(it -> !it.isBlank()).toArray(String[]::new); + // the array was not empty, but contains only null values - this may not be deliberate action - for example + // the initalization was like `priceInPriceLists(nullVariable)` and this should exclude the constraint + if (normalizeNames.length == 0) { + return null; + } + // otherwise propagate only non-null values + return normalizeNames.length == priceList.length ? + new PriceInPriceLists(priceList) : new PriceInPriceLists(normalizeNames); } /** @@ -1537,13 +1549,19 @@ static AttributeInRange attributeInRangeNow(@Nullable String attributeName) { @SuppressWarnings("unchecked") @Nullable static AttributeInSet attributeInSet(@Nullable String attributeName, @Nullable T... set) { + // if the array is empty - it was deliberate action which needs to produce empty result of the query if (attributeName == null || set == null) { return null; } final List args = Arrays.stream(set).filter(Objects::nonNull).toList(); if (args.size() == set.length) { return new AttributeInSet(attributeName, set); + } else if (args.isEmpty()) { + // the array was not empty, but contains only null values - this may not be deliberate action - for example + // the initalization was like `attributeInSet("attrName", nullVariable)` and this should exclude the constraint + return null; } else { + // otherwise propagate only non-null values final T[] limitedSet = (T[]) Array.newInstance(set.getClass().getComponentType(), args.size()); for (int i = 0; i < args.size(); i++) { limitedSet[i] = args.get(i); @@ -1805,7 +1823,19 @@ static EntityPrimaryKeyInSet entityPrimaryKeyInSet(@Nullable Integer... primaryK if (primaryKey == null) { return null; } - return new EntityPrimaryKeyInSet(primaryKey); + // if the array is empty - it was deliberate action which needs to produce empty result of the query + if (primaryKey.length == 0) { + return new EntityPrimaryKeyInSet(primaryKey); + } + final Integer[] normalizedPks = Arrays.stream(primaryKey).filter(Objects::nonNull).toArray(Integer[]::new); + // the array was not empty, but contains only null values - this may not be deliberate action - for example + // the initalization was like `entityPrimaryKeyInSet(nullVariable)` and this should exclude the constraint + if (normalizedPks.length == 0) { + return null; + } + // otherwise propagate only non-null values + return normalizedPks.length == primaryKey.length ? + new EntityPrimaryKeyInSet(primaryKey) : new EntityPrimaryKeyInSet(normalizedPks); } /**