Skip to content

eXate MariaDB JDBC Driver

Installing the Driver

Add the following dependency to your Maven pom.xml:

<dependency>
    <groupId>com.exate</groupId>
    <artifactId>exate-mariadb-jdbc</artifactId>
    <version>X.XX</version>
</dependency>

Repository Configuration

The driver is hosted on an Azure Artifacts Maven feed. Configure your Maven repository settings:

<repository>
    <id>eXate-Maven</id>
    <url>https://pkgs.dev.azure.com/exatetechnology/data-science/_packaging/{YOUR_FEED}/maven/v1</url>
    <releases>
        <enabled>true</enabled>
    </releases>
    <snapshots>
        <enabled>true</enabled>
    </snapshots>
</repository>

Your project will be provided with a specific feed URL and access token.


Driver Class

When configuring your JDBC client (e.g. DBeaver, Denodo), register the following driver class:

com.exate.mariadb.ExateDriver

The JDBC URL format is:

jdbc:mariadb://host:3306/database

Authentication

A JWT token must be available for authentication. The token can be provided in three ways:

1. Environment Variable

export EXATE_TOKEN=your_jwt_token_here

2. Query-Level Token

Include the token as a SQL comment prefixed to your query:

-- EXATE_TOKEN: your_jwt_token_here
SELECT *
FROM Employee;

3. Denodo Users

Use the Init SQL statements feature in the datasource configuration:

SET SESSION EXATE_TOKEN TO @{your_jwt_token_here}

The token passed via Init SQL statements or Query-Level Token always takes precedence over the environment variable.


Configuring the Driver

API Gateway URI

The driver communicates with the APIgator service for all encryption and decryption operations. Configure the apigator.uri driver property in your JDBC client (e.g. DBeaver, Denodo), or set the environment variable:

export APIGATOR_URI=your-apigator-endpoint

# With a custom port:
export APIGATOR_URI=your-apigator-endpoint:port
  • If no port is supplied, the driver defaults to TLS port 443.
  • The apigator.uri driver property takes precedence over the environment variable.
  • If neither is set, the driver defaults to localhost.
  • Do not include a protocol prefix (http:// / https://). The driver always connects to APIgator over TLS.

Additional Claims (Matching Rules)

Claims are extracted from the JWT token. Additional claims can be supplied via the MATCHING_RULES environment variable as a JSON array:

export MATCHING_RULES='[{"attributeName":"department","attributeValue":"finance"},{"attributeName":"region","attributeValue":"eu"}]'

Protection Modes

The driver supports three protection modes, controlled by the EXATE_PROTECTION_TYPE environment variable:

Mode Value Write (INSERT/UPDATE) Read (SELECT)
Cryptographic (default) cryptographic Pseudonymise (reversible encrypt) Reconstruct (decrypt)
Mask-Read maskread Pass-through (no write protection) Datamasking (one-way mask)
Mask-Write maskwrite Datamasking (one-way mask) Pass-through (no read decryption)
export EXATE_PROTECTION_TYPE=cryptographic   # default
export EXATE_PROTECTION_TYPE=maskread
export EXATE_PROTECTION_TYPE=maskwrite

Entitlements

For any table requiring encryption or decryption, create an eXate Datagator entitlement named using the following format:

{database_name}.{schema_name}

MariaDB note: MariaDB does not have a separate schema namespace — the schema and the database are the same concept. Use the database name for both components. For example, for database mydb:

mydb.mydb

Columns matching the configured attributes will be:

  • Encrypted on INSERT and UPDATE operations.
  • Decrypted on SELECT queries.

Refer to the eXate User Guide for details on configuring entitlements within eXate Datagator.


Row-Level Access Control (RLAC)

When an eXate manifest includes a WHERE clause filter, the driver automatically injects it into every SELECT. Example:

SELECT *
FROM Employee
WHERE FirstName = 'John'
-- becomes (transparently):
SELECT *
FROM Employee
WHERE FirstName = '⟨ciphertext⟩'
  AND department = 'Sales'

Querying Encrypted Data

SELECT

-- EXATE_TOKEN: your_jwt_token_here
SELECT *
FROM Employee;

INSERT

-- EXATE_TOKEN: your_jwt_token_here
INSERT INTO Employee (EmployeeID, FirstName, LastName)
VALUES (1, 'John', 'Doe');

UPDATE

-- EXATE_TOKEN: your_jwt_token_here
UPDATE Employee
SET FirstName = 'Jane'
WHERE EmployeeID = 1;

Exact Match Searches

Encrypted columns support exact match WHERE clause filtering:

-- EXATE_TOKEN: your_jwt_token_here
SELECT *
FROM Employee
WHERE FirstName = 'John';

Unsupported Queries

Partial match searches using LIKE are not supported for encrypted columns.


Stored Procedures

The driver supports transparent encryption and decryption through stored procedure calls using standard JDBC callable statement escape syntax: {CALL ProcedureName(...)}.

No-Parameter Call

String sql = "--EXATE_TOKEN: " + token + "\n{CALL GetAllEmployees}";
try(
CallableStatement cstmt = connection.prepareCall(sql);
ResultSet rs = cstmt.executeQuery()){
        while(rs.

next()){
        System.out.

println(rs.getString("FirstName")); // decrypted
        }
        }

IN Parameter (Encrypted Before Execution)

String sql = "--EXATE_TOKEN: " + token + "\n{CALL GetEmployeesByFirstName(?)}";
try(
CallableStatement cstmt = connection.prepareCall(sql)){
        cstmt.

setString(1,"John"); // encrypted transparently
    try(
ResultSet rs = cstmt.executeQuery()){
        while(rs.

next()){
        System.out.

println(rs.getString("FirstName")); // decrypted
        }
        }
        }

OUT Parameters (Decrypted on Return)

Define your stored procedure with OUT parameters:

CREATE PROCEDURE GetEmployeeSummaryWithOutParams(
    OUT p_FirstName VARCHAR (100),
    OUT p_Count INT
)
BEGIN
SELECT FirstName
INTO p_FirstName
FROM Employee
ORDER BY EmployeeID ASC LIMIT 1;
SELECT COUNT(*)
INTO p_Count
FROM Employee;
END;

Invoke via JDBC:

String sql = "--EXATE_TOKEN: " + token + "\n{CALL GetEmployeeSummaryWithOutParams(?, ?)}";
try(
CallableStatement cstmt = connection.prepareCall(sql)){
        cstmt.

registerOutParameter(1,Types.VARCHAR);  // p_FirstName — decrypted
    cstmt.

registerOutParameter(2,Types.INTEGER);  // p_Count
    cstmt.

execute();
// Consume any result sets before reading OUT params
    while(cstmt.

getMoreResults()){ /* drain */ }
String firstName = cstmt.getString(1); // cleartext
int total = cstmt.getInt(2);
}

Note: Only a single OUT parameter per statement is supported. Consume all result sets before reading OUT parameter values.


Advanced Features

Self-JOIN and CTE Support

Fully supported. Each alias in a self-join is an independent Apigator group. CTE aliases resolve to base tables.

Reconstruct Coalescer

Batches concurrent reconstruct (decrypt) calls to reduce gRPC round-trips:

export EXATE_COALESCE_ENABLED=true
export EXATE_COALESCE_WINDOW_MS=2
export EXATE_COALESCE_MAX_BATCH=20

Environment Variable Reference

Core Settings

Variable Default Description
EXATE_TOKEN (required) Apigator bearer token
APIGATOR_URI (required) Apigator gRPC host:port
EXATE_PROTECTION_TYPE cryptographic cryptographic, maskread, or maskwrite
MATCHING_RULES null JSON array of additional claim matchers
USE_TLS true TLS for gRPC

gRPC Channel Tuning

Variable Default Description
EXATE_GRPC_CHANNEL_POOL true Reuse gRPC channels
EXATE_GRPC_POOL_IDLE_MINUTES 10 Idle channel eviction (minutes)
EXATE_GRPC_KEEPALIVE_SECS 300 Keepalive ping interval (seconds)
EXATE_GRPC_KEEPALIVE_TIMEOUT_SECS 20 Keepalive ping timeout (seconds)
EXATE_GRPC_KEEPALIVE_WITHOUT_CALLS false Ping even with no active RPCs
EXATE_GRPC_MAX_INBOUND_MB 20 Max inbound message (MB)

Coalescer

Variable Default Description
EXATE_COALESCE_ENABLED false Batch concurrent reconstruct calls
EXATE_COALESCE_WINDOW_MS 2 Batch window (ms)
EXATE_COALESCE_MAX_BATCH 20 Max per batch

Optional Job Config Overrides

Variable Default Description
EXATE_SNAPSHOT_DATE null Point-in-time snapshot date
EXATE_DATA_OWNING_COUNTRY_CODE null ISO country code of data owner
EXATE_COUNTRY_CODE null ISO country code override
EXATE_DATA_USAGE_ID null Data usage identifier
EXATE_THIRD_PARTY_ID null Third-party identifier
EXATE_EXECUTION_CONTEXT null Execution context label
EXATE_SILENT_MODE null Suppress protection errors silently
EXATE_PROTECT_NULL_VALUES null Encrypt NULL values
EXATE_PRESERVE_STRING_LENGTH null Preserve ciphertext length
EXATE_USE_RESTRICTED_TEXT null Replace unreadable with restricted text
EXATE_RESTRICTED_TEXT null Custom restricted text
EXATE_DATA_CONSISTENT_ACROSS_ORG null Org-wide deterministic encryption

Observability

Variable Default Description
EXATE_ENABLE_METRICS true Log cache/latency metrics at shutdown

Further Information

For more details, refer to the official eXate documentation or contact support.