Beispiel #1
0
def derive_view(stype: s_types.Type,
                *,
                derived_name: typing.Optional[sn.SchemaName] = None,
                derived_name_quals: typing.Optional[typing.Sequence[str]] = (),
                derived_name_base: typing.Optional[str] = None,
                preserve_shape: bool = False,
                preserve_path_id: bool = False,
                is_insert: bool = False,
                is_update: bool = False,
                inheritance_merge: bool = True,
                attrs: typing.Optional[dict] = None,
                ctx: context.ContextLevel) -> s_types.Type:

    if derived_name is None:
        derived_name = derive_view_name(stype=stype,
                                        derived_name_quals=derived_name_quals,
                                        derived_name_base=derived_name_base,
                                        ctx=ctx)

    if is_insert:
        vtype = s_types.ViewType.Insert
    elif is_update:
        vtype = s_types.ViewType.Update
    else:
        vtype = s_types.ViewType.Select

    if attrs is None:
        attrs = {}
    else:
        attrs = dict(attrs)

    attrs['view_type'] = vtype

    derived: s_types.Type

    if isinstance(stype, s_abc.Collection):
        ctx.env.schema, derived = stype.derive_subtype(ctx.env.schema,
                                                       name=derived_name)

    elif isinstance(stype, s_inh.InheritingObject):
        ctx.env.schema, derived = stype.derive_subtype(
            ctx.env.schema,
            name=derived_name,
            inheritance_merge=inheritance_merge,
            refdict_whitelist={'pointers'},
            mark_derived=True,
            preserve_path_id=preserve_path_id,
            attrs=attrs,
        )

        if (not stype.generic(ctx.env.schema)
                and isinstance(derived, s_sources.Source)):
            scls_pointers = stype.get_pointers(ctx.env.schema)
            derived_own_pointers = derived.get_pointers(ctx.env.schema)

            for pn, ptr in derived_own_pointers.items(ctx.env.schema):
                # This is a view of a view.  Make sure query-level
                # computable expressions for pointers are carried over.
                src_ptr = scls_pointers.get(ctx.env.schema, pn)
                computable_data = ctx.source_map.get(src_ptr)
                if computable_data is not None:
                    ctx.source_map[ptr] = computable_data

                if src_ptr in ctx.pending_cardinality:
                    ctx.pointer_derivation_map[src_ptr].append(ptr)
                    stmtctx.pend_pointer_cardinality_inference(ptrcls=ptr,
                                                               ctx=ctx)

    ctx.view_nodes[derived.get_name(ctx.env.schema)] = derived

    if preserve_shape and stype in ctx.env.view_shapes:
        ctx.env.view_shapes[derived] = ctx.env.view_shapes[stype]

    return derived
Beispiel #2
0
def derive_view(
    stype: s_types.Type,
    *,
    derived_name: Optional[sn.QualName] = None,
    derived_name_quals: Optional[Sequence[str]] = (),
    derived_name_base: Optional[str] = None,
    preserve_shape: bool = False,
    preserve_path_id: bool = False,
    is_insert: bool = False,
    is_update: bool = False,
    is_delete: bool = False,
    inheritance_merge: bool = True,
    attrs: Optional[Dict[str, Any]] = None,
    ctx: context.ContextLevel,
) -> s_types.Type:

    if derived_name is None:
        assert isinstance(stype, s_obj.DerivableObject)
        derived_name = derive_view_name(stype=stype,
                                        derived_name_quals=derived_name_quals,
                                        derived_name_base=derived_name_base,
                                        ctx=ctx)

    if is_insert:
        exprtype = s_types.ExprType.Insert
    elif is_update:
        exprtype = s_types.ExprType.Update
    elif is_delete:
        exprtype = s_types.ExprType.Delete
    else:
        exprtype = s_types.ExprType.Select

    if attrs is None:
        attrs = {}
    else:
        attrs = dict(attrs)

    attrs['expr_type'] = exprtype

    derived: s_types.Type

    if isinstance(stype, s_abc.Collection):
        ctx.env.schema, derived = stype.derive_subtype(
            ctx.env.schema,
            name=derived_name,
            attrs=attrs,
        )

    elif isinstance(stype, s_obj.DerivableInheritingObject):
        existing = ctx.env.schema.get(derived_name,
                                      default=None,
                                      type=type(stype))
        if existing is not None:
            if ctx.recompiling_schema_alias:
                # When recompiling schema alias, we, essentially
                # re-derive the already-existing objects exactly.
                derived = existing
            else:
                raise AssertionError(
                    f'{type(stype).get_schema_class_displayname()}'
                    f' {derived_name!r} already exists', )
        else:
            ctx.env.schema, derived = stype.derive_subtype(
                ctx.env.schema,
                name=derived_name,
                inheritance_merge=inheritance_merge,
                inheritance_refdicts={'pointers'},
                mark_derived=True,
                transient=True,
                preserve_path_id=preserve_path_id,
                attrs=attrs,
            )

        if (not stype.generic(ctx.env.schema)
                and isinstance(derived, s_sources.Source)):
            scls_pointers = stype.get_pointers(ctx.env.schema)
            derived_own_pointers = derived.get_pointers(ctx.env.schema)

            for pn, ptr in derived_own_pointers.items(ctx.env.schema):
                # This is a view of a view.  Make sure query-level
                # computable expressions for pointers are carried over.
                src_ptr = scls_pointers.get(ctx.env.schema, pn)
                computable_data = ctx.source_map.get(src_ptr)
                if computable_data is not None:
                    ctx.source_map[ptr] = computable_data

                if src_ptr in ctx.env.pointer_specified_info:
                    ctx.env.pointer_derivation_map[src_ptr].append(ptr)

    else:
        raise TypeError("unsupported type in derive_view")

    ctx.view_nodes[derived.get_name(ctx.env.schema)] = derived

    if preserve_shape and stype in ctx.env.view_shapes:
        ctx.env.view_shapes[derived] = ctx.env.view_shapes[stype]

    ctx.env.created_schema_objects.add(derived)

    return derived
Beispiel #3
0
def derive_view(
    stype: s_types.Type,
    *,
    derived_name: Optional[sn.QualName] = None,
    derived_name_quals: Optional[Sequence[str]] = (),
    preserve_shape: bool = False,
    preserve_path_id: bool = False,
    exprtype: s_types.ExprType = s_types.ExprType.Select,
    inheritance_merge: bool = True,
    attrs: Optional[Dict[str, Any]] = None,
    ctx: context.ContextLevel,
) -> s_types.Type:

    if derived_name is None:
        assert isinstance(stype, s_obj.DerivableObject)
        derived_name = derive_view_name(stype=stype,
                                        derived_name_quals=derived_name_quals,
                                        ctx=ctx)

    if attrs is None:
        attrs = {}
    else:
        attrs = dict(attrs)

    attrs['expr_type'] = exprtype

    derived: s_types.Type

    if isinstance(stype, s_types.Collection):
        ctx.env.schema, derived = stype.derive_subtype(
            ctx.env.schema,
            name=derived_name,
            attrs=attrs,
        )

    elif isinstance(stype, (s_objtypes.ObjectType, s_scalars.ScalarType)):
        existing = ctx.env.schema.get(derived_name,
                                      default=None,
                                      type=type(stype))
        if existing is not None:
            if ctx.recompiling_schema_alias:
                # When recompiling schema alias, we, essentially
                # re-derive the already-existing objects exactly.
                derived = existing
            else:
                raise AssertionError(
                    f'{type(stype).get_schema_class_displayname()}'
                    f' {derived_name!r} already exists', )
        else:
            ctx.env.schema, derived = stype.derive_subtype(
                ctx.env.schema,
                name=derived_name,
                inheritance_merge=inheritance_merge,
                inheritance_refdicts={'pointers'},
                mark_derived=True,
                transient=True,
                preserve_path_id=preserve_path_id,
                attrs=attrs,
            )

        if (stype.is_view(ctx.env.schema)
                # XXX: Previously, the main check here was just for
                # (not stype.generic(...)). generic isn't really the
                # right way to figure out if something is a view, since
                # some aliases will be generic. On changing it to is_view
                # instead, though, two GROUP BY tests that grouped
                # on the result of a group broke
                # (test_edgeql_group_by_group_by_03{a,b}).
                #
                # It's probably a bug that this matters in that case, and
                # it is an accident that group bindings are named in such
                # a way that they count as being generic, but for now
                # preserve that behavior.
                and not (stype.generic(ctx.env.schema) and
                         (view_ir := ctx.view_sets.get(stype)) and
                         (scope_info := ctx.path_scope_map.get(view_ir))
                         and scope_info.binding_kind) and isinstance(
                             derived, s_objtypes.ObjectType)):
            assert isinstance(stype, s_objtypes.ObjectType)
            scls_pointers = stype.get_pointers(ctx.env.schema)
            derived_own_pointers = derived.get_pointers(ctx.env.schema)

            for pn, ptr in derived_own_pointers.items(ctx.env.schema):
                # This is a view of a view.  Make sure query-level
                # computable expressions for pointers are carried over.
                src_ptr = scls_pointers.get(ctx.env.schema, pn)
                computable_data = (ctx.source_map.get(src_ptr)
                                   if src_ptr else None)
                if computable_data is not None:
                    ctx.source_map[ptr] = computable_data

                if src_ptr in ctx.env.pointer_specified_info:
                    ctx.env.pointer_derivation_map[src_ptr].append(ptr)
Beispiel #4
0
def derive_view(
    stype: s_types.Type,
    *,
    derived_name: Optional[sn.SchemaName] = None,
    derived_name_quals: Optional[Sequence[str]] = (),
    derived_name_base: Optional[str] = None,
    preserve_shape: bool = False,
    preserve_path_id: bool = False,
    is_insert: bool = False,
    is_update: bool = False,
    is_delete: bool = False,
    inheritance_merge: bool = True,
    attrs: Optional[Dict[str, Any]] = None,
    ctx: context.ContextLevel,
) -> s_types.Type:

    if derived_name is None:
        assert isinstance(stype, s_obj.DerivableObject)
        derived_name = derive_view_name(stype=stype,
                                        derived_name_quals=derived_name_quals,
                                        derived_name_base=derived_name_base,
                                        ctx=ctx)

    if is_insert:
        exprtype = s_types.ExprType.Insert
    elif is_update:
        exprtype = s_types.ExprType.Update
    elif is_delete:
        exprtype = s_types.ExprType.Delete
    else:
        exprtype = s_types.ExprType.Select

    if attrs is None:
        attrs = {}
    else:
        attrs = dict(attrs)

    attrs['expr_type'] = exprtype

    derived: s_types.Type

    if isinstance(stype, s_abc.Collection):
        ctx.env.schema, derived = stype.derive_subtype(ctx.env.schema,
                                                       name=derived_name)

    elif isinstance(stype, s_obj.DerivableInheritingObject):
        ctx.env.schema, derived = stype.derive_subtype(
            ctx.env.schema,
            name=derived_name,
            inheritance_merge=inheritance_merge,
            inheritance_refdicts={'pointers'},
            mark_derived=True,
            transient=True,
            preserve_path_id=preserve_path_id,
            attrs=attrs,
        )

        if (not stype.generic(ctx.env.schema)
                and isinstance(derived, s_sources.Source)):
            scls_pointers = stype.get_pointers(ctx.env.schema)
            derived_own_pointers = derived.get_pointers(ctx.env.schema)

            for pn, ptr in derived_own_pointers.items(ctx.env.schema):
                # This is a view of a view.  Make sure query-level
                # computable expressions for pointers are carried over.
                src_ptr = scls_pointers.get(ctx.env.schema, pn)
                computable_data = ctx.source_map.get(src_ptr)
                if computable_data is not None:
                    ctx.source_map[ptr] = computable_data

                if src_ptr in ctx.pending_cardinality:
                    ctx.pointer_derivation_map[src_ptr].append(ptr)
                    stmtctx.pend_pointer_cardinality_inference(ptrcls=ptr,
                                                               ctx=ctx)

    else:
        raise TypeError("unsupported type in derive_view")

    ctx.view_nodes[derived.get_name(ctx.env.schema)] = derived

    if preserve_shape and stype in ctx.env.view_shapes:
        ctx.env.view_shapes[derived] = ctx.env.view_shapes[stype]

    ctx.env.created_schema_objects.add(derived)

    return derived