From d135b1e686aa0219268352cedb7c7583425f9be9 Mon Sep 17 00:00:00 2001 From: Gani Georgiev Date: Wed, 2 Apr 2025 23:25:42 +0300 Subject: [PATCH] added more geoPoint field acccess tests --- core/collection_import_test.go | 2 +- core/record_field_resolver_runner.go | 4 ++-- core/record_field_resolver_test.go | 7 +++++++ tests/data/data.db | Bin 344064 -> 344064 bytes tools/search/filter.go | 29 ++++++++++++++------------- 5 files changed, 25 insertions(+), 17 deletions(-) diff --git a/core/collection_import_test.go b/core/collection_import_test.go index 74c1201f..74df2f6e 100644 --- a/core/collection_import_test.go +++ b/core/collection_import_test.go @@ -170,7 +170,7 @@ func TestImportCollections(t *testing.T) { expectedCollectionFields := map[string]int{ core.CollectionNameAuthOrigins: 6, "nologin": 10, - "demo1": 18, + "demo1": 19, "demo2": 5, "demo3": 5, "demo4": 16, diff --git a/core/record_field_resolver_runner.go b/core/record_field_resolver_runner.go index 77f9b8cc..412e330b 100644 --- a/core/record_field_resolver_runner.go +++ b/core/record_field_resolver_runner.go @@ -419,8 +419,8 @@ func (r *runner) processActiveProps() (*search.ResolverResult, error) { return nil, fmt.Errorf("non-filterable field %q", prop) } - // json field -> treat the rest of the props as json path - // @todo consider converting to "JSONExtractable" interface + // json or geoPoint field -> treat the rest of the props as json path + // @todo consider converting to "JSONExtractable" interface with optional extra validation for the remaining props? if field != nil && (field.Type() == FieldTypeJSON || field.Type() == FieldTypeGeoPoint) { var jsonPath strings.Builder for j, p := range r.activeProps[i+1:] { diff --git a/core/record_field_resolver_test.go b/core/record_field_resolver_test.go index 3a45f64c..629d1e67 100644 --- a/core/record_field_resolver_test.go +++ b/core/record_field_resolver_test.go @@ -518,6 +518,13 @@ func TestRecordFieldResolverUpdateQuery(t *testing.T) { false, "SELECT DISTINCT `demo4`.* FROM `demo4` LEFT JOIN json_each(CASE WHEN json_valid([[demo4.self_rel_many]]) THEN [[demo4.self_rel_many]] ELSE json_array([[demo4.self_rel_many]]) END) `demo4_self_rel_many_je` LEFT JOIN `demo4` `demo4_self_rel_many` ON [[demo4_self_rel_many.id]] = [[demo4_self_rel_many_je.value]] WHERE ((CASE WHEN json_valid([[demo4.json_object]]) THEN JSON_EXTRACT([[demo4.json_object]], '$') ELSE JSON_EXTRACT(json_object('pb', [[demo4.json_object]]), '$.pb') END) IS {:TEST} OR (CASE WHEN json_valid([[demo4.json_object]]) THEN JSON_EXTRACT([[demo4.json_object]], '$') ELSE JSON_EXTRACT(json_object('pb', [[demo4.json_object]]), '$.pb') END) IS NOT {:TEST} OR {:TEST} IS (CASE WHEN json_valid([[demo4.json_object]]) THEN JSON_EXTRACT([[demo4.json_object]], '$') ELSE JSON_EXTRACT(json_object('pb', [[demo4.json_object]]), '$.pb') END) OR {:TEST} IS NOT (CASE WHEN json_valid([[demo4.json_object]]) THEN JSON_EXTRACT([[demo4.json_object]], '$') ELSE JSON_EXTRACT(json_object('pb', [[demo4.json_object]]), '$.pb') END) OR (CASE WHEN json_valid([[demo4.json_object]]) THEN JSON_EXTRACT([[demo4.json_object]], '$') ELSE JSON_EXTRACT(json_object('pb', [[demo4.json_object]]), '$.pb') END) IS NULL OR (CASE WHEN json_valid([[demo4.json_object]]) THEN JSON_EXTRACT([[demo4.json_object]], '$') ELSE JSON_EXTRACT(json_object('pb', [[demo4.json_object]]), '$.pb') END) IS NOT NULL OR NULL IS (CASE WHEN json_valid([[demo4.json_object]]) THEN JSON_EXTRACT([[demo4.json_object]], '$') ELSE JSON_EXTRACT(json_object('pb', [[demo4.json_object]]), '$.pb') END) OR NULL IS NOT (CASE WHEN json_valid([[demo4.json_object]]) THEN JSON_EXTRACT([[demo4.json_object]], '$') ELSE JSON_EXTRACT(json_object('pb', [[demo4.json_object]]), '$.pb') END) OR (CASE WHEN json_valid([[demo4.json_object]]) THEN JSON_EXTRACT([[demo4.json_object]], '$') ELSE JSON_EXTRACT(json_object('pb', [[demo4.json_object]]), '$.pb') END) IS 1 OR (CASE WHEN json_valid([[demo4.json_object]]) THEN JSON_EXTRACT([[demo4.json_object]], '$') ELSE JSON_EXTRACT(json_object('pb', [[demo4.json_object]]), '$.pb') END) IS NOT 1 OR 1 IS (CASE WHEN json_valid([[demo4.json_object]]) THEN JSON_EXTRACT([[demo4.json_object]], '$') ELSE JSON_EXTRACT(json_object('pb', [[demo4.json_object]]), '$.pb') END) OR 1 IS NOT (CASE WHEN json_valid([[demo4.json_object]]) THEN JSON_EXTRACT([[demo4.json_object]], '$') ELSE JSON_EXTRACT(json_object('pb', [[demo4.json_object]]), '$.pb') END) OR (CASE WHEN json_valid([[demo4.json_object]]) THEN JSON_EXTRACT([[demo4.json_object]], '$') ELSE JSON_EXTRACT(json_object('pb', [[demo4.json_object]]), '$.pb') END) IS (CASE WHEN json_valid([[demo4.json_object]]) THEN JSON_EXTRACT([[demo4.json_object]], '$') ELSE JSON_EXTRACT(json_object('pb', [[demo4.json_object]]), '$.pb') END) OR (CASE WHEN json_valid([[demo4.json_object]]) THEN JSON_EXTRACT([[demo4.json_object]], '$') ELSE JSON_EXTRACT(json_object('pb', [[demo4.json_object]]), '$.pb') END) IS NOT (CASE WHEN json_valid([[demo4.json_object]]) THEN JSON_EXTRACT([[demo4.json_object]], '$') ELSE JSON_EXTRACT(json_object('pb', [[demo4.json_object]]), '$.pb') END) OR (CASE WHEN json_valid([[demo4.json_object]]) THEN JSON_EXTRACT([[demo4.json_object]], '$') ELSE JSON_EXTRACT(json_object('pb', [[demo4.json_object]]), '$.pb') END) IS [[demo4.title]] OR [[demo4.title]] IS NOT (CASE WHEN json_valid([[demo4.json_object]]) THEN JSON_EXTRACT([[demo4.json_object]], '$') ELSE JSON_EXTRACT(json_object('pb', [[demo4.json_object]]), '$.pb') END) OR (((CASE WHEN json_valid([[demo4_self_rel_many.json_object]]) THEN JSON_EXTRACT([[demo4_self_rel_many.json_object]], '$') ELSE JSON_EXTRACT(json_object('pb', [[demo4_self_rel_many.json_object]]), '$.pb') END) IS {:TEST}) AND (NOT EXISTS (SELECT 1 FROM (SELECT (CASE WHEN json_valid([[__mm_demo4_self_rel_many.json_object]]) THEN JSON_EXTRACT([[__mm_demo4_self_rel_many.json_object]], '$') ELSE JSON_EXTRACT(json_object('pb', [[__mm_demo4_self_rel_many.json_object]]), '$.pb') END) as [[multiMatchValue]] FROM `demo4` `__mm_demo4` LEFT JOIN json_each(CASE WHEN json_valid([[__mm_demo4.self_rel_many]]) THEN [[__mm_demo4.self_rel_many]] ELSE json_array([[__mm_demo4.self_rel_many]]) END) `__mm_demo4_self_rel_many_je` LEFT JOIN `demo4` `__mm_demo4_self_rel_many` ON [[__mm_demo4_self_rel_many.id]] = [[__mm_demo4_self_rel_many_je.value]] WHERE `__mm_demo4`.`id` = `demo4`.`id`) {{__smTEST}} WHERE NOT ([[__smTEST.multiMatchValue]] IS {:TEST})))) OR ((NULL IS (CASE WHEN json_valid([[demo4_self_rel_many.json_object]]) THEN JSON_EXTRACT([[demo4_self_rel_many.json_object]], '$') ELSE JSON_EXTRACT(json_object('pb', [[demo4_self_rel_many.json_object]]), '$.pb') END)) AND (NOT EXISTS (SELECT 1 FROM (SELECT (CASE WHEN json_valid([[__mm_demo4_self_rel_many.json_object]]) THEN JSON_EXTRACT([[__mm_demo4_self_rel_many.json_object]], '$') ELSE JSON_EXTRACT(json_object('pb', [[__mm_demo4_self_rel_many.json_object]]), '$.pb') END) as [[multiMatchValue]] FROM `demo4` `__mm_demo4` LEFT JOIN json_each(CASE WHEN json_valid([[__mm_demo4.self_rel_many]]) THEN [[__mm_demo4.self_rel_many]] ELSE json_array([[__mm_demo4.self_rel_many]]) END) `__mm_demo4_self_rel_many_je` LEFT JOIN `demo4` `__mm_demo4_self_rel_many` ON [[__mm_demo4_self_rel_many.id]] = [[__mm_demo4_self_rel_many_je.value]] WHERE `__mm_demo4`.`id` = `demo4`.`id`) {{__smTEST}} WHERE NOT (NULL IS [[__smTEST.multiMatchValue]])))) OR (((CASE WHEN json_valid([[demo4_self_rel_many.json_object]]) THEN JSON_EXTRACT([[demo4_self_rel_many.json_object]], '$') ELSE JSON_EXTRACT(json_object('pb', [[demo4_self_rel_many.json_object]]), '$.pb') END) IS (CASE WHEN json_valid([[demo4_self_rel_many.json_object]]) THEN JSON_EXTRACT([[demo4_self_rel_many.json_object]], '$') ELSE JSON_EXTRACT(json_object('pb', [[demo4_self_rel_many.json_object]]), '$.pb') END)) AND (NOT EXISTS (SELECT 1 FROM (SELECT (CASE WHEN json_valid([[__mm_demo4_self_rel_many.json_object]]) THEN JSON_EXTRACT([[__mm_demo4_self_rel_many.json_object]], '$') ELSE JSON_EXTRACT(json_object('pb', [[__mm_demo4_self_rel_many.json_object]]), '$.pb') END) as [[multiMatchValue]] FROM `demo4` `__mm_demo4` LEFT JOIN json_each(CASE WHEN json_valid([[__mm_demo4.self_rel_many]]) THEN [[__mm_demo4.self_rel_many]] ELSE json_array([[__mm_demo4.self_rel_many]]) END) `__mm_demo4_self_rel_many_je` LEFT JOIN `demo4` `__mm_demo4_self_rel_many` ON [[__mm_demo4_self_rel_many.id]] = [[__mm_demo4_self_rel_many_je.value]] WHERE `__mm_demo4`.`id` = `demo4`.`id`) {{__mlTEST}} LEFT JOIN (SELECT (CASE WHEN json_valid([[__mm_demo4_self_rel_many.json_object]]) THEN JSON_EXTRACT([[__mm_demo4_self_rel_many.json_object]], '$') ELSE JSON_EXTRACT(json_object('pb', [[__mm_demo4_self_rel_many.json_object]]), '$.pb') END) as [[multiMatchValue]] FROM `demo4` `__mm_demo4` LEFT JOIN json_each(CASE WHEN json_valid([[__mm_demo4.self_rel_many]]) THEN [[__mm_demo4.self_rel_many]] ELSE json_array([[__mm_demo4.self_rel_many]]) END) `__mm_demo4_self_rel_many_je` LEFT JOIN `demo4` `__mm_demo4_self_rel_many` ON [[__mm_demo4_self_rel_many.id]] = [[__mm_demo4_self_rel_many_je.value]] WHERE `__mm_demo4`.`id` = `demo4`.`id`) {{__mrTEST}} WHERE NOT ([[__mlTEST.multiMatchValue]] IS [[__mrTEST.multiMatchValue]])))))", }, + { + "geoPoint props access", + "demo1", + "point = '' || point.lat > 1 || point.lon < 2 || point.something > 3", + false, + "SELECT `demo1`.* FROM `demo1` WHERE (([[demo1.point]] = '' OR [[demo1.point]] IS NULL) OR (CASE WHEN json_valid([[demo1.point]]) THEN JSON_EXTRACT([[demo1.point]], '$.lat') ELSE JSON_EXTRACT(json_object('pb', [[demo1.point]]), '$.pb.lat') END) > {:TEST} OR (CASE WHEN json_valid([[demo1.point]]) THEN JSON_EXTRACT([[demo1.point]], '$.lon') ELSE JSON_EXTRACT(json_object('pb', [[demo1.point]]), '$.pb.lon') END) < {:TEST} OR (CASE WHEN json_valid([[demo1.point]]) THEN JSON_EXTRACT([[demo1.point]], '$.something') ELSE JSON_EXTRACT(json_object('pb', [[demo1.point]]), '$.pb.something') END) > {:TEST})", + }, } for _, s := range scenarios { diff --git a/tests/data/data.db b/tests/data/data.db index e22b80d180002d7b8f1d687caff587f3cce1e6ec..d06471a524a929e66e9fb3764d097065946aa636 100644 GIT binary patch delta 1379 zcmah|T})eb6uiq9q;Phh?(GEM~z(OcU>eCNpzB?9KUPG{#qBVsOtUYD>Z4vgpG(Ir*RSJHOxm zoSZ_zP$(FR&H6C}LHreav0?y0u+pZ5Q;Z?hJH4O9ZW3@18!f3CE~D6Jd9&dj?CJ8t zK_z43Il;l$t&Z?wHa4A$$HK9AD#K8-3y6|=@FDnMtNiw{t96yqNJ&LrMwOBBCi$I$ zJP8NEe}KK^Lf3loSP*F-dLi)}F;6%M57A3}O}tfpw&)`C#QTVGTzc==35EtMvao8FYHRPuji!Is(a+BulgZ7D00q&vBD;nfZ8% zOlB7rQ=zGOe%Fji+eZN;ATt3YxMptc|s=R<`!NY*_<8kX>GcSS8MCA83o( zpys+Ji+D9|^#%1fUcwV-9v@KNS8gd^|$7@c7B@iiqmZ=?ZssBJ^rEIXvPghbKIqUb%1++(NIk+y-*XZS+?S z=0`BUtl33}FpboU>dm;p_(|(l5p+tiAcVOBgTJq*BX^RlQD zTlW!S{t&@d0~V1c0&q!o1z{eJUsD;qMj)yVG>Q||lA5j|Hk0-pXspFg(O64FNY^+y z?)JC`{p2a>VF;d9i)X|WDudY!q+kek07TA*VDTDglD2nYk375!zX0;yBN%*78Y*BX zu(~^S7c18aRC4kP){JTTG2_59`!_8`?f?VMgc*)xdR~xs-o;+=%^qDX=j3UMvpFVh z(@}erp0V>b-X0YMJ8cylb|GqGW7FIW&vKQsN+hjplv|A1==1!-^3qHq9!)2B>wF?b mKXHhMUFA1_!de@NC$RFy9;PQv|Hr7pB!*CQ$UhT`Hu`TspM|V zTS@7b+Y-8IsVT8LKgQ@L44Dq;2yzjH2~%YL5QY8ngW*3xr3(HNhBr;IG6uqVAKt_B zzR!8i3va1pDwRwXGZ!TYVnmG>)c^#6F0b2MRFrTO^LNtMS=fi>t8{a@wl4ezYxAwE zdf2BaRcWDI>z7l@3HaPQ+ zs@n5gLtTu~XyjBNj2y?|k2b-6{PhK3Xh}g%mFNO>T7^3OFT2m?v`eC0ato3eba{hL zkHh12j-5U`lgSC${A?jdB*xW~7?(#$PO)7C-wTII1iQ%g8}1t_hPdvkE)P3&5$y%- zFjHlwi4qgie4*K(4pi5ht(Nk!azvnco(FGb=aN&WGxaaKccAO&$w+u4B9y!91k7&srSKc&GY&pK&z8jy(r5QayxD6>0y?sbJ@)KiMdQJ zKjC@p)!CE9|K__>iMhNnjU1WyfOQV0(V!;!(r(GlS={w@KJXyqgFLE2=sGB}oi z-O54&R^A22@#YrnRfe|Ur$E{M6UNt&{+50j_m|K?bxi=RWLJ8ywkwe0K^p1cK2 zj5Hy+1gZD1^5NU)So9^gU6SllK#)8^ml$+=9d3_z%%4mKk{Mq*?VUQ6@`*{&p9&-; zzbln?iD~JSDCOLi72oCgxdD8kCiHywh