Source code for exasol.nb_connector.language_container_activation

import pyexasol

from exasol.nb_connector.connections import open_pyexasol_connection
from exasol.nb_connector.secret_store import Secrets

# All secret store entries with language container activation commands
# will have this common prefix in their keys.
ACTIVATION_KEY_PREFIX = "language_container_activation_"


def get_registered_languages_string(conf: Secrets) -> str:
    """
    Gets the session level language definitions from the database. Returns a string
    in a format of a space separated list: "<alias1>=<url1> <alias2=<url2> ..."
    """

    with open_pyexasol_connection(conf) as pyexasol_conn:
        query_result = pyexasol_conn.execute(
            "SELECT SESSION_VALUE FROM SYS.EXA_PARAMETERS WHERE PARAMETER_NAME='SCRIPT_LANGUAGES'"
        ).fetchall()
        return query_result[0][0]


def get_registered_languages(conf: Secrets) -> dict[str, str]:
    """
    Collects the existing, session level, language definitions from the database.
    Returns them as a dictionary {alias: language_url}
    """

    lang_definitions_str = get_registered_languages_string(conf)
    result: dict[str, str] = {}
    for lang_definition in lang_definitions_str.split():
        alias, lang_url = lang_definition.split("=", maxsplit=1)
        result[alias] = lang_url
    return result


def get_requested_languages(conf: Secrets) -> dict[str, str]:
    """
    Collects language definitions from the secret store. Returns them as a
    dictionary {alias: language_url}.

    Raises a RuntimeError if tt finds two entries with the same alias but
    different language definitions (i.e. URLs).
    """

    result: dict[str, str] = {}
    # Iterate over all entries that look like language definitions.
    for key, value in conf.items():
        if key.startswith(ACTIVATION_KEY_PREFIX):
            alias, lang_url = value.split("=", maxsplit=1)
            alias = alias.upper()
            if alias in result:
                if result[alias] != lang_url:
                    error = (
                        "Unable to merge multiple language definitions. "
                        f"Found incompatible definitions for the language alias {alias}."
                    )
                    raise RuntimeError(error)
            else:
                result[alias] = lang_url
    return result


[docs] def get_activation_sql(conf: Secrets) -> str: """ Merges multiple language definitions (i.e. URLs) found in the secret store with language definitions currently registered in the database at the SESSION level. Returns a language activation command which combines all that language definitions. For details on how an activation command may look like please refer to https://docs.exasol.com/db/latest/database_concepts/udf_scripts/adding_new_packages_script_languages.htm The secret store entries containing language definitions should have keys with a common prefix. This prefix is defined in the ACTIVATION_KEY_PREFIX. Multiple language definitions in the secret store would normally have unique aliases. In case there are more than one entry with the same alias, their definitions should match. Otherwise, a RuntimeError will be raised. If a language with the same aliases is already present in the database, its definition will be overwritten, no exception raised. """ # Collect language definitions, either already registered in the database or # recorded in the secret store. lang_definitions = get_registered_languages(conf) lang_definitions.update(get_requested_languages(conf)) # Build and return an SQL command for the language container activation. merged_langs_str = " ".join( f"{key}={value}" for key, value in lang_definitions.items() ) return f"ALTER SESSION SET SCRIPT_LANGUAGES='{merged_langs_str}';"
[docs] def open_pyexasol_connection_with_lang_definitions( conf: Secrets, **kwargs ) -> pyexasol.ExaConnection: """ Opens a `pyexasol` connection and applies the `ALTER SESSION` command using all registered languages. """ conn = open_pyexasol_connection(conf, **kwargs) conn.execute(get_activation_sql(conf)) return conn