Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

When processing data, users want to have access to non-tabular (not stored in cache structures) data. Example of such data is application  

  1. Application attributes - an associative array specified on an application side.

...

  1. To run certain logic that depends on the value of the attribute (for example, the application language Business logic might depend on such attributes - application language, application name, date/time formats, debug tokens, etc ([2], progress monitoring [4]).
  2. To audit changes in the database (for SecuritySubject can be used to provide fine-grained access control to cache data. For example, CacheInterceptor extracts the user from the attributes and saves saves the subject id it along with data ).
  3. To optimize the transfer of parameters to processing functions (for example, multiple QuerySqlFunction use the same parameter and it is convenient to take it from the attributes, rather than transfer it separately to each function).

...

  1. and it can be used for filtering.

The requirements include:

  1. Attributes Data must be accessible from user defined functions (QuerySqlFunction, CacheInterceptor) on all nodes participated in queries.
  2. Setting attributes via protocols: thin client, jdbc:thin.
  3. Attribute values Application attributes ​​can change during the life of the connection (a connection from a connection pool can be sequentially used by different applications).

Ignite does not have a similar public such API:

  1. ServiceCallContext helps solve similar problems, but has several limitations . The main one is that it is only available in - available only by calls via the IgniteService API and cannot be used for single primitive operations or transactions.
  2. UserAttributes - allows to set user attributes, but the attribute values ​​are fixed for the entire lifetime of the connection.
  3. ClientListenerConnectionContext - it's available only on single node , which directly accepts connection from a client connection.

A similar Application context mechanism exists in Oracle [1] and it's widely used [6]. Setting Support similar mechanisms (session variables is also available in ) exist in multiple DBMS (e.g. SQLServer [8], Snowflake [7], MySQL [9]).

Description

Accessing attributes

  1. ApplicationContext is an entrypoint for accessing all non-tabular data.
  2. Access The access requires static methods, because objects injection isn't possible for user functions (QuerySqlFunction are static, CacheInterceptor is a cache singleton for cache).
  3. User can easily create own QuerySqlFunction  to get access to the attribute from SQL if needed.


Code Block
languagejava
/** ApplicationContext interface. It's an entrypoint for all non-tabular informationdata. */
public class ApplicationContext {
    /** @return Application attributes set for current thread. */
    public static @Nullable Map<String, String> getAttributes();

    /** @return Current SecuritySubject. */
	public static @Nullable SecuritySubject getSecuritySubject();
 }
 
/** Example, use it in QuerySqlFunction. */
public static class UserDefinedFunctions {
    /** @return Session ID, set with application attributeattributes. */
    @QuerySqlFunction
    public static @Nullable String sessionId() {
        Map<String, String> appAttrs = ApplicationContext.getAttributes();
 
        return appAttrs == null ? null : appAttr.get("SESSION_ID");
    }
}

Setting attributes

Ignite 

...

attributes

...

languagejava

...

IgniteClient (Java)

  1. Client should mirror the logic of Ignite node.
  2. New feature is needed in the ClientBitmaskFeature protocol.


Code Block
languagejava
// Extends the interface with new public method.
public interface ClientTransactions {
	...

    /** @param appAttrs Application attributes. */
    public ClientTransactions withApplicationAttributes(Map<String, String> appAttrs);
}

// Example of usage.
try (IgniteClient cln = Ignition.startClient(clnCfg)) {
    Map<String, String> appAttrs = F.asMap("SESSION_ID", "1234");

    try (ClientTransaction tx = cln.transactions().withApplicationAttributes(appAttrs).txStart()) {
        ...
    }
}

...

[7] https://docs.snowflake.com/en/sql-reference/session-variables#session-variable-functions

[8] https://learn.microsoft.com/en-us/sql/t-sql/functions/session-context-transact-sql?view=sql-server-ver16

[9] https://dev.mysql.com/doc/refman/8.4/en/user-variables.html

Tickets

// Links or report with relevant JIRA tickets.