normlite.engine.context

Provide key runtime abstraction for executing SQL statements.

The design of SQL statement execution separates responsibilities cleanly using the following key classes:

SQL Statement Execution Design

Class

Responsibility

normlite.sql.base.Executable

Describes what to execute (e.g. normlite.sql.ddl.CreateTable, normlite.sql.dml.Insert) notiondbapi._model.NotionPage for more details).

normlite.sql.base.SQLCompiler

Translates the normlite.sql.base.Executable into a serializable payload.

ExecutionContext

Orchestrates binding, compilation, and result setup.

normlite.engine.base.Connection

Owns the DBAPI connection and executes statements.

normlite.engine.base.Engine

Factory for normlite.sql.base.SQLCompiler and Connection.

Added in version 0.7.0: ExecutionContext orchestrates binding, compilation, and result setup.

Module Contents

class normlite.engine.context.ExecutionStyle(*args, **kwds)[source]

Bases: enum.Enum

Define the execution style for a context.

Added in version 0.8.0.

EXECUTE

A single operation is executed.

It indicates cursor.execute() will be used.

Changed in version 0.9.0.

EXECUTEMANY

Multiple operations are executed on a query result.

It indicates that cursor.execute() will be used. This execution style is used for DELETE/UPDATE statements where the execution loop is driven by the query results.

Changed in version 0.9.0.

INSERTMANYVALUES

The same operation is executed multiple times with different parameters.

This execution style is used for INSERT statements that add multiple rows. The execution loop is driven by the parameters.

Added in version 0.9.0.

class normlite.engine.context.ExecutionContext(engine: normlite.engine.base.Engine, connection: normlite.engine.base.Connection, cursor: normlite.notiondbapi.dbapi2.Cursor, compiled: normlite.sql.base.Compiled, distilled_params: normlite.engine.interfaces._CoreMultiExecuteParams | None = None, *, execution_options: Mapping[str, Any] | None = None)[source]

Orchestrate binding, compilation, and result setup.

This class manages the key activities for the execution of SQL statements. It binds dynamically the parameters at runtime prior to execution using the owned normlite.sql.Compiled object. After execution, it sets up the normlite.cursor.CursorResult object to be returned using the owned normlite.notiondbapi.dbapi2.Cursor (which contains the result set of the executed statement).

Changed in version 0.8.0: _bind_params() now binds values to named arguments by looking up parameters recursively. This enables to support bind parameters for all DDL/DML constructs.

See also

normlite SQL compiler normlite.sql.compiler module

Here you find examples illustrating the code emitted for various DDL/DML constructs.

Added in version 0.7.0: _bind_params() expects that parameters have been provided for all columns. It raises normlite.exceptions.ArgumentError if this is not the case.

engine: normlite.engine.base.Engine

Engine which the connection is associated with.

Added in version 0.8.0.

connection: normlite.engine.base.Connection

Connection associated with the engine.

_cursor: normlite.notiondbapi.dbapi2.Cursor | None

The DBAPI cursor holding the result set of the executed statement if no pre-fetch/post-fetch is required.

Added in version 0.8.0.

compiled: normlite.sql.base.Compiled

The compiled statement.

Changed in version 0.8.0.

compiled_dict: dict

The JSON object representing result of the compilation + parameter binding.

This attribute must be computed prior to executing the context.

Added in version 0.8.0.

Example:

# insert many values, note "payload" is a list containing each row to be added
{
    "operation": {
        "endpoint": "pages",
        "request": "create",
    },
    "payload" : [
        {
            "parent": {
                "type": "database_id",
                "database_id": "59833787-2cf9-4fdf-8782-e53db20768a5",
            },
            "properties": {
                "name": {
                    "title": [
                        {
                            "text": {
                                "content": "Galileo Galilei"
                            }
                        }
                    ]
                },
                "is_active" : {
                    "checkbox": True
                }
            }
        },
        {
            "parent": {
                "type": "database_id",
                "database_id": "59833787-2cf9-4fdf-8782-e53db20768a5",
            },
            "properties": {
                "name": {
                    "title": [
                        {
                            "text": {
                                "content": "Isaac Newton"
                            }
                        }
                    ]
                },
                "is_active" : {
                    "checkbox": False
                }
            }
        },
    ]
}
invoked_stmt: normlite.sql.base.Executable | None

The normlite.sql.base.Executable statement object that was given in the first place.

This should be structurally equivalent to compiled.statement, but not necessarily the same object as in a caching scenario the compiled form will have been extracted from the cache.

Added in version 0.8.0.

distilled_params: normlite.engine.interfaces._CoreMultiExecuteParams

The normalized bind parameters containing the values to be bound into compiled_dict.

Added in version 0.8.0.

path_params: dict | None

The path params for the DBAPI operation.

Added in version 0.8.0.

query_params: dict | None

The query params for the DBAPI operation.

Added in version 0.8.0.

payload: list[dict] | None

The payload parameter for the DBAPI operation.

Added in version 0.8.0.

execution_style: ExecutionStyle

The style of DBAPI cursor method that will be used to execute a statement.

Added in version 0.8.0.

execution_options: normlite.engine.interfaces.ExecutionOptions

Execution options associated with the current statement execution.

Added in version 0.8.0.

_result: normlite.engine.cursor.CursorResult | None

The cursor result of the operation(s) executed in this context.

Added in version 0.8.0.

_rowcount: int | None

The rowcount returned by an INSERT/UPDATE/DELETE/SELECT statement.

Added in version 0.9.0.

_returned_primary_keys_rows: list[tuple] | None

The list of primary keys returned by the last executed DML statement as row.

Added in version 0.9.0.

bulk_operation: dict | None

The operation to be executed when execution_style is ExecutionStyle.EXCUTEMANY.

Added in version 0.9.0.

bulk_parameters: list[dict] | None

The parameters set for the bulk operation when execution_style is ExecutionStyle.EXCUTEMANY.

Added in version 0.9.0.

_result_cursor: normlite.notiondbapi.dbapi2.Cursor | None

The cursor used internally for prefetching/postfetching Notion pages in delete/update/insert.

Added in version 0.9.0.

_staged_result_cursor: normlite.notiondbapi.dbapi2.Cursor | None

The cursor used internally to route results after pre-fetch/post-fetching.

Added in version 0.9.0.

resolved_params: dict | None = None
property cursor: normlite.notiondbapi.dbapi2.Cursor | None

Return the effective DBAPI cursor for this execution.

This property implements cursor routing, selecting the cursor that represents the final, user-visible outcome of the execution.

Design principle

The decision of which cursor to expose is made entirely upstream during the execution pipeline, specifically in the statement’s _finalize_execution() phase. This property does not contain any conditional logic related to statement type (INSERT/UPDATE/DELETE), execution options, or returning behavior.

Instead, it simply reflects the outcome of that decision:

  • If a post-processing step (e.g. bulk update, post-fetch, RETURNING)

has produced a new cursor, it will have been assigned to _result_cursor and is returned here. - Otherwise, the original execution cursor (_cursor) is returned.

Added in version 0.9.0.

_get_exec_cursor() normlite.notiondbapi.dbapi2.Cursor[source]

Return the execution cursor to be used in the pipeline.

This method is a private API that only normlite.engine.base.Connection may use. It hides the implementaion details related to which cursor shall be used to execute the DBAPI operation. The cursor is crucial because it holds the result set(s). Different cursors are created, depending on the statement being executed. For EXECUTE and INSERTMANYVALUES style statements (e.g., SELECT or bulk inserts), the _cursor is used to execute the operation and to hold the corresponding result set. For EXECUTEMANY style statements (e.g., DELETE/UPDATE/INSERT…RETURNING), the _staged_result_cursor is used to execute the operation and to hold the corresponding result set.

Added in version 0.9.0.

_determine_execution_style() ExecutionStyle[source]
property operation: dict

Return the DBAPI operation.

Added in version 0.8.0.

property parameters: dict | list[dict]

Return the DBAPI parameters for the related operation.

This attribute provides the DBAPI parameters as a dictionary with the following keys:

  • “path_params”: This stores the path parameters for the DBAPI operation.

  • “query_params”: This stores the query paramters for the DBAPI operation.

  • “payload”: This stores the payload for the DBAPI operation.

parameters is a materialized view based on the parameters calculations done in pre_exec(). It aggregates the computed attributes path_params, query_params, and payload into the DBAPI parameters dictionary structure.

See also

normlite.notion_sdk.client.AbstractNotionClient for the client parameters API structure.

Changed in version 0.9.0.

Added in version 0.8.0.

pre_exec() None[source]

Perform value binding and type adaptation before execution.

..versionchanged: 0.9.0

In this version, binding supports bulk inserts with multi-parameters.

Changed in version 0.8.0: In this version, binding has been extended to support the override case (user-provided parameters in the execute call). Execution options resolution is also supported now.

_assert_all_params_consumed(resolved_params: list[dict])[source]
post_exec() None[source]

Perform row counting preservation after execution.

Changed in version 0.9.0.

_is_no_params(distilled)[source]
_resolve_parameters(overrides: normlite.engine.interfaces._CoreMultiExecuteParams) Sequence[Mapping[str, normlite.sql.elements.BindParameter]][source]

Resolve binding parameters using the values passed as normalized parameters in the constructor.

Supports both single and multi-parameter execution.

Added in version 0.8.0.

_build_overrides_sets() list[Mapping[str, Any]][source]

Build the list of parameter dictionaries used for execution.

Returns a list of dictionaries, one per execution (even for single execution).

_validate_insert_values(resolved_parameters: dict[str, normlite.sql.elements.BindParameter] | list[dict[str, normlite.sql.elements.BindParameter]])[source]
_resolve_exec_options() None[source]
_resolve_bindparam(bindparam: normlite.sql.elements.BindParameter) dict[source]
_bind_params(template: dict, params: dict) dict[source]

Helper for binding parameters at runtime.

setup_cursor_result() normlite.engine.cursor.CursorResult[source]

Finalize execution and materialize a normlite.engine.cursor.CursorResult.

This method represents the terminal step of the execution pipeline. It materializes a read-only façade (CursorResult) over the DBAPI cursor’s post-execution state and freezes the outcome of this execution.

Key design guarantees

  • Execution is frozen

Once this method is called, the execution outcome is considered final. No further mutation of the underlying cursor or execution context is permitted or expected.

  • Single-execution binding

The returned CursorResult is bound to exactly one execution of one compiled statement. Each ExecutionContext may produce at most one result object.

  • Materialized result façade

The CursorResult acts as a read-only façade over the cursor’s final state. It exposes rows, metadata, and identity information derived from the cursor without copying or re-buffering data.

  • Identity preservation

At the time this method is called:
  • execution has fully completed

  • all row and object identities (e.g. Notion object IDs / lastrowid)

have been resolved and preserved - the cursor reflects the final, stable execution state

  • Source of truth

The execution context and its cursor remain the authoritative source of execution data. The result object does not mutate or re-interpret execution state.

Lifecycle and usage

This method is not intended for direct invocation by users. It is called internally by the connection execution pipeline once statement execution has completed successfully.

Repeated calls to this method return the same CursorResult instance, ensuring idempotence and enforcing one-time result creation.

Note

  • The underlying DBAPI cursor must not be mutated after this method has been invoked.

  • Result consumption (iteration, scalar access, identity inspection)

may occur lazily, but the execution itself is fully complete.

Changed in version 0.8.0: This version formalizes structural membership and API contract.

returns:
A read-only result object representing the finalized outcome of

this execution.

rtype:

CursorResult

get_rowcount() int | None[source]

Return the DBAPI cursor.rowcount value, or in some cases an interpreted value.

See normlite.engine.cursor.CursorResult.rowcount for details on this.

Added in version 0.9.0.