You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 14 Next »

IDIEP-126
Author
Sponsor
Created 10.09.2024
Status
DRAFT


Motivation

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

  1. Application attributes - an associative array specified on an application side. Business logic might depend on such attributes - application language, application name, date/time formats, debug tokens, etc ([2], [4]).
  2. SecuritySubject can be used to provide fine-grained access control to cache data. For example, CacheInterceptor saves the subject id it along with data and it can be used for filtering.

The requirements include:

  1. Data must be accessible from user defined functions (QuerySqlFunction, CacheInterceptor) on all nodes participated in queries.
  2. 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 such API:

  1. ServiceCallContext helps solve similar problems, but has several limitations - available only by calls via the IgniteService API and cannot be used for primitive operations.
  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 a client connection.

Application context mechanism exists in Oracle [1] and it's widely used [6]. Support similar mechanisms (session variables) 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. The access requires static methods, because objects injection isn't possible for user functions (QuerySqlFunction are static, CacheInterceptor is a cache singleton).
  3. User can easily create own QuerySqlFunction  to get access to the attribute from SQL if needed.


/** ApplicationContext interface. It's an entrypoint for all non-tabular data. */
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 attributes. */
    @QuerySqlFunction
    public static @Nullable String sessionId() {
        Map<String, String> appAttrs = ApplicationContext.getAttributes();
 
        return appAttrs == null ? null : appAttr.get("SESSION_ID");
    }
}

Setting attributes

IgniteClient (Java)

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


// 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()) {
        ...
    }
}

JDBC

The standard jdbc protocol describes the methods Connection#setClientInfo, which allow changing the values ​​of client attributes during the life of the connection [3]. Implementation features:

  1. The list of attributes that can be set using #setClientInfo is arbitrary. The documentation recommends strictly limiting the set of attributes, but this is not necessary. For example, Oracle does not have such a limitation [5]. The setClientInfo array is completely translated into the getClientAttributes array.
  2. The parameters set in setClientInfo are passed along with each JdbcRequest (this requires a new feature in JdbcThinFeature).
  3. The client must reset the set values ​​itself.


// JDBC connection to Ignite server.
try (Connection conn = DriverManager.getConnection(URL)) {
    conn.setClientInfo("SESSION_ID", "1234");
 
    ...
}

Spreading context across cluster nodes

  1. Via the QueryStartRequest SQL message protocol (for jdbc, SQL transactions)
  2. Via the transaction protocol for handling inserts (CacheInterceptor), since inserts are not always performed on the request initiator node.

Risks and Assumptions

// Describe project risks, such as API or binary compatibility issues, major protocol changes, etc.

  1. It doesn't work for non-transactional ignite-node SQL but work for JDBC.

Discussion Links

// Links to discussions on the devlist, if applicable.

Reference Links

[1] https://docs.oracle.com/en/database/oracle/oracle-database/19/dbseg/using-application-contexts-to-retrieve-user-information.html#GUID-51C9D5FA-6787-4F05-82EF-A5968BEDC5A0

[2] https://stackoverflow.com/questions/71067911/use-oracles-dbms-session-set-context-in-entity-framework-core

[3] https://docs.oracle.com/en/java/javase/11/docs/api/java.sql/java/sql/Connection.html#setClientInfo(java.lang.String,java.lang.String)

[4] https://torofimofu.blogspot.com/2014/05/oracle.html

[5] https://docs.oracle.com/database/121/JJDBC/jdbcvers.htm#BABDAEEC

[6] https://stackoverflow.com/search?tab=newest&q=SYS_CONTEXT

[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.

  • No labels