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
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
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)
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