diff options
| author | vvvv <[email protected]> | 2025-10-16 11:07:18 +0300 |
|---|---|---|
| committer | vvvv <[email protected]> | 2025-10-16 11:39:58 +0300 |
| commit | 619f58f599a109ca31a442940c4d852dabc1d5dd (patch) | |
| tree | aa48fbc0cff4d6362d6bcd4165c9b81d98d04801 | |
| parent | 7e2655424dbb29c9c095fceb9a09427400860a9b (diff) | |
YQL-20339 doc
commit_hash:a8c9013fd0fcaee84d3025dddc931ad1b0b547a3
| -rw-r--r-- | yql/essentials/docs/en/builtins/basic.md | 44 | ||||
| -rw-r--r-- | yql/essentials/docs/en/builtins/dict.md | 492 | ||||
| -rw-r--r-- | yql/essentials/docs/en/builtins/types.md | 66 | ||||
| -rw-r--r-- | yql/essentials/docs/en/changelog/2025.04.md | 10 | ||||
| -rw-r--r-- | yql/essentials/docs/en/types/index.md | 1 | ||||
| -rw-r--r-- | yql/essentials/docs/en/types/linear.md | 37 | ||||
| -rw-r--r-- | yql/essentials/docs/en/types/toc_i.yaml | 2 | ||||
| -rw-r--r-- | yql/essentials/docs/ru/builtins/basic.md | 46 | ||||
| -rw-r--r-- | yql/essentials/docs/ru/builtins/dict.md | 493 | ||||
| -rw-r--r-- | yql/essentials/docs/ru/builtins/types.md | 67 | ||||
| -rw-r--r-- | yql/essentials/docs/ru/changelog/2025.04.md | 11 | ||||
| -rw-r--r-- | yql/essentials/docs/ru/types/index.md | 1 | ||||
| -rw-r--r-- | yql/essentials/docs/ru/types/linear.md | 37 | ||||
| -rw-r--r-- | yql/essentials/docs/ru/types/toc_i.yaml | 2 | ||||
| -rw-r--r-- | yql/essentials/providers/common/comp_nodes/yql_parsetypehandle.cpp | 1 |
15 files changed, 1309 insertions, 1 deletions
diff --git a/yql/essentials/docs/en/builtins/basic.md b/yql/essentials/docs/en/builtins/basic.md index 3a692edbcfc..994387eaf57 100644 --- a/yql/essentials/docs/en/builtins/basic.md +++ b/yql/essentials/docs/en/builtins/basic.md @@ -913,6 +913,50 @@ A typical example of a `SemilatticeRT` side effect is to perform an `UPSERT` to SELECT WithSideEffects(MyModule::Func(...)) FROM table ``` +## ToDynamicLinear + +#### Signature + +```yql +ToDynamicLinear(Linear<T>)->DynamicLinear<T> +``` + +This function is available since version [2025.04](../changelog/2025.04.md). +The `ToDynamicLinear` function converts a value from a static [linear](../types/linear.md) type to a dynamic type. + +## FromDynamicLinear + +#### Signature + +```yql +FromDynamicLinear(DynamicLinear<T>)->Linear<T> +``` + +This function is available since version [2025.04](../changelog/2025.04.md). +The `FromDynamicLinear` function converts a value from a dynamic [linear](../types/linear.md) type to a static type. + +## Block + +#### Signature + +```yql +Block(lambda((dependsOnArgument)->T))->T +``` + +This function is available since version [2025.04](../changelog/2025.04.md). +The `Block` function evaluates a lambda with one argument (whose type is unspecified, as it should only be used as a dependent node) and returns its output value. +Dependent nodes are those used to control the evaluation of nondeterministic functions such as [Random](#random) or functions that produce values of [linear](../types/linear.md) types. + +#### Example + +```yql +SELECT Block(($arg)->{ + $dict = ToMutDict({'key1':123}, $arg); -- use a dependent node when creating a linear value + $dict = MutDictInsert($dict, 'key2', 456); + return FromMutDict($dict); +}); -- {'key1':123, 'key2': 456} +``` + ## EvaluateExpr, EvaluateAtom {#evaluate_expr_atom} Evaluate an expression before the start of the main calculation and input its result to the query as a literal (constant). In many contexts, where only a constant would be expected in standard SQL (for example, in table names, in the number of rows in [LIMIT](../syntax/select/limit_offset.md), and so on), this functionality is implicitly enabled automatically. diff --git a/yql/essentials/docs/en/builtins/dict.md b/yql/essentials/docs/en/builtins/dict.md index 57b01e54acf..4099a07ca94 100644 --- a/yql/essentials/docs/en/builtins/dict.md +++ b/yql/essentials/docs/en/builtins/dict.md @@ -280,3 +280,495 @@ SELECT SetSymmetricDifference( -- { 2 : (null, "qwe"), 3 : ("bar", null) } ``` +## DictInsert {#dictinsert} + +#### Signature + +```yql +DictInsert(Dict<K,V>,K,V)->Dict<K,V> +``` + +This function is available since version [2025.04](../changelog/2025.04.md). +Returns a new dictionary with the specified key and value added. If the key already exists, the dictionary is not modified. +When working with a `Set`, the `Void()` function should be passed as the value. + +#### Examples + +```yql +SELECT DictInsert({'foo':1}, 'bar', 2); -- {'foo':1,'bar':2} +SELECT DictInsert({'foo':1}, 'foo', 2); -- {'foo':1} +SELECT DictInsert({'foo'}, 'bar', Void()); -- {'foo','bar'} +``` + +## DictUpsert {#dictupsert} + +#### Signature + +```yql +DictUpsert(Dict<K,V>,K,V)->Dict<K,V> +``` + +This function is available since version [2025.04](../changelog/2025.04.md). +Returns a new dictionary with the specified key and value added or replaced. If the key already exists, the value is updated. + +#### Examples + +```yql +SELECT DictUpsert({'foo':1}, 'bar', 2); -- {'foo':1,'bar':2} +SELECT DictUpsert({'foo':1}, 'foo', 2); -- {'foo':2} +``` + +## DictUpdate {#dictupdate} + +#### Signature + +```yql +DictUpdate(Dict<K,V>,K,V)->Dict<K,V> +``` + +This function is available since version [2025.04](../changelog/2025.04.md). +Returns a new dictionary with the replaced value of the given key. If the key does not exist, the dictionary is not modified. + +#### Examples + +```yql +SELECT DictUpdate({'foo':1}, 'bar', 2); -- {'foo':1} +SELECT DictUpdate({'foo':1}, 'foo', 2); -- {'foo':2} +``` + +## DictRemove {#dictremove} + +#### Signature + +```yql +DictRemove(Dict<K,V>,K)->Dict<K,V> +``` + +This function is available since version [2025.04](../changelog/2025.04.md). +Returns a new dictionary without the given key. If the key does not exist, the dictionary is not modified. + +#### Examples + +```yql +SELECT DictRemove({'foo':1}, 'bar'); -- {'foo':1} +SELECT DictRemove({'foo':1}, 'foo'); -- {} +``` + +## ToMutDict {#tomutdict} + +#### Signature + +```yql +ToMutDict(Dict<K,V>,dependArg1...)->Linear<mutDictType for Dict<K,V>> +``` + +This function is available since version [2025.04](../changelog/2025.04.md). +Converts a dictionary to its mutable version. One or more dependent expressions must also be passed, for example, using the `lambda` argument in the [`Block`](basic.md#block) function. + +#### Examples + +```yql +SELECT Block( + ($arg)->{ + $dict = ToMutDict({'foo':1}, $arg); + return FromMutDict($dict); + }); -- {'foo':1} +``` + +## MutDictCreate {#mutdictcreate} + +#### Signature + +```yql +MutDictCreate(KeyType,ValueType,dependArg1...)->Linear<mutDictType for Dict<K,V>> +``` + +This function is available since version [2025.04](../changelog/2025.04.md). +Builds an empty mutable dictionary with the specified key and value types. You must also pass one or more dependent expressions, for example, by using the `lambda` argument in the [`Block`](basic.md#block) function. + +#### Examples + +```yql +SELECT Block( + ($arg)->{ + $dict = MutDictCreate(String, Int32, $arg); + return FromMutDict($dict); + }); -- {} +``` + +## FromMutDict {#frommutdict} + +#### Signature + +```yql +FromMutDict(Linear<mutDictType for Dict<K,V>>)->Dict<K,V> +``` + +This function is available since version [2025.04](../changelog/2025.04.md). +Consumes a mutable dictionary and converts it to an immutable one. + +#### Examples + +```yql +SELECT Block( + ($arg)->{ + $dict = ToMutDict({'foo':1}, $arg); + return FromMutDict($dict); + }); -- {'foo':1} +``` + +## MutDictInsert {#mutdictinsert} + +#### Signature + +```yql +MutDictInsert(Linear<mutDictType for Dict<K,V>>,K,V)->Linear<mutDictType for Dict<K,V>> +``` + +This function is available since version [2025.04](../changelog/2025.04.md). +Adds the specified key and value to a mutable dictionary and returns the same mutable dictionary. If the key already exists in the dictionary, the dictionary is not modified. +When working with a `Set`, the `Void()` function should be passed as the value. + +#### Examples + +```yql +SELECT Block( + ($arg)->{ + $dict = ToMutDict({'foo':1}, $arg); + $dict = MutDictInsert($dict,'foo',2); + return FromMutDict($dict); + }); -- {'foo':1} + +SELECT Block( + ($arg)->{ + $dict = ToMutDict({'foo':1}, $arg); + $dict = MutDictInsert($dict,'bar',2); + return FromMutDict($dict); + }); -- {'foo':1,'bar':2} + +SELECT Block( + ($arg)->{ + $dict = ToMutDict({'foo'}, $arg); + $dict = MutDictInsert($dict,'bar', Void()); + return FromMutDict($dict); + }); -- {'foo','bar'} +``` + +## MutDictUpsert {#mutdictupsert} + +#### Signature + +```yql +MutDictUpsert(Linear<mutDictType for Dict<K,V>>,K,V)->Linear<mutDictType for Dict<K,V>> +``` + +This function is available since version [2025.04](../changelog/2025.04.md). +Adds or replaces the specified key and value in a mutable dictionary and returns the same mutable dictionary. If the key already exists in the dictionary, the value is updated. + +#### Examples + +```yql +SELECT Block( + ($arg)->{ + $dict = ToMutDict({'foo':1}, $arg); + $dict = MutDictUpsert($dict,'foo',2); + return FromMutDict($dict); + }); -- {'foo':2} + +SELECT Block( + ($arg)->{ + $dict = ToMutDict({'foo':1}, $arg); + $dict = MutDictUpsert($dict,'bar',2); + return FromMutDict($dict); + }); -- {'foo':1,'bar':2} +``` + +## MutDictUpdate {#mutdictupdate} + +#### Signature + +```yql +MutDictUpdate(Linear<mutDictType for Dict<K,V>>,K,V)->Linear<mutDictType for Dict<K,V>> +``` + +This function is available since version [2025.04](../changelog/2025.04.md). +Replaces the value in a mutable dictionary with the specified key and returns the same mutable dictionary. If the key does not exist in the dictionary, the dictionary is not modified. + +#### Examples + +```yql +SELECT Block( + ($arg)->{ + $dict = ToMutDict({'foo':1}, $arg); + $dict = MutDictUpdate($dict,'foo',2); + return FromMutDict($dict); + }); -- {'foo':2} + +SELECT Block( + ($arg)->{ + $dict = ToMutDict({'foo':1}, $arg); + $dict = MutDictUpdate($dict,'bar',2); + return FromMutDict($dict); + }); -- {'foo':1} +``` + +## MutDictRemove {#mutdictremove} + +#### Signature + +```yql +MutDictRemove(Linear<mutDictType for Dict<K,V>>,K)->Linear<mutDictType for Dict<K,V>> +``` + +This function is available since version [2025.04](../changelog/2025.04.md). +Removes the value from a mutable dictionary by the given key and returns the same mutable dictionary. If the key does not exist in the dictionary, the dictionary is not modified. + +#### Examples + +```yql +SELECT Block( + ($arg)->{ + $dict = ToMutDict({'foo':1}, $arg); + $dict = MutDictRemove($dict,'foo'); + return FromMutDict($dict); + }); --{} + +SELECT Block( + ($arg)->{ + $dict = ToMutDict({'foo':1}, $arg); + $dict = MutDictRemove($dict,'bar'); + return FromMutDict($dict); + }); -- {'foo':1} +``` + +## MutDictPop {#mutdictpop} + +#### Signature + +```yql +MutDictPop(Linear<mutDictType for Dict<K,V>>,K)->Tuple<Linear<mutDictType for Dict<K,V>>,V?> +``` + +This function is available since version [2025.04](../changelog/2025.04.md). +Removes the value from a mutable dictionary by the given key and returns the same mutable dictionary and the value by the removed key. If the key did not exist in the dictionary, the dictionary is not modified and an empty Optional is returned. + +#### Examples + +```yql +SELECT Block( + ($arg)->{ + $dict = ToMutDict({'foo':1}, $arg); + $dict, $val = MutDictPop($dict,'foo'); + return (FromMutDict($dict), $val); + }); -- ({},1) + +SELECT Block( + ($arg)->{ + $dict = ToMutDict({'foo':1}, $arg); + $dict, $val = MutDictPop($dict,'bar'); + return (FromMutDict($dict), $val); + }); -- ({'foo':1},null) +``` + +## MutDictContains {#mutdictcontains} + +#### Signature + +```yql +MutDictContains(Linear<mutDictType for Dict<K,V>>,K)->Tuple<Linear<mutDictType for Dict<K,V>>,Bool> +``` + +This function is available since version [2025.04](../changelog/2025.04.md). +Checks for the existence of a key in a mutable dictionary, returns the same mutable dictionary and the result. + +#### Examples + +```yql +SELECT Block( + ($arg)->{ + $dict = ToMutDict({'foo':1}, $arg); + $dict, $val = MutDictContains($dict,'foo'); + return (FromMutDict($dict), $val); + }); -- ({'foo':1},True) + +SELECT Block( + ($arg)->{ + $dict = ToMutDict({'foo':1}, $arg); + $dict, $val = MutDictContains($dict,'bar'); + return (FromMutDict($dict), $val); + }); -- ({'foo':1},False) +``` + +## MutDictLookup {#mutdictlookup} + +#### Signature + +```yql +MutDictLookup(Linear<mutDictType for Dict<K,V>>,K)->Tuple<Linear<mutDictType for Dict<K,V>>,V?> +``` + +This function is available since version [2025.04](../changelog/2025.04.md). +Gets a value by key in a mutable dictionary, returns the same mutable dictionary and an optional result. + +#### Examples + +```yql +SELECT Block( + ($arg)->{ + $dict = ToMutDict({'foo':1}, $arg); + $dict, $val = MutDictLookup($dict,'foo'); + return (FromMutDict($dict), $val); + }); -- ({'foo':1},1) + +SELECT Block( + ($arg)->{ + $dict = ToMutDict({'foo':1}, $arg); + $dict, $val = MutDictLookup($dict,'bar'); + return (FromMutDict($dict), $val); + }); -- ({'foo':1},null) +``` + +## MutDictHasItems {#mutdicthasitems} + +#### Signature + +```yql +MutDictHasItems(Linear<mutDictType for Dict<K,V>>)->Tuple<Linear<mutDictType for Dict<K,V>>,Bool> +``` + +This function is available since version [2025.04](../changelog/2025.04.md). +Checks whether a mutable dictionary is not empty and returns the same mutable dictionary and the result. + +#### Examples + +```yql +SELECT Block( + ($arg)->{ + $dict = ToMutDict({'foo':1}, $arg); + $dict, $val = MutDictHasItems($dict); + return (FromMutDict($dict), $val); + }); -- ({'foo':1},True) + +SELECT Block( + ($arg)->{ + $dict = MutDictCreate(String, Int32, $arg); + $dict, $val = MutDictHasItems($dict); + return (FromMutDict($dict), $val); + }); -- ({},False) +``` + +## MutDictLength {#mutdictlength} + +#### Signature + +```yql +MutDictLength(Linear<mutDictType for Dict<K,V>>)->Tuple<Linear<mutDictType for Dict<K,V>>,Uint64> +``` + +This function is available since version [2025.04](../changelog/2025.04.md). +Gets the number of elements in a mutable dictionary and returns the same mutable dictionary and the result. + +#### Examples + +```yql +SELECT Block( + ($arg)->{ + $dict = ToMutDict({'foo':1}, $arg); + $dict, $val = MutDictLength($dict); + return (FromMutDict($dict), $val); + }); -- ({'foo':1},1) + +SELECT Block( + ($arg)->{ + $dict = MutDictCreate(String, Int32, $arg); + $dict, $val = MutDictLength($dict); + return (FromMutDict($dict), $val); + }); -- ({},0) +``` + +## MutDictKeys {#mutdictkeys} + +#### Signature + +```yql +MutDictKeys(Linear<mutDictType for Dict<K,V>>)->Tuple<Linear<mutDictType for Dict<K,V>>,List<K>> +``` + +This function is available since version [2025.04](../changelog/2025.04.md). +Gets a list of keys in a mutable dictionary and returns the same mutable dictionary and the result. + +#### Examples + +```yql +SELECT Block( + ($arg)->{ + $dict = ToMutDict({'foo':1}, $arg); + $dict, $val = MutDictKeys($dict); + return (FromMutDict($dict), $val); + }); -- ({'foo':1},['foo']) + +SELECT Block( + ($arg)->{ + $dict = MutDictCreate(String, Int32, $arg); + $dict, $val = MutDictKeys($dict); + return (FromMutDict($dict), $val); + }); -- ({},[]) +``` + +## MutDictPayloads {#mutdictpayloads} + +#### Signature + +```yql +MutDictPayloads(Linear<mutDictType for Dict<K,V>>)->Tuple<Linear<mutDictType for Dict<K,V>>,List<V>> +``` + +This function is available since version [2025.04](../changelog/2025.04.md). +Gets a list of values in a mutable dictionary and returns the same mutable dictionary and the result. + +#### Examples + +```yql +SELECT Block( + ($arg)->{ + $dict = ToMutDict({'foo':1}, $arg); + $dict, $val = MutDictPayloads($dict); + return (FromMutDict($dict), $val); + }); -- ({'foo':1},['1']) + +SELECT Block( + ($arg)->{ + $dict = MutDictCreate(String, Int32, $arg); + $dict, $val = MutDictPayloads($dict); + return (FromMutDict($dict), $val); + }); -- ({},[]) +``` + +## MutDictItems {#mutdictitems} + +#### Signature + +```yql +MutDictItems(Linear<mutDictType for Dict<K,V>>)->Tuple<Linear<mutDictType for Dict<K,V>>,List<Tuple<K,V>>> +``` + +This function is available since version [2025.04](../changelog/2025.04.md). +Gets a list of tuples with key-value pairs in a mutable dictionary, returns the same mutable dictionary and the result. + +#### Examples + +```yql +SELECT Block( + ($arg)->{ + $dict = ToMutDict({'foo':1}, $arg); + $dict, $val = MutDictItems($dict); + return (FromMutDict($dict), $val); + }); -- ({'foo':1},[('foo',1)]) + +SELECT Block( + ($arg)->{ + $dict = MutDictCreate(String, Int32, $arg); + $dict, $val = MutDictItems($dict); + return (FromMutDict($dict), $val); + }); -- ({},[]) +``` diff --git a/yql/essentials/docs/en/builtins/types.md b/yql/essentials/docs/en/builtins/types.md index 566ee1de1f2..06105c785d3 100644 --- a/yql/essentials/docs/en/builtins/types.md +++ b/yql/essentials/docs/en/builtins/types.md @@ -165,6 +165,24 @@ Return the same-name [special data types](../types/special.md). They have no arg SELECT FormatType(VoidType()); -- Void ``` +## LinearType, DynamicLinearType {#lineartype} + +#### Signature + +```yql +LinearType(Type) -> linear type parameterized by the given type +``` + +Functions available since version [2025.04](../changelog/2025.04.md). +Returns the [linear](../types/linear.md) type. + +#### Examples + +```yql +SELECT FormatType(LinearType(ResourceType("Foo"))); -- Linear<Resource<'Foo'>> +SELECT FormatType(DynamicLinearType(ResourceType("Foo"))); -- DynamicLinear<Resource<'Foo'>> +``` + ## OptionalItemType, ListItemType and StreamItemType {#optionalitemtype} If a type is passed to these functions, then they perform the action reverse to [OptionalType](#optionaltype), [ListType](#listtype), and [StreamType](#listtype): return the item type based on its container type. @@ -185,6 +203,34 @@ SELECT FormatType(ListItemType( )); -- Int32 ``` +## LinearItemType {#linearitemtype} + +#### Signature + +```yql +LinearItemType(LinearType)->linear type parameter +LinearItemType(DynamicLinearType)->linear type parameter +``` + +These functions are available starting with version [2025.04](../changelog/2025.04.md). +If these functions are passed a type, they perform the inverse of [LinearType](#lineartype) or [DynamicLinearType](#lineartype) — they return the type of the linear type parameter. + +If these functions are passed a type handle, they perform the inverse of [LinearTypeHandle](#lineartypehandle) or [DynamicLinearTypeHandle](#lineartypehandle)—they return the handle of the parameter type based on the linear type handle. + +#### Examples + +```yql +SELECT FormatType(LinearItemType( + ParseType("Linear<Int32>") +)); -- Int32 +``` + +```yql +SELECT FormatType(LinearItemType( + ParseTypeHandle("Linear<Int32>") +)); -- Int32 +``` + ## DictKeyType and DictPayloadType {#dictkeytype} Returns the type of the key or value based on the dictionary type. @@ -635,3 +681,23 @@ Getting the number of arguments in a lambda function. SELECT LambdaArgumentsCount(($x, $y)->($x+$y)) ; -- 2 ``` + +### LinearTypeHandle and DynamicLinearTypeHandle {#lineartypehandle} + +#### Signature + +```yql +LinearTypeHandle(TypeHandle)->handle of a static linear type +DynamicLinearTypeHandle(TypeHandle)->handle of a dynamic linear type +``` + +Functions available starting with version [2025.04](../changelog/2025.04.md). +These functions construct a handle of a static or dynamic linear type based on the passed handle of the parameter type. + +#### Examples + +```yql +SELECT FormatType(LinearTypeHandle( + TypeHandle(DataType("Bool")) +)); -- Linear<Bool> +``` diff --git a/yql/essentials/docs/en/changelog/2025.04.md b/yql/essentials/docs/en/changelog/2025.04.md index fbffc9112cc..f6e20c7092d 100644 --- a/yql/essentials/docs/en/changelog/2025.04.md +++ b/yql/essentials/docs/en/changelog/2025.04.md @@ -1,6 +1,16 @@ +## Changes in types + +Added linear types. + ## Changes in built-in functions * Added functions `WithSideEffects`/`WithSideEffectsMode` for working with side effects. +* Added functions for creating new dictionaries based on existing ones with content modification: `DictInsert`/`DictUpsert`/`DictUpdate`/`DictRemove`. +* Added functions for working with mutable dictionaries using linear types. +* Added `Block` function for executing a block of code using anonymous dependent nodes. +* Added `ToDynamicLinear`/`FromDynamicLinear` functions for converting between linear types. +* Added `LinearType`/`DynamicLinearType` functions for constructing linear types. * Added the `LinearTypeHandle`/`DynamicLinearTypeHandle` functions for constructing linear types during code generation. +* Added the `LinearItemType` function for retrieving the parameter type from a linear type. ## Changes in NOT NULL expression diff --git a/yql/essentials/docs/en/types/index.md b/yql/essentials/docs/en/types/index.md index 8933ad400b2..41405cd2699 100644 --- a/yql/essentials/docs/en/types/index.md +++ b/yql/essentials/docs/en/types/index.md @@ -6,6 +6,7 @@ This section contains articles on YQL data types: - [Optional types](optional.md) - [Containers](containers.md) - [Special types](special.md) +- [Linear types](linear.md) - [Type casting](cast.md) - [Text representation of data types](type_string.md) - [Parameter transfer in JSON format](json.md) diff --git a/yql/essentials/docs/en/types/linear.md b/yql/essentials/docs/en/types/linear.md new file mode 100644 index 00000000000..ce17aab54b3 --- /dev/null +++ b/yql/essentials/docs/en/types/linear.md @@ -0,0 +1,37 @@ +## Linear Types + +Most types in YQL are immutable, meaning expressions return new values rather than modify existing ones. +This approach, common in functional programming languages, allows for more aggressive optimizations (such as removing common subexpressions or caching results). +However, in some scenarios, this can lead to slower query execution. In particular, when attempting to modify a single value in a list/dictionary, it is necessary to either return a full copy or use persistent data structures, which also incurs additional overhead. + +Linear types offer a different approach: instead of reusing the immutable results of expression evaluation, reuse of a linear type value is prohibited. It is passed, as if in a relay race, from the point of creation to the point of consumption, where it is converted to a regular immutable value. + +Linear types are available starting with version [2025.04](../changelog/2025.04.md). + +Linear types are described by a single type parameter T and come in two varieties: statically verified Linear<T> and runtime-verified DynamicLinear<T>. +Statically verified types are more efficient but have composition limitations. + +Typically, the Resource type is used in the T parameter of a linear type. In this case, user-defined functions (UDFs) can pass such data between each other with a guarantee of protection against reuse in the query, allowing for a more efficient implementation. + +Linear types are not serializable—they cannot be read or written to tables, meaning they can only be used in the middle of expressions. + +Functions that accept or return linear types are divided into three classes: +* If the linear type is contained in the result but not in the arguments, it is a generating function; +* If the linear type is contained in both the arguments and the result, it is a transforming function; +* If a linear type is contained in the arguments but not in the result, it is an consuming function. + +A generating function must accept a dependent expression in at least one argument, since multiple independent values of linear types can be constructed from the input arguments. +It is recommended to create and consume linear types within the [`Block`](../builtins/basic.md#block) function, which allows an anonymous dependent expression to be passed as a `lambda` argument. + +### Rules for checking static linear types `Linear<T>` + +* `Linear` types are checked as the last stage of optimization, and if the optimizer eliminates expression reuse, no error is raised. +* `Linear` cannot be an argument to `lambda`. +* `Linear` cannot be returned from `lambda`. +* `Linear` can be used either by itself or as a field in a `Struct/Tuple` (without nesting). Whenever possible, individual uses of `Struct/Tuple` fields are tracked using the field access operator (dot). + +If you need to use values of linear types within other container types (for example, in lists), you should use the `DynamicLinear` type. + +### Rules for checking dynamic linear types `DynamicLinear<T>` + +* The `FromDynamicLinear` function or user-defined functions (UDFs) may retrieve a value of this type, but only once, otherwise a query execution error will occur. diff --git a/yql/essentials/docs/en/types/toc_i.yaml b/yql/essentials/docs/en/types/toc_i.yaml index cd0f40f6f02..0a04c673b91 100644 --- a/yql/essentials/docs/en/types/toc_i.yaml +++ b/yql/essentials/docs/en/types/toc_i.yaml @@ -9,6 +9,8 @@ items: href: containers.md - name: Special href: special.md +- name: Linear + href: linear.md - name: Type casting href: cast.md - name: Text representation of data types diff --git a/yql/essentials/docs/ru/builtins/basic.md b/yql/essentials/docs/ru/builtins/basic.md index 40377a9517f..5286146d226 100644 --- a/yql/essentials/docs/ru/builtins/basic.md +++ b/yql/essentials/docs/ru/builtins/basic.md @@ -386,7 +386,6 @@ $config = @@{ SELECT Udf(Protobuf::TryParse, $config As TypeConfig)("") ``` - ## CurrentUtc... {#current-utc} `CurrentUtcDate()`, `CurrentUtcDatetime()` и `CurrentUtcTimestamp()` - получение текущей даты и/или времени в UTC. Тип данных результата указан в конце названия функции. @@ -1150,6 +1149,51 @@ WithSideEffectsMode(T, mode:string)->T SELECT WithSideEffects(MyModule::Func(...)) FROM table ``` +## ToDynamicLinear + +#### Сигнатура + +```yql +ToDynamicLinear(Linear<T>)->DynamicLinear<T> +``` + +Функция доступна начиная с версии [2025.04](../changelog/2025.04.md). +Функция `ToDynamicLinear` преобразует значение из статического [линейного](../types/linear.md) типа в динамический. + +## FromDynamicLinear + +#### Сигнатура + +```yql +FromDynamicLinear(DynamicLinear<T>)->Linear<T> +``` + +Функция доступна начиная с версии [2025.04](../changelog/2025.04.md). +Функция `FromDynamicLinear` преобразует значение из динамического [линейного](../types/linear.md) типа в статический. + +## Block + +#### Сигнатура + +```yql +Block(lambda((dependsOnArgument)->T))->T +``` + +Функция доступна начиная с версии [2025.04](../changelog/2025.04.md). +Функция `Block` выполняет лямбду с одним аргументом (тип которого не определен, так как должен использоваться только как зависимый узел) и возвращает ее выходное значение. +Зависимые узлы это те, которые используются для управления вычислением недетерминированных функций таких как [Random](#random) или функций, создающих значения [линейных](../types/linear.md) типов. + +#### Пример + +```yql +SELECT Block(($arg)->{ + $dict = ToMutDict({'key1':123}, $arg); -- используем зависимый узел при создании значения линейного типа + $dict = MutDictInsert($dict, 'key2', 456); + return FromMutDict($dict); +}); -- {'key1':123, 'key2': 456} +``` + + ## EvaluateExpr, EvaluateAtom {#evaluate_expr_atom} Возможность выполнить выражение до начала основного расчета и подставить его результат в запрос как литерал (константу). Во многих контекстах, где в стандартном SQL ожидалась бы только константа (например, в именах таблиц, количестве строк в [LIMIT](../syntax/select/limit_offset.md) и т.п.) этот функционал активируется неявным образом автоматически. diff --git a/yql/essentials/docs/ru/builtins/dict.md b/yql/essentials/docs/ru/builtins/dict.md index 693e703be17..8497930238d 100644 --- a/yql/essentials/docs/ru/builtins/dict.md +++ b/yql/essentials/docs/ru/builtins/dict.md @@ -443,3 +443,496 @@ SELECT SetSymmetricDifference( -- { 2 : (null, "qwe"), 3 : ("bar", null) } ``` +## DictInsert {#dictinsert} + +#### Сигнатура + +```yql +DictInsert(Dict<K,V>,K,V)->Dict<K,V> +``` + +Функция доступна начиная с версии [2025.04](../changelog/2025.04.md). +Возвращает новый словарь в который добавили заданный ключ и значение. Если ключ уже существовал, словарь не изменяется. +При работе с множеством (`Set`) в качестве значения следует передавать функцию `Void()`. + +#### Примеры + +```yql +SELECT DictInsert({'foo':1}, 'bar', 2); -- {'foo':1,'bar':2} +SELECT DictInsert({'foo':1}, 'foo', 2); -- {'foo':1} +SELECT DictInsert({'foo'}, 'bar', Void()); -- {'foo','bar'} +``` + +## DictUpsert {#dictupsert} + +#### Сигнатура + +```yql +DictUpsert(Dict<K,V>,K,V)->Dict<K,V> +``` + +Функция доступна начиная с версии [2025.04](../changelog/2025.04.md). +Возвращает новый словарь в который добавили или заменили заданный ключ и значение. Если ключ уже существовал, значение обновляется. + +#### Примеры + +```yql +SELECT DictUpsert({'foo':1}, 'bar', 2); -- {'foo':1,'bar':2} +SELECT DictUpsert({'foo':1}, 'foo', 2); -- {'foo':2} +``` + +## DictUpdate {#dictupdate} + +#### Сигнатура + +```yql +DictUpdate(Dict<K,V>,K,V)->Dict<K,V> +``` + +Функция доступна начиная с версии [2025.04](../changelog/2025.04.md). +Возвращает новый словарь в который заменили значение по заданному ключу. Если ключ не существовал, словарь не меняется. + +#### Примеры + +```yql +SELECT DictUpdate({'foo':1}, 'bar', 2); -- {'foo':1} +SELECT DictUpdate({'foo':1}, 'foo', 2); -- {'foo':2} +``` + +## DictRemove {#dictremove} + +#### Сигнатура + +```yql +DictRemove(Dict<K,V>,K)->Dict<K,V> +``` + +Функция доступна начиная с версии [2025.04](../changelog/2025.04.md). +Возвращает новый словарь без заданного ключа. Если ключ не существовал, словарь не меняется. + +#### Примеры + +```yql +SELECT DictRemove({'foo':1}, 'bar'); -- {'foo':1} +SELECT DictRemove({'foo':1}, 'foo'); -- {} +``` + +## ToMutDict {#tomutdict} + +#### Сигнатура + +```yql +ToMutDict(Dict<K,V>,dependArg1...)->Linear<mutDictType for Dict<K,V>> +``` + +Функция доступна начиная с версии [2025.04](../changelog/2025.04.md). +Конвертирует словарь в свою мутабельную версию. Также необходимо передать одно или более зависимое выражение, например, используя аргумент `lambda` в функции [`Block`](basic.md#block). + +#### Примеры + +```yql +SELECT Block( + ($arg)->{ + $dict = ToMutDict({'foo':1}, $arg); + return FromMutDict($dict); + }); -- {'foo':1} +``` + +## MutDictCreate {#mutdictcreate} + +#### Сигнатура + +```yql +MutDictCreate(KeyType,ValueType,dependArg1...)->Linear<mutDictType for Dict<K,V>> +``` + +Функция доступна начиная с версии [2025.04](../changelog/2025.04.md). +Строит пустой мутабельный словарь с заданными типами ключа и значения. Также необходимо передать одно или более зависимое выражение, например, используя аргумент `lambda` в функции [`Block`](basic.md#block). + +#### Примеры + +```yql +SELECT Block( + ($arg)->{ + $dict = MutDictCreate(String, Int32, $arg); + return FromMutDict($dict); + }); -- {} +``` + +## FromMutDict {#frommutdict} + +#### Сигнатура + +```yql +FromMutDict(Linear<mutDictType for Dict<K,V>>)->Dict<K,V> +``` + +Функция доступна начиная с версии [2025.04](../changelog/2025.04.md). +Поглощает мутабельный словарь и преобразует его в иммутабельный. + +#### Примеры + +```yql +SELECT Block( + ($arg)->{ + $dict = ToMutDict({'foo':1}, $arg); + return FromMutDict($dict); + }); -- {'foo':1} +``` + +## MutDictInsert {#mutdictinsert} + +#### Сигнатура + +```yql +MutDictInsert(Linear<mutDictType for Dict<K,V>>,K,V)->Linear<mutDictType for Dict<K,V>> +``` + +Функция доступна начиная с версии [2025.04](../changelog/2025.04.md). +Добавляет в мутабельный словарь заданные ключ и значение, возвращает этот же мутабельный словарь. Если ключ в словаре уже существовал, словарь не меняется. +При работе с множеством (`Set`) в качестве значения следует передавать функцию `Void()`. + +#### Примеры + +```yql +SELECT Block( + ($arg)->{ + $dict = ToMutDict({'foo':1}, $arg); + $dict = MutDictInsert($dict,'foo',2); + return FromMutDict($dict); + }); -- {'foo':1} + +SELECT Block( + ($arg)->{ + $dict = ToMutDict({'foo':1}, $arg); + $dict = MutDictInsert($dict,'bar',2); + return FromMutDict($dict); + }); -- {'foo':1,'bar':2} + +SELECT Block( + ($arg)->{ + $dict = ToMutDict({'foo'}, $arg); + $dict = MutDictInsert($dict,'bar', Void()); + return FromMutDict($dict); + }); -- {'foo','bar'} +``` + +## MutDictUpsert {#mutdictupsert} + +#### Сигнатура + +```yql +MutDictUpsert(Linear<mutDictType for Dict<K,V>>,K,V)->Linear<mutDictType for Dict<K,V>> +``` + +Функция доступна начиная с версии [2025.04](../changelog/2025.04.md). +Добавляет или заменяет в мутабельный словаре заданные ключ и значение, возвращает этот же мутабельный словарь. Если ключ в словаре уже существовал, значение обновляется. + +#### Примеры + +```yql +SELECT Block( + ($arg)->{ + $dict = ToMutDict({'foo':1}, $arg); + $dict = MutDictUpsert($dict,'foo',2); + return FromMutDict($dict); + }); -- {'foo':2} + +SELECT Block( + ($arg)->{ + $dict = ToMutDict({'foo':1}, $arg); + $dict = MutDictUpsert($dict,'bar',2); + return FromMutDict($dict); + }); -- {'foo':1,'bar':2} +``` + +## MutDictUpdate {#mutdictupdate} + +#### Сигнатура + +```yql +MutDictUpdate(Linear<mutDictType for Dict<K,V>>,K,V)->Linear<mutDictType for Dict<K,V>> +``` + +Функция доступна начиная с версии [2025.04](../changelog/2025.04.md). +Заменяет в мутабельном словаре значение по заданному ключу, возвращает этот же мутабельный словарь. Если ключ в словаре не существовал, словарь не меняется. + +#### Примеры + +```yql +SELECT Block( + ($arg)->{ + $dict = ToMutDict({'foo':1}, $arg); + $dict = MutDictUpdate($dict,'foo',2); + return FromMutDict($dict); + }); -- {'foo':2} + +SELECT Block( + ($arg)->{ + $dict = ToMutDict({'foo':1}, $arg); + $dict = MutDictUpdate($dict,'bar',2); + return FromMutDict($dict); + }); -- {'foo':1} +``` + +## MutDictRemove {#mutdictremove} + +#### Сигнатура + +```yql +MutDictRemove(Linear<mutDictType for Dict<K,V>>,K)->Linear<mutDictType for Dict<K,V>> +``` + +Функция доступна начиная с версии [2025.04](../changelog/2025.04.md). +Удаляет в мутабельном словаре значение по заданному ключу, возвращает этот же мутабельный словарь. Если ключ в словаре не существовал, словарь не меняется. + +#### Примеры + +```yql +SELECT Block( + ($arg)->{ + $dict = ToMutDict({'foo':1}, $arg); + $dict = MutDictRemove($dict,'foo'); + return FromMutDict($dict); + }); -- {} + +SELECT Block( + ($arg)->{ + $dict = ToMutDict({'foo':1}, $arg); + $dict = MutDictRemove($dict,'bar'); + return FromMutDict($dict); + }); -- {'foo':1} +``` + + +## MutDictPop {#mutdictpop} + +#### Сигнатура + +```yql +MutDictPop(Linear<mutDictType for Dict<K,V>>,K)->Tuple<Linear<mutDictType for Dict<K,V>>,V?> +``` + +Функция доступна начиная с версии [2025.04](../changelog/2025.04.md). +Удаляет в мутабельном словаре значение по заданному ключу, возвращает этот же мутабельный словарь и значение по удаленному ключу. Если ключ в словаре не существовал, словарь не меняется и возвращается пустой Optional. + +#### Примеры + +```yql +SELECT Block( + ($arg)->{ + $dict = ToMutDict({'foo':1}, $arg); + $dict, $val = MutDictPop($dict,'foo'); + return (FromMutDict($dict), $val); + }); -- ({},1) + +SELECT Block( + ($arg)->{ + $dict = ToMutDict({'foo':1}, $arg); + $dict, $val = MutDictPop($dict,'bar'); + return (FromMutDict($dict), $val); + }); -- ({'foo':1},null) +``` + +## MutDictContains {#mutdictcontains} + +#### Сигнатура + +```yql +MutDictContains(Linear<mutDictType for Dict<K,V>>,K)->Tuple<Linear<mutDictType for Dict<K,V>>,Bool> +``` + +Функция доступна начиная с версии [2025.04](../changelog/2025.04.md). +Проверяет существования ключа в мутабельном словаре, возвращает этот же мутабельный словарь и результат. + +#### Примеры + +```yql +SELECT Block( + ($arg)->{ + $dict = ToMutDict({'foo':1}, $arg); + $dict, $val = MutDictContains($dict,'foo'); + return (FromMutDict($dict), $val); + }); -- ({'foo':1},True) + +SELECT Block( + ($arg)->{ + $dict = ToMutDict({'foo':1}, $arg); + $dict, $val = MutDictContains($dict,'bar'); + return (FromMutDict($dict), $val); + }); -- ({'foo':1},False) +``` + +## MutDictLookup {#mutdictlookup} + +#### Сигнатура + +```yql +MutDictLookup(Linear<mutDictType for Dict<K,V>>,K)->Tuple<Linear<mutDictType for Dict<K,V>>,V?> +``` + +Функция доступна начиная с версии [2025.04](../changelog/2025.04.md). +Получает значение по ключу в мутабельном словаре, возвращает этот же мутабельный словарь и опциональный результат. + +#### Примеры + +```yql +SELECT Block( + ($arg)->{ + $dict = ToMutDict({'foo':1}, $arg); + $dict, $val = MutDictLookup($dict,'foo'); + return (FromMutDict($dict), $val); + }); -- ({'foo':1},1) + +SELECT Block( + ($arg)->{ + $dict = ToMutDict({'foo':1}, $arg); + $dict, $val = MutDictLookup($dict,'bar'); + return (FromMutDict($dict), $val); + }); -- ({'foo':1},null) +``` + +## MutDictHasItems {#mutdicthasitems} + +#### Сигнатура + +```yql +MutDictHasItems(Linear<mutDictType for Dict<K,V>>)->Tuple<Linear<mutDictType for Dict<K,V>>,Bool> +``` + +Функция доступна начиная с версии [2025.04](../changelog/2025.04.md). +Проверяет непустоту мутабельного словаря, возвращает этот же мутабельный словарь и результат. + +#### Примеры + +```yql +SELECT Block( + ($arg)->{ + $dict = ToMutDict({'foo':1}, $arg); + $dict, $val = MutDictHasItems($dict); + return (FromMutDict($dict), $val); + }); -- ({'foo':1},True) + +SELECT Block( + ($arg)->{ + $dict = MutDictCreate(String, Int32, $arg); + $dict, $val = MutDictHasItems($dict); + return (FromMutDict($dict), $val); + }); -- ({},False) +``` + +## MutDictLength {#mutdictlength} + +#### Сигнатура + +```yql +MutDictLength(Linear<mutDictType for Dict<K,V>>)->Tuple<Linear<mutDictType for Dict<K,V>>,Uint64> +``` + +Функция доступна начиная с версии [2025.04](../changelog/2025.04.md). +Получает количество элементов в мутабельном словаре, возвращает этот же мутабельный словарь и результат. + +#### Примеры + +```yql +SELECT Block( + ($arg)->{ + $dict = ToMutDict({'foo':1}, $arg); + $dict, $val = MutDictLength($dict); + return (FromMutDict($dict), $val); + }); -- ({'foo':1},1) + +SELECT Block( + ($arg)->{ + $dict = MutDictCreate(String, Int32, $arg); + $dict, $val = MutDictLength($dict); + return (FromMutDict($dict), $val); + }); -- ({},0) +``` + +## MutDictKeys {#mutdictkeys} + +#### Сигнатура + +```yql +MutDictKeys(Linear<mutDictType for Dict<K,V>>)->Tuple<Linear<mutDictType for Dict<K,V>>,List<K>> +``` + +Функция доступна начиная с версии [2025.04](../changelog/2025.04.md). +Получает список ключей в мутабельном словаре, возвращает этот же мутабельный словарь и результат. + +#### Примеры + +```yql +SELECT Block( + ($arg)->{ + $dict = ToMutDict({'foo':1}, $arg); + $dict, $val = MutDictKeys($dict); + return (FromMutDict($dict), $val); + }); -- ({'foo':1},['foo']) + +SELECT Block( + ($arg)->{ + $dict = MutDictCreate(String, Int32, $arg); + $dict, $val = MutDictKeys($dict); + return (FromMutDict($dict), $val); + }); -- ({},[]) +``` + +## MutDictPayloads {#mutdictpayloads} + +#### Сигнатура + +```yql +MutDictPayloads(Linear<mutDictType for Dict<K,V>>)->Tuple<Linear<mutDictType for Dict<K,V>>,List<V>> +``` + +Функция доступна начиная с версии [2025.04](../changelog/2025.04.md). +Получает список значений в мутабельном словаре, возвращает этот же мутабельный словарь и результат. + +#### Примеры + +```yql +SELECT Block( + ($arg)->{ + $dict = ToMutDict({'foo':1}, $arg); + $dict, $val = MutDictPayloads($dict); + return (FromMutDict($dict), $val); + }); -- ({'foo':1},['1']) + +SELECT Block( + ($arg)->{ + $dict = MutDictCreate(String, Int32, $arg); + $dict, $val = MutDictPayloads($dict); + return (FromMutDict($dict), $val); + }); -- ({},[]) +``` + +## MutDictItems {#mutdictitems} + +#### Сигнатура + +```yql +MutDictItems(Linear<mutDictType for Dict<K,V>>)->Tuple<Linear<mutDictType for Dict<K,V>>,List<Tuple<K,V>>> +``` + +Функция доступна начиная с версии [2025.04](../changelog/2025.04.md). +Получает список кортежей с парами ключ-значение в мутабельном словаре, возвращает этот же мутабельный словарь и результат. + +#### Примеры + +```yql +SELECT Block( + ($arg)->{ + $dict = ToMutDict({'foo':1}, $arg); + $dict, $val = MutDictItems($dict); + return (FromMutDict($dict), $val); + }); -- ({'foo':1},[('foo',1)]) + +SELECT Block( + ($arg)->{ + $dict = MutDictCreate(String, Int32, $arg); + $dict, $val = MutDictItems($dict); + return (FromMutDict($dict), $val); + }); -- ({},[]) +``` diff --git a/yql/essentials/docs/ru/builtins/types.md b/yql/essentials/docs/ru/builtins/types.md index 577dd4cbb66..6a0446784d9 100644 --- a/yql/essentials/docs/ru/builtins/types.md +++ b/yql/essentials/docs/ru/builtins/types.md @@ -282,6 +282,25 @@ VoidType()->тип SELECT FormatType(VoidType()); -- Void ``` +## LinearType, DynamicLinearType {#lineartype} + +#### Сигнатура + +```yql +LinearType(Type)->линейный тип, параметризуемый заданным типом +``` + +Функции доступны начиная с версии [2025.04](../changelog/2025.04.md). +Возвращает [линейный](../types/linear.md) тип. + +#### Примеры + +```yql +SELECT FormatType(LinearType(ResourceType("Foo"))); -- Linear<Resource<'Foo'>> +SELECT FormatType(DynamicLinearType(ResourceType("Foo"))); -- DynamicLinear<Resource<'Foo'>> +``` + + ## OptionalItemType, ListItemType и StreamItemType {#optionalitemtype} #### Сигнатура @@ -310,6 +329,34 @@ SELECT FormatType(ListItemType( )); -- Int32 ``` +## LinearItemType {#linearitemtype} + +#### Сигнатура + +```yql +LinearItemType(LinearType)->тип параметра линейного типа +LinearItemType(DynamicLinearType)->тип параметра линейного типа +``` + +Функции доступны начиная с версии [2025.04](../changelog/2025.04.md). +Если этим функциям передается тип, то они выполняют действие, обратное [LinearType](#lineartype) или [DynamicLinearType](#lineartype) — возвращают тип параметра линейного типа. + +Если этим функциям передается хендл типа, то выполняют действие, обратное [LinearTypeHandle](#lineartypehandle) или [DynamicLinearTypeHandle](#lineartypehandle) — возвращают хендл типа параметра по хендлу линейного типа. + +#### Примеры + +```yql +SELECT FormatType(LinearItemType( + ParseType("Linear<Int32>") +)); -- Int32 +``` + +```yql +SELECT FormatType(LinearItemType( + ParseTypeHandle("Linear<Int32>") +)); -- Int32 +``` + ## DictKeyType и DictPayloadType {#dictkeytype} #### Сигнатура @@ -984,3 +1031,23 @@ LambdaOptionalArgumentsCount(LambdaFunction)->Uint32 SELECT LambdaOptionalArgumentsCount(($x, $y, $z?)->(if($x,$y,$z))) ; -- 1 ``` + +### LinearTypeHandle и DynamicLinearTypeHandle {#lineartypehandle} + +#### Сигнатура + +```yql +LinearTypeHandle(TypeHandle)->хэндл статического линейного типа +DynamicLinearTypeHandle(TypeHandle)->хэндл динамического линейного типа +``` + +Функции доступны начиная с версии [2025.04](../changelog/2025.04.md). +Функции строят хендл статического или динамического линейного типа по переданному хендлу типа параметра. + +#### Примеры + +```yql +SELECT FormatType(LinearTypeHandle( + TypeHandle(DataType("Bool")) +)); -- Linear<Bool> +```
\ No newline at end of file diff --git a/yql/essentials/docs/ru/changelog/2025.04.md b/yql/essentials/docs/ru/changelog/2025.04.md index 54813a75bd4..49cf7e82b2c 100644 --- a/yql/essentials/docs/ru/changelog/2025.04.md +++ b/yql/essentials/docs/ru/changelog/2025.04.md @@ -1,6 +1,17 @@ +## Изменения в типах + +Добавлены линейные типы. + ## Изменения во встроенных функциях * Добавлены функции `WithSideEffects`/`WithSideEffectsMode` для работы с побочными эффектами. +* Добавлены функции для создания новых словарей на основе существующих с модификацией содержимого: `DictInsert`/`DictUpsert`/`DictUpdate`/`DictRemove`. +* Добавлены функции для работы с изменяемыми словарями с использованием линейных типов. +* Добавлена функция `Block` для выполнения блока кода с использованием анонимных зависимых узлов. +* Добавлены функции `ToDynamicLinear`/`FromDynamicLinear` для преобразования между линейными типами. +* Добавлены функции `LinearType`/`DynamicLinearType` для построения линейных типов. +* Добавлены функции `LinearTypeHandle`/`DynamicLinearTypeHandle` для построения линейных типов во время кодогенерации. +* Добавлена функция `LinearItemType` для получения типа параметра из линейного типа. ## Изменения в выражении NOT NULL diff --git a/yql/essentials/docs/ru/types/index.md b/yql/essentials/docs/ru/types/index.md index b164e21e75b..ce139feb2c7 100644 --- a/yql/essentials/docs/ru/types/index.md +++ b/yql/essentials/docs/ru/types/index.md @@ -6,6 +6,7 @@ - [Опциональные типы](optional.md) - [Контейнеры](containers.md) - [Специальные типы](special.md) +- [Линейные типы](linear.md) - [Преобразования типов](cast.md) - [Текстовое представление типов данных](type_string.md) - [Передача параметров в формате JSON](json.md) diff --git a/yql/essentials/docs/ru/types/linear.md b/yql/essentials/docs/ru/types/linear.md new file mode 100644 index 00000000000..535ebf7408e --- /dev/null +++ b/yql/essentials/docs/ru/types/linear.md @@ -0,0 +1,37 @@ +## Линейные типы + +Большинство типов в YQL являются неизменяемыми, то есть выражения возвращают новые значения, а не меняют существующие. +Этот подход, принятый в функциональных языках программирования, позволяет проводить более агрессивные оптимизации (например, удалять общие подвыражения или кешировать результаты). +Но в некоторых сценариях это может приводить к более медленному выполнению запроса, в частности при попытке изменить одно значение в списке/словаре необходимо или возвращать полную копию, или использовать персистентные структуры данных, что также имеет дополнительные накладные расходы. + +Линейные типы предлагают другой подход — вместо того, чтобы переиспользовать неизменяемые результаты вычисления выражения, повторное использование значения линейного типа запрещено. Оно передается как бы по эстафете от точки создания до точки поглощения, где оно преобразуется уже в обычное неизменяемое значение. + +Линейные типы доступны начиная с версии [2025.04](../changelog/2025.04.md). + +Линейные типы описываются одним параметром-типом T и бывают двух видов — статически верифицируемые `Linear<T>` и верифицируемые во время выполнения `DynamicLinear<T>`. +Статически верифицируемые типы более эффективные, но имеют ограничения по композиции. + +Обычно в параметре `T` линейного типа используется тип `Resource`. В этом случае пользовательские функции (UDF) могут передавать такие данные друг другу с гарантией защиты от повторного использования в запросе, что позволяет использовать более эффективную реализацию. + +Линейные типы не являются сериализуемыми — их нельзя прочитать/записать в таблицы, т.е. их можно использовать только в середине выражений. + +Функции, принимающие или возвращающие линейные типы, делятся на 3 класса: +* Если линейный тип содержится в результате, но не в аргументах - это порождающая функция; +* Если линейный тип содержится и в аргументах и в результате - это трансформирующая функция; +* Если линейный тип содержится в аргументах, но не в результате - это поглощающая функция. + +Порождающая функция обязательно принимает зависимое выражение как минимум в одном аргументе, так как можно построить из входных аргументов несколько независимых значений линейных типов. +Создавать и поглощать линейные типы рекомендуется внутри функции [`Block`](../builtins/basic.md#block), позволяющей ввести анонимное зависимое выражение как аргумент `lambda`. + +### Правила проверки статических линейных типов `Linear<T>` + +* `Linear` типы проверяются как последняя стадия оптимизации, и, если оптимизатор устранил повторное использование выражения, то ошибки не возникает. +* `Linear` тип не может быть аргументом `lambda`. +* `Linear` тип не может возвращаться из `lambda`. +* `Linear` тип можно использовать либо сам по себе, либо как поле в `Struct/Tuple` (без вложенности). При этом по возможности отслеживается индивидуальное использование полей `Struct/Tuple` через оператор обращения к полю (точка). + +При необходимости использования значений линейных типов внутри других контейнерных типов (например, в списках) следует использовать `DynamicLinear` тип. + +### Правила проверки динамических линейных типов `DynamicLinear<T>` + +* Функция `FromDynamicLinear` или пользовательские функции (UDF) могут извлечь значение такого типа, но не более одного раза - иначе возникнет ошибка выполнения запроса. diff --git a/yql/essentials/docs/ru/types/toc_i.yaml b/yql/essentials/docs/ru/types/toc_i.yaml index 81922093172..ff4f6d68a1c 100644 --- a/yql/essentials/docs/ru/types/toc_i.yaml +++ b/yql/essentials/docs/ru/types/toc_i.yaml @@ -9,6 +9,8 @@ items: href: containers.md - name: Специальные href: special.md +- name: Линейные + href: linear.md - name: Преобразования типов href: cast.md - name: Текстовое представление типов данных diff --git a/yql/essentials/providers/common/comp_nodes/yql_parsetypehandle.cpp b/yql/essentials/providers/common/comp_nodes/yql_parsetypehandle.cpp index f520fb4c3b4..5bc55fb44c8 100644 --- a/yql/essentials/providers/common/comp_nodes/yql_parsetypehandle.cpp +++ b/yql/essentials/providers/common/comp_nodes/yql_parsetypehandle.cpp @@ -45,6 +45,7 @@ public: // TODO: Collect type annotation directly from AST. NYql::TTypeAnnotationContext typesCtx; + typesCtx.LangVer = ctx.LangVer; auto callableTransformer = NYql::CreateExtCallableTypeAnnotationTransformer(typesCtx); auto typeTransformer = NYql::CreateTypeAnnotationTransformer(callableTransformer, typesCtx); if (NYql::InstantTransform(*typeTransformer, exprRoot, *exprCtxPtr) != NYql::IGraphTransformer::TStatus::Ok) { |
