Exasol Ansible Collection Entity Model#
The Exasol Ansible Collection automates two kinds of Exasol interaction. exasol_query and
exasol_script are direct-execution surfaces: each run is a trusted-operator command that
executes operator-supplied SQL and reports what happened, with no persisted collection-owned
state. exasol_schema, exasol_user, exasol_role, and exasol_grants are declarative
reconciliation surfaces: each run observes real Exasol catalog state and plans the minimal
statements needed to move it toward the requested state, owner, comment, membership, or
privilege set. exasol_info is a read-only surface that never changes Exasol state.
SCHEMA, EXASOL_USER, and EXASOL_ROLE are independent aggregate roots: each is a Exasol
catalog object addressed by its own exact name, and each is reconciled from its own catalog view
(EXA_ALL_SCHEMAS/EXA_SCHEMAS, EXA_ALL_USERS, EXA_ALL_ROLES). GRANT is a distinct
aggregate whose identity is the tuple (principal, principal type, object, privilege); it
references EXASOL_USER or EXASOL_ROLE as the granted principal and, for object privileges, a
schema optionally further qualified by a named object (disambiguated by object_type when
supplied) as the granted object, but it does not own or cascade-delete those aggregates. A single
exasol_grants invocation reconciles a batch of such tuples at once, one per
system_privileges entry and per object_privileges[].privileges entry. QUERY_EXECUTION and
SCRIPT_EXECUTION are ephemeral
per-invocation read models, not persisted catalog objects: they exist only for the duration of one
module run and are re-derived from scratch on every call. SERVER_INFO is likewise a
per-invocation read model.
Aggregate Boundary Diagram#
flowchart LR
subgraph schema_aggregate["Aggregate Root: SCHEMA"]
direction TB
SCHEMA["SCHEMA<br/>Root Entity"]
SCHEMA_NAME["SCHEMA_NAME<br/>Exact Identifier"]
SCHEMA_OWNER["OWNER<br/>User or Role Reference"]
SCHEMA_COMMENT["COMMENT<br/>Value Object"]
SCHEMA_QUOTA["RAW_SIZE_LIMIT<br/>Value Object"]
SCHEMA --> SCHEMA_NAME
SCHEMA --> SCHEMA_OWNER
SCHEMA --> SCHEMA_COMMENT
SCHEMA --> SCHEMA_QUOTA
end
subgraph user_aggregate["Aggregate Root: EXASOL_USER"]
direction TB
EXASOL_USER["EXASOL_USER<br/>Root Entity"]
USER_NAME["USER_NAME<br/>Exact Identifier"]
USER_AUTH_METHOD["AUTHENTICATION_METHOD<br/>Value Object (password | ldap)"]
USER_PASSWORD["PASSWORD<br/>Secret Value Object"]
USER_LDAP_DN["LDAP_DN<br/>Secret Value Object"]
USER_SESSION_GRANT["CREATE SESSION Grant<br/>Optional On Creation"]
EXASOL_USER --> USER_NAME
EXASOL_USER --> USER_AUTH_METHOD
EXASOL_USER --> USER_PASSWORD
EXASOL_USER --> USER_LDAP_DN
EXASOL_USER --> USER_SESSION_GRANT
end
subgraph role_aggregate["Aggregate Root: EXASOL_ROLE"]
direction TB
EXASOL_ROLE["EXASOL_ROLE<br/>Root Entity"]
ROLE_NAME["ROLE_NAME<br/>Exact Identifier"]
EXASOL_ROLE --> ROLE_NAME
end
subgraph grant_aggregate["Aggregate Root: GRANT"]
direction TB
GRANT["GRANT<br/>Root Entity"]
GRANT_PRINCIPAL["PRINCIPAL<br/>User or Role Reference"]
GRANT_OBJECT["OBJECT<br/>Schema, Optionally Qualified<br/>by a Named Object"]
GRANT_OBJECT_TYPE["OBJECT_TYPE<br/>Value Object (function | script |<br/>table | view | virtual_schema)"]
GRANT_PRIVILEGE["PRIVILEGE<br/>Value Object"]
GRANT --> GRANT_PRINCIPAL
GRANT --> GRANT_OBJECT
GRANT --> GRANT_OBJECT_TYPE
GRANT --> GRANT_PRIVILEGE
end
subgraph query_execution_aggregate["Read Model: QUERY_EXECUTION"]
direction TB
QUERY_EXECUTION["QUERY_EXECUTION<br/>Per-Invocation Read Model"]
EXECUTED_QUERIES_Q["EXECUTED_QUERIES<br/>Ordered Statement List"]
QUERY_EXECUTION -->|one statement or an ordered, unbound statement batch| EXECUTED_QUERIES_Q
end
subgraph script_execution_aggregate["Read Model: SCRIPT_EXECUTION"]
direction TB
SCRIPT_EXECUTION["SCRIPT_EXECUTION<br/>Per-Invocation Read Model"]
EXECUTED_QUERIES_S["EXECUTED_QUERIES<br/>pyexasol-Split Statement List"]
SCRIPT_EXECUTION --> EXECUTED_QUERIES_S
end
SERVER_INFO["SERVER_INFO<br/>Per-Invocation Read Model"]
query_execution_aggregate ~~~ script_execution_aggregate
script_execution_aggregate ~~~ SERVER_INFO
GRANT_PRINCIPAL -. "references" .-> EXASOL_USER
GRANT_PRINCIPAL -. "references" .-> EXASOL_ROLE
GRANT_OBJECT -. "references" .-> SCHEMA
SCHEMA_OWNER -. "references" .-> EXASOL_USER
SCHEMA_OWNER -. "references" .-> EXASOL_ROLE
Entity Relationship Diagram#
erDiagram
SCHEMAS ||--o| EXASOL_USERS : owned_by_user
SCHEMAS ||--o| EXASOL_ROLES : owned_by_role
GRANTS }o--o| EXASOL_USERS : grants_to_user
GRANTS }o--o| EXASOL_ROLES : grants_to_role
GRANTS }o--o| SCHEMAS : grants_on_schema
Domain Entity attributes#
Each section represents a domain entity rather than a specific technical artifact. The domain model is derived from the Gherkin acceptance scenarios, and the code should express the same domain concepts. The existing acceptance tests effectively define and shape the domain model described here. However, this alignment is not currently enforced.
SCHEMA#
Attribute |
Description |
Data Type |
Validation Rules |
|---|---|---|---|
schema_name |
Exact schema identifier |
String |
Primary Key, exact identifier preserved as supplied |
exists |
Whether the schema currently exists |
Boolean |
Derived from |
owner |
User or role that owns the schema |
String / Reference |
Optional; reconciled via |
comment |
Free-text schema comment |
String / null |
Optional; |
raw_size_limit |
Storage quota |
Integer / null |
Optional; reconciled via |
new_name |
Requested rename target |
String |
Optional; reconciled via |
cascade |
Whether |
Boolean |
Default |
EXASOL_USER#
Attribute |
Description |
Data Type |
Validation Rules |
|---|---|---|---|
user_name |
Exact user identifier |
String |
Primary Key, exact identifier preserved as supplied |
exists |
Whether the user currently exists |
Boolean |
Derived from |
authentication_method |
Login credential mechanism |
Enum ( |
Optional; defaults to |
password |
Login secret |
String (write-only) |
Never returned in results or error messages; required to create or alter a user while |
ldap_dn |
LDAP distinguished name bound to the user |
String (write-only) |
Never returned in results or error messages; required to create or alter a user while |
update_password |
Password update policy |
Enum ( |
|
create_session |
Whether |
Boolean |
Default |
cascade |
Whether |
Boolean |
Default |
EXASOL_ROLE#
Attribute |
Description |
Data Type |
Validation Rules |
|---|---|---|---|
role_name |
Exact role identifier |
String |
Primary Key, exact identifier preserved as supplied |
exists |
Whether the role currently exists |
Boolean |
Derived from |
cascade |
Whether |
Boolean |
Default |
GRANT#
Attribute |
Description |
Data Type |
Validation Rules |
|---|---|---|---|
principal |
Granted user or role name |
String |
Foreign Key to |
principal_type |
Whether |
Enum ( |
Exactly one of |
system_privileges |
Server-wide privileges (for example |
List |
Optional; checked against |
object_privileges |
Batch of schema-scoped privilege requests |
List |
Optional; each entry reconciled independently against |
object_privileges[].schema |
Schema an entry’s privileges apply to |
String |
Required per entry |
object_privileges[].object |
Object within the schema, unqualified name |
String / null |
Optional; omitted means the privileges apply to the schema itself |
object_privileges[].object_type |
Kind of the named object |
Enum ( |
Optional; disambiguates same-named objects of different kinds when |
object_privileges[].privileges |
Object privileges to reconcile (for example |
List |
Required per entry |
state |
Desired grant state |
Enum ( |
|
QUERY_EXECUTION#
Per-invocation read model produced by exasol_query.
Attribute |
Description |
Data Type |
Validation Rules |
|---|---|---|---|
query |
Requested statement or ordered statement list |
String / List |
Required; a list is an ordered statement batch |
positional_args |
Values bound to |
List |
Only valid when |
named_args |
Values bound to |
Map<String, Any> |
Only valid when |
changed |
Whether any executed statement was not read-only |
Boolean |
|
query_result |
Rows from the last statement |
List |
Empty when the last statement has no result set |
query_all_results |
One result list per statement, in execution order |
List<List |
Empty entries for statements without a result set |
executed_queries |
Statements executed, or predicted in check mode |
List |
In check mode, empty unless the batch contains a write statement |
rowcount |
Per-statement affected/selected row count |
List |
Empty in check mode |
execution_time_ms |
Per-statement execution time |
List |
Empty in check mode |
SCRIPT_EXECUTION#
Per-invocation read model produced by exasol_script.
Attribute |
Description |
Data Type |
Validation Rules |
|---|---|---|---|
script |
Requested multi-statement SQL script |
String |
Required; always a single string, never a list |
changed |
Whether any statement pyexasol executed was not read-only |
Boolean |
|
query_result |
Rows from the last executed statement |
List |
Empty when the last statement has no result set |
query_all_results |
One result list per statement pyexasol split from the script |
List<List |
Empty in check mode |
executed_queries |
Statements pyexasol executed, in order |
List |
In check mode, the whole supplied script as one entry instead of the real per-statement split |
rowcount |
Per-statement affected/selected row count |
List |
Empty in check mode |
execution_time_ms |
Per-statement execution time |
List |
Empty in check mode |
SERVER_INFO#
Per-invocation read model produced by exasol_info.
Attribute |
Description |
Data Type |
Validation Rules |
|---|---|---|---|
version |
Exasol server version |
String |
Non-empty |
database_name |
Exasol database name |
String |
Non-empty |
cluster_size |
Number of nodes in the Exasol cluster |
Integer |
At least |
changed |
Always |
Boolean |
This use case never alters Exasol state |
Aggregate Insight#
exasol_schema, exasol_user, exasol_role, and exasol_grants reconcile independent
aggregates from observed catalog state and always predict the identical statement plan in check
mode that a real run would execute. exasol_query and exasol_script are direct-execution
surfaces over the ephemeral QUERY_EXECUTION and SCRIPT_EXECUTION read models: they are exempt
from the state-reconciliation rule and from automatic redaction of operator-supplied SQL text,
per doc/design/security/tier_segregation_and_trusted_operator_boundary.md. exasol_script
additionally defers all statement-splitting to upstream pyexasol (execute_sql_script) so the
collection never maintains a second SQL-script parser; its check mode is therefore coarser than
its real execution, predicting a non-read-only script as one opaque unit rather than the real
per-statement breakdown. exasol_info produces the SERVER_INFO read model without touching any
aggregate.