Skip to content

tdfs4ds.feature_store.type_changes

tdfs4ds.feature_store.type_changes

Type changes of registered features (0.3.5.1).

A feature (data domain, entity, name) has ONE catalog entry, so one value type and one storage table, whatever the number of processes computing it. A pre-existing feature whose source type changed used to be ignored silently: its values kept going into the old FEATURE_VALUE type, cast or truncated.

The source type is compared to the stored one by whether the values FIT, never by equality:

  • fits: same type, or one whose values the stored type holds (a shorter VARCHAR of the same character set or LATIN into UNICODE, an integer into a wider integer, FLOAT or a large enough DECIMAL, a smaller DECIMAL into a larger one, a lower TIMESTAMP precision). Nothing to say.
  • wider: a type exists that holds the stored type, this process's type and every other producer's type (:func:common_type). Migrating the feature to it is safe for every producer, and the processes that already fit keep fitting: there is no ping-pong.
  • incompatible: no common type (text and number, number and date, ...). One feature cannot hold both kinds of values.

upload_features refuses a re-registration with a feature that does not fit, and the message explains the alternatives with code (:func:conflict_message); run() logs the same text as a warning and writes with the stored type. The migration itself is relocation.plan_type_change.

_INT_RANK module-attribute

_INT_RANK = {'BYTEINT': 1, 'SMALLINT': 2, 'INTEGER': 3, 'INT': 3, 'BIGINT': 4}

_INT_DIGITS module-attribute

_INT_DIGITS = {1: 3, 2: 5, 3: 10, 4: 19}

_INT_NAME module-attribute

_INT_NAME = {1: 'BYTEINT', 2: 'SMALLINT', 3: 'INTEGER', 4: 'BIGINT'}

_FLOATS module-attribute

_FLOATS = {'FLOAT', 'REAL', 'DOUBLE PRECISION', 'DOUBLE'}

_TEXT_RE module-attribute

_TEXT_RE = compile('^(VARCHAR|CHAR|CHARACTER\\s+VARYING|CHARACTER|VARGRAPHIC|LONG\\s+VARCHAR)\\s*(?:\\(\\s*(\\d+)\\s*\\))?(.*)$')

_DEC_RE module-attribute

_DEC_RE = compile('^(?:DECIMAL|NUMERIC|DEC|NUMBER)\\s*(?:\\(\\s*(\\d+)\\s*(?:,\\s*(\\d+)\\s*)?\\))?')

_TS_RE module-attribute

_TS_RE = compile('^TIMESTAMP\\s*(?:\\(\\s*(\\d+)\\s*\\))?(\\s+WITH\\s+TIME\\s+ZONE)?')

_CS_RE module-attribute

_CS_RE = compile('CHAR(?:ACTER)?\\s+SET\\s+(\\w+)')

_LEN_RE module-attribute

_LEN_RE = compile('^((?:VARCHAR|CHARACTER\\s+VARYING)\\s*\\(\\s*)\\d+(\\s*\\))', IGNORECASE)

_with_length

_with_length(sql_type, n) -> str

sql_type with its VARCHAR length replaced by n, every other character kept (its character-set spelling is part of the storage table name: rewriting it would change the name).

_norm

_norm(sql_type) -> str

parse_type

parse_type(sql_type) -> dict

{"kind": int|float|decimal|text|date|timestamp|other, ...} for a SQL type text. Pure.

_cs_fits

_cs_fits(src_cs, dst_cs) -> bool

fits

fits(source, stored) -> bool

Whether every value of type source is stored without loss in type stored. Pure.

_round_up

_round_up(n: int, multiple) -> int

common_type

common_type(types, varchar_multiple=None) -> Optional[str]

The narrowest type holding every value of types, or None when there is none. Pure.

One of types when it holds the others; otherwise a computed one (integers -> the widest integer, integers and decimals -> a DECIMAL large enough (FLOAT beyond 38 digits), any FLOAT -> FLOAT, texts -> VARCHAR(max) in UNICODE when any is UNICODE, the length rounded up to varchar_multiple). Mixed kinds (text and number, ...) -> None.

unify_varchar_types

unify_varchar_types(types: Dict[str, str], multiple=1024) -> Dict[str, str]

One VARCHAR type per character set for a whole result set. Pure.

types: {column: sql type} of the feature columns of a process. Every VARCHAR of a character set gets VARCHAR(ceil(longest / multiple) * multiple) of that set, the longest being taken over the result set; LATIN and UNICODE stay apart. multiple=None keeps the longest length unrounded. Other types are returned unchanged.

new_feature_types

new_feature_types(source_types: Dict[str, str], new_names, stored: Dict[str, dict], multiple=1024) -> Dict[str, str]

The types of the features being registered, one text type per process and character set. Pure.

source_types: {column: source type} of every feature of the result set; new_names: the features not registered yet; stored: {FEATURE upper: {"type": ...}} of the registered ones. A new VARCHAR takes the stored type of a registered VARCHAR of the same character set that holds it (the widest such), so it joins the process's existing text table; otherwise the new VARCHARs of a character set share VARCHAR(ceil(longest / multiple) * multiple), the longest taken over the NEW features. Registered features never change type here. Non-text types are returned unchanged.

classify

classify(name, stored, source, others=(), varchar_multiple=None) -> Optional[dict]

The conflict of one feature, or None when source fits stored. Pure.

others: [{"process_id", "view", "type"}] of the OTHER processes computing the feature (type None when their view could not be read).

select_item

select_item(view_ddl: Optional[str], column: str) -> Optional[str]

The select-list item that produces column in a view text, when it can be found (<expression> AS <column> on one line, or the bare column). Pure, best effort.

_expr

_expr(item: Optional[str], column: str) -> str

_cast_lines

_cast_lines(view, item, column, to_type) -> List[str]

conflict_message

conflict_message(conflicts: List[dict], process_view: str, process_id: Optional[str] = None, view_ddl: Optional[str] = None, other_ddls: Optional[Dict[str, str]] = None, at_run: bool = False, entity=None, data_domain=None) -> str

The refusal (registration) or warning (at_run) text with the alternatives and code. Pure.

_rows

_rows(sql)

stored_types

stored_types(entity_columns, feature_names, data_domain=None) -> Dict[str, dict]

{FEATURE_NAME upper: {"type", "table", "database", "id"}} of the registered features of this entity and domain (current catalog rows).

other_producers

other_producers(feature_names, entity_columns, data_domain=None, exclude_view=None, exclude_pid=None) -> Dict[str, List[dict]]

{FEATURE upper: [{"process_id", "view", "type"}]}: the other registered processes of this domain and entity that compute each feature, with their source type (None when the view could not be read).

find_conflicts

find_conflicts(source_types: Dict[str, str], entity_columns, data_domain=None, process_view=None, process_id=None, varchar_multiple=None, stored=None) -> List[dict]

The conflicts of the registered features of a result set (I/O: the catalog, and the other producers only when a conflict exists). source_types: {feature: type} after the VARCHAR unification.