From 6892ae3a6141d88b7ea04cb37119b3f27320fdfa Mon Sep 17 00:00:00 2001 From: Jeroen van der Heijden Date: Sat, 1 Nov 2025 13:31:33 +0100 Subject: [PATCH 1/3] rm comment --- inc/ti/qbind.t.h | 1 - 1 file changed, 1 deletion(-) diff --git a/inc/ti/qbind.t.h b/inc/ti/qbind.t.h index b81ac4f4..f3ef4392 100644 --- a/inc/ti/qbind.t.h +++ b/inc/ti/qbind.t.h @@ -23,7 +23,6 @@ typedef enum typedef enum { - /* first three flags are exclusive, only one may be set */ TI_QBIND_FLAG_NSE =1< Date: Sat, 1 Nov 2025 15:24:14 +0100 Subject: [PATCH 2/3] Added type_all() function --- inc/doc.h | 1 + inc/ti/fn/fnmodtype.h | 57 ++------------------------ inc/ti/fn/fntypeall.h | 38 ++++++++++++++++++ inc/ti/type.h | 2 + inc/ti/version.h | 2 +- itest/test_collection_functions.py | 38 ++++++++++++++++++ src/ti/export.c | 6 +-- src/ti/qbind.c | 64 +++++++++++++++--------------- src/ti/type.c | 49 +++++++++++++++++++++++ 9 files changed, 169 insertions(+), 88 deletions(-) create mode 100644 inc/ti/fn/fntypeall.h diff --git a/inc/doc.h b/inc/doc.h index 7233e108..ba681849 100644 --- a/inc/doc.h +++ b/inc/doc.h @@ -126,6 +126,7 @@ #define DOC_TIMEVAL DOC_SEE("collection-api/timeval") #define DOC_TRY DOC_SEE("collection-api/try") #define DOC_TYPE DOC_SEE("collection-api/type") +#define DOC_TYPE_ALL DOC_SEE("collection-api/type_all") #define DOC_TYPE_ASSERT DOC_SEE("collection-api/type_assert") #define DOC_TYPE_COUNT DOC_SEE("collection-api/type_count") #define DOC_TYPE_INFO DOC_SEE("collection-api/type_info") diff --git a/inc/ti/fn/fnmodtype.h b/inc/ti/fn/fnmodtype.h index c5af1ca8..4887dd6d 100644 --- a/inc/ti/fn/fnmodtype.h +++ b/inc/ti/fn/fnmodtype.h @@ -44,24 +44,6 @@ static inline int modtype__delv_cb(ti_thing_t * thing, ti_field_t * field) return 0; } -typedef struct -{ - ti_type_t * type; - imap_t * imap; -} modtype__collect_t; - -static int modtype__collect_cb(ti_thing_t * thing, modtype__collect_t * w) -{ - if (thing->type_id == w->type->type_id) - { - if (imap_add(w->imap, ti_thing_key(thing), thing)) - return -1; - - ti_incref(thing); - } - return 0; -} - typedef struct { ti_field_t * field; @@ -311,37 +293,6 @@ static int modtype__all_cb(ti_thing_t * thing, modtype__all_t * w) return w->e->nr; } -static imap_t * modtype__collect_things(ti_query_t * query, ti_type_t * type) -{ - modtype__collect_t collect = { - .imap = imap_create(), - .type = type, - }; - - if (!collect.imap) - return NULL; - - if (ti_query_vars_walk( - query->vars, - query->collection, - (imap_cb) modtype__collect_cb, - &collect) || - imap_walk( - query->collection->things, - (imap_cb) modtype__collect_cb, - &collect) || - ti_gc_walk( - query->collection->gc, - (queue_cb) modtype__collect_cb, - &collect)) - { - imap_destroy(collect.imap, (imap_destroy_cb) ti_val_unsafe_drop); - return NULL; - } - - return collect.imap; -} - static void type__add( ti_query_t * query, ti_type_t * type, @@ -609,7 +560,7 @@ static void type__add( .e = e, }; - imap = modtype__collect_things(query, type); + imap = ti_type_collect_things(query, type); if (!imap) { ex_set_mem(e); @@ -775,7 +726,7 @@ static int type__mod_using_callback( if (!modjob.dval) goto fail2; /* error is set */ - imap = modtype__collect_things(query, field->type); + imap = ti_type_collect_things(query, field->type); if (!imap) { ex_set_mem(e); @@ -817,7 +768,7 @@ static int type__mod_using_callback( (imap_cb) modtype__unlocked_cb, NULL); - imap_after = modtype__collect_things(query, field->type); + imap_after = ti_type_collect_things(query, field->type); if (imap_after) { imap_difference_inplace(imap_after, imap); @@ -1393,7 +1344,7 @@ static void type__all( ti_closure_inc(closure, query, e)) goto fail0; - imap = modtype__collect_things(query, type); + imap = ti_type_collect_things(query, type); if (!imap) { ex_set_mem(e); diff --git a/inc/ti/fn/fntypeall.h b/inc/ti/fn/fntypeall.h new file mode 100644 index 00000000..3b890513 --- /dev/null +++ b/inc/ti/fn/fntypeall.h @@ -0,0 +1,38 @@ +#include + +static int do__f_type_all(ti_query_t * query, cleri_node_t * nd, ex_t * e) +{ + const int nargs = fn_get_nargs(nd); + imap_t * imap; + ti_type_t * type; + ti_vset_t * vset; + + if (fn_not_collection_scope("type_all", query, e) || + fn_nargs("type_all", DOC_TYPE_ALL, 1, nargs, e) || + ti_do_statement(query, nd->children, e) || + fn_arg_str("type_all", DOC_TYPE_ALL, 1, query->rval, e)) + return e->nr; + + type = ti_types_by_raw(query->collection->types, (ti_raw_t *) query->rval); + if (!type) + return ti_raw_err_not_found((ti_raw_t *) query->rval, "type", e); + + imap = ti_type_collect_things(query, type); + if (!imap) + { + ex_set_mem(e); + return e->nr; + } + + vset = ti_vset_create_imap(imap); + if (!vset) + { + ex_set_mem(e); + imap_destroy(imap, (imap_destroy_cb) ti_val_unsafe_drop); + return e->nr; + } + + ti_val_unsafe_drop(query->rval); + query->rval = (ti_val_t *) vset; + return e->nr; +} diff --git a/inc/ti/type.h b/inc/ti/type.h index 3feb3f6b..a7ed41fc 100644 --- a/inc/ti/type.h +++ b/inc/ti/type.h @@ -18,6 +18,7 @@ #include #include #include +#include ti_type_t * ti_type_create( ti_types_t * types, @@ -31,6 +32,7 @@ ti_type_t * ti_type_create_unnamed( ti_types_t * types, ti_raw_t * name, uint8_t flags); +imap_t * ti_type_collect_things(ti_query_t * query, ti_type_t * type); void ti_type_drop(ti_type_t * type); void ti_type_drop_unnamed(ti_type_t * type); void ti_type_del(ti_type_t * type, vec_t * vars); diff --git a/inc/ti/version.h b/inc/ti/version.h index 7c1d9774..a3025d8a 100644 --- a/inc/ti/version.h +++ b/inc/ti/version.h @@ -25,7 +25,7 @@ * "-rc0" * "" */ -#define TI_VERSION_PRE_RELEASE "-alpha5" +#define TI_VERSION_PRE_RELEASE "-alpha6" #define TI_MAINTAINER \ "Jeroen van der Heijden " diff --git a/itest/test_collection_functions.py b/itest/test_collection_functions.py index 4911ae16..37d71d68 100755 --- a/itest/test_collection_functions.py +++ b/itest/test_collection_functions.py @@ -6006,6 +6006,44 @@ async def test_bit_count(self, client): """) self.assertEqual(res, 42) + async def test_type_all(self, client): + q = client.query + + with self.assertRaisesRegex( + LookupError, + 'function `type_all` is undefined in the `@thingsdb` scope;'): + await q('type_all("T");', scope='/t') + + with self.assertRaisesRegex( + NumArgumentsError, + 'function `type_all` takes 1 argument but 0 were given;'): + await q('type_all();') + + with self.assertRaisesRegex( + TypeError, + 'function `type_all` expects argument 1 to be of type `str` ' + 'but got type `int` instead'): + await q('type_all(1);') + + with self.assertRaisesRegex( + LookupError, + 'type `T` not found'): + await q('type_all("T");') + + r = await q("""//ti + set_type('T', { + name: 'str', + }); + mod_type('T', 'add', 't', 'T?'); + .t1 = T{}; + .t2 = T{}; + .t2.t = .t2; + .t2 = nil; // test gc + t3 = T{}; + type_all('T').len(); + """) + self.assertEqual(r, 3) + if __name__ == '__main__': run_test(TestCollectionFunctions()) diff --git a/src/ti/export.c b/src/ti/export.c index 010ab054..ba3e4c8e 100644 --- a/src/ti/export.c +++ b/src/ti/export.c @@ -414,13 +414,13 @@ static int export__val(ti_fmt_t * fmt, ti_val_t * val) } case TI_VAL_SET: { - imap_t * map = VSET(val); - if (!map->n) + imap_t * imap = VSET(val); + if (!imap->n) return buf_append_str(buf, "set()"); if (buf_append_str(buf, "set(\n")) return -1; fmt->indent++; - if (imap_walk(map, (imap_cb) export__set_val, fmt)) + if (imap_walk(imap, (imap_cb) export__set_val, fmt)) return -1; fmt->indent--; return -( diff --git a/src/ti/qbind.c b/src/ti/qbind.c index 0752f910..c146c494 100644 --- a/src/ti/qbind.c +++ b/src/ti/qbind.c @@ -250,6 +250,7 @@ #include #include #include +#include #include #include #include @@ -301,11 +302,11 @@ static void qbind__statement(ti_qbind_t * qbind, cleri_node_t * nd); */ enum { - TOTAL_KEYWORDS = 276, + TOTAL_KEYWORDS = 277, MIN_WORD_LENGTH = 2, MAX_WORD_LENGTH = 17, - MIN_HASH_VALUE = 26, - MAX_HASH_VALUE = 710 + MIN_HASH_VALUE = 12, + MAX_HASH_VALUE = 751 }; /* @@ -317,32 +318,32 @@ static inline unsigned int qbind__hash( { static unsigned short asso_values[] = { - 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, - 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, - 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, - 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, - 711, 711, 711, 711, 711, 711, 711, 711, 10, 10, - 10, 711, 10, 711, 9, 711, 12, 711, 711, 711, - 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, - 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, - 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, - 711, 711, 711, 711, 711, 9, 711, 14, 27, 102, - 17, 11, 128, 328, 77, 9, 24, 53, 11, 50, - 14, 43, 151, 45, 10, 9, 10, 60, 135, 248, - 156, 150, 30, 711, 711, 711, 711, 711, 711, 711, - 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, - 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, - 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, - 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, - 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, - 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, - 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, - 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, - 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, - 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, - 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, - 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, - 711, 711, 711, 711, 711, 711 + 752, 752, 752, 752, 752, 752, 752, 752, 752, 752, + 752, 752, 752, 752, 752, 752, 752, 752, 752, 752, + 752, 752, 752, 752, 752, 752, 752, 752, 752, 752, + 752, 752, 752, 752, 752, 752, 752, 752, 752, 752, + 752, 752, 752, 752, 752, 752, 752, 752, 4, 3, + 6, 752, 3, 752, 3, 752, 4, 752, 752, 752, + 752, 752, 752, 752, 752, 752, 752, 752, 752, 752, + 752, 752, 752, 752, 752, 752, 752, 752, 752, 752, + 752, 752, 752, 752, 752, 752, 752, 752, 752, 752, + 752, 752, 752, 752, 752, 2, 752, 19, 120, 85, + 23, 4, 136, 275, 180, 2, 6, 71, 24, 59, + 11, 41, 110, 44, 5, 2, 3, 28, 281, 191, + 227, 252, 25, 752, 752, 752, 752, 752, 752, 752, + 752, 752, 752, 752, 752, 752, 752, 752, 752, 752, + 752, 752, 752, 752, 752, 752, 752, 752, 752, 752, + 752, 752, 752, 752, 752, 752, 752, 752, 752, 752, + 752, 752, 752, 752, 752, 752, 752, 752, 752, 752, + 752, 752, 752, 752, 752, 752, 752, 752, 752, 752, + 752, 752, 752, 752, 752, 752, 752, 752, 752, 752, + 752, 752, 752, 752, 752, 752, 752, 752, 752, 752, + 752, 752, 752, 752, 752, 752, 752, 752, 752, 752, + 752, 752, 752, 752, 752, 752, 752, 752, 752, 752, + 752, 752, 752, 752, 752, 752, 752, 752, 752, 752, + 752, 752, 752, 752, 752, 752, 752, 752, 752, 752, + 752, 752, 752, 752, 752, 752, 752, 752, 752, 752, + 752, 752, 752, 752, 752, 752 }; register unsigned int hval = n; @@ -732,15 +733,16 @@ qbind__fmap_t qbind__fn_mapping[TOTAL_KEYWORDS] = { {.name="to_thing", .fn=do__f_to_thing, CHAIN_CE_X}, {.name="to_type", .fn=do__f_to_type, CHAIN_CE_X}, {.name="to", .fn=do__f_to, CHAIN_NE}, + {.name="trim", .fn=do__f_trim, CHAIN_NE}, {.name="trim_left", .fn=do__f_trim_left, CHAIN_NE}, {.name="trim_right", .fn=do__f_trim_right, CHAIN_NE}, - {.name="trim", .fn=do__f_trim, CHAIN_NE}, {.name="try", .fn=do__f_try, XROOT_NE}, + {.name="type", .fn=do__f_type, ROOT_NE}, + {.name="type_all", .fn=do__f_type_all, ROOT_NE}, {.name="type_assert", .fn=do__f_type_assert, ROOT_NE}, {.name="type_count", .fn=do__f_type_count, ROOT_NE}, {.name="type_err", .fn=do__f_type_err, ROOT_NE}, {.name="type_info", .fn=do__f_type_info, ROOT_NE}, - {.name="type", .fn=do__f_type, ROOT_NE}, {.name="types_info", .fn=do__f_types_info, ROOT_NE}, {.name="unique", .fn=do__f_unique, CHAIN_NE}, {.name="unshift", .fn=do__f_unshift, CHAIN_CE_XX}, diff --git a/src/ti/type.c b/src/ti/type.c index 382a9312..fed4615b 100644 --- a/src/ti/type.c +++ b/src/ti/type.c @@ -26,6 +26,24 @@ #include #include +typedef struct +{ + ti_type_t * type; + imap_t * imap; +} type__collect_t; + +static int type__collect_cb(ti_thing_t * thing, type__collect_t * w) +{ + if (thing->type_id == w->type->type_id) + { + if (imap_add(w->imap, ti_thing_key(thing), thing)) + return -1; + + ti_incref(thing); + } + return 0; +} + static char * type__wrap_name(const char * name, size_t n) { char * wname; @@ -114,6 +132,37 @@ ti_type_t * ti_type_create_unnamed( return type; } +imap_t * ti_type_collect_things(ti_query_t * query, ti_type_t * type) +{ + type__collect_t collect = { + .imap = imap_create(), + .type = type, + }; + + if (!collect.imap) + return NULL; + + if (ti_query_vars_walk( + query->vars, + query->collection, + (imap_cb) type__collect_cb, + &collect) || + imap_walk( + query->collection->things, + (imap_cb) type__collect_cb, + &collect) || + ti_gc_walk( + query->collection->gc, + (queue_cb) type__collect_cb, + &collect)) + { + imap_destroy(collect.imap, (imap_destroy_cb) ti_val_unsafe_drop); + return NULL; + } + + return collect.imap; +} + /* used as a callback function and removes all cached type mappings */ static int type__map_cleanup(ti_type_t * t_haystack, ti_type_t * t_needle) { From 6aeb4a260b2eb2e4c7eefba435d39191ac17408c Mon Sep 17 00:00:00 2001 From: Jeroen van der Heijden Date: Sat, 1 Nov 2025 15:53:21 +0100 Subject: [PATCH 3/3] Added type_all() function --- inc/ti/fn/fntypeall.h | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/inc/ti/fn/fntypeall.h b/inc/ti/fn/fntypeall.h index 3b890513..fe0fb91d 100644 --- a/inc/ti/fn/fntypeall.h +++ b/inc/ti/fn/fntypeall.h @@ -3,7 +3,6 @@ static int do__f_type_all(ti_query_t * query, cleri_node_t * nd, ex_t * e) { const int nargs = fn_get_nargs(nd); - imap_t * imap; ti_type_t * type; ti_vset_t * vset; @@ -17,19 +16,31 @@ static int do__f_type_all(ti_query_t * query, cleri_node_t * nd, ex_t * e) if (!type) return ti_raw_err_not_found((ti_raw_t *) query->rval, "type", e); - imap = ti_type_collect_things(query, type); - if (!imap) + if (ti_type_is_wrap_only(type)) { - ex_set_mem(e); - return e->nr; + vset = ti_vset_create(); + if (!vset) + { + ex_set_mem(e); + return e->nr; + } } - - vset = ti_vset_create_imap(imap); - if (!vset) + else { - ex_set_mem(e); - imap_destroy(imap, (imap_destroy_cb) ti_val_unsafe_drop); - return e->nr; + imap_t * imap = ti_type_collect_things(query, type); + if (!imap) + { + ex_set_mem(e); + return e->nr; + } + + vset = ti_vset_create_imap(imap); + if (!vset) + { + ex_set_mem(e); + imap_destroy(imap, (imap_destroy_cb) ti_val_unsafe_drop); + return e->nr; + } } ti_val_unsafe_drop(query->rval);