예제 #1
0
def _inject_tname(
        insert_stmt: qlast.InsertQuery, *,
        ctx: context.ContextLevel) -> None:

    for el in insert_stmt.shape:
        if isinstance(el.compexpr, qlast.InsertQuery):
            _inject_tname(el.compexpr, ctx=ctx)

    assert isinstance(insert_stmt.subject.steps[0], qlast.BaseObjectRef)
    insert_stmt.shape.append(
        qlast.ShapeElement(
            expr=qlast.Path(
                steps=[qlast.Ptr(ptr=qlast.ObjectRef(name='_tname'))],
            ),
            compexpr=qlast.Path(
                steps=[
                    qlast.Introspect(
                        type=qlast.TypeName(
                            maintype=insert_stmt.subject.steps[0],
                        ),
                    ),
                    qlast.Ptr(ptr=qlast.ObjectRef(name='name')),
                ],
            ),
        ),
    )
예제 #2
0
    def visit_order(self, node):
        if not isinstance(node, gql_ast.ObjectValue):
            raise g_errors.GraphQLTranslationError(
                f'an object is expected for "order"')

        # if there is no specific ordering, then order by id
        if not node.fields:
            return [
                qlast.SortExpr(
                    path=qlast.Path(
                        steps=[qlast.Ptr(ptr=qlast.ObjectRef(name='id'))],
                        partial=True,
                    ),
                    direction=qlast.SortAsc,
                )
            ]

        # Ordering is handled by specifying a list of special Ordering objects.
        # Validation is already handled by this point.
        orderby = []
        for enum in node.fields:
            name, direction, nulls = self._visit_order_item(enum)
            orderby.append(
                qlast.SortExpr(
                    path=qlast.Path(
                        steps=[qlast.Ptr(ptr=qlast.ObjectRef(name=name))],
                        partial=True,
                    ),
                    direction=direction,
                    nones_order=nulls,
                ))

        return orderby
예제 #3
0
파일: expr.py 프로젝트: yew1eb/edgedb
def compile_coalesce_insert(left: qlast.Expr, right: qlast.InsertQuery,
                            ctx: context.ContextLevel) -> irast.Set:

    # This maybe could have been implemented with less code by
    # modifying compile_operator directly, but all of those approaches
    # seemed to require some spaghetti code or adding dead-drop state
    # in context.
    with ctx.newscope() as lctx:
        lir = setgen.ensure_set(dispatch.compile(left, ctx=lctx), ctx=lctx)
        lir = setgen.scoped_set(setgen.ensure_stmt(lir, ctx=lctx), ctx=lctx)
    with ctx.newscope() as rctx:
        rir = setgen.ensure_set(stmt.compile_InsertQuery(right,
                                                         ctx=rctx,
                                                         conditioned_on=lir),
                                ctx=rctx)
        rir = setgen.scoped_set(setgen.ensure_stmt(rir, ctx=rctx), ctx=rctx)

    with ctx.new() as subctx:
        subctx.anchors = subctx.anchors.copy()
        l_alias = subctx.aliases.get('l')
        subctx.anchors[l_alias] = lir
        r_alias = subctx.aliases.get('r')
        subctx.anchors[r_alias] = rir

        rpath = qlast.Path(steps=[qlast.ObjectRef(name=r_alias)])
        lpath = qlast.Path(steps=[qlast.ObjectRef(name=l_alias)])

        # Only one side of the the ?? will possibly be non-empty, so
        # we just union them together.
        e = qlast.BinOp(op='UNION', left=lpath, right=rpath)

        return setgen.ensure_set(dispatch.compile(e, ctx=subctx), ctx=subctx)
예제 #4
0
def get_config_type_shape(
    schema: s_schema.Schema,
    stype: s_objtypes.ObjectType,
    path: List[qlast.Base],
) -> List[qlast.ShapeElement]:
    from . import objtypes as s_objtypes
    shape = []
    seen: Set[str] = set()

    stypes = [stype] + list(stype.descendants(schema))

    for t in stypes:
        t_name = t.get_name(schema)

        for unqual_pn, p in t.get_pointers(schema).items(schema):
            pn = str(unqual_pn)
            if pn in ('id', '__type__') or pn in seen:
                continue

            elem_path: List[qlast.Base] = []

            if t != stype:
                elem_path.append(
                    qlast.TypeIntersection(type=qlast.TypeName(
                        maintype=qlast.ObjectRef(
                            module=t_name.module,
                            name=t_name.name,
                        ), ), ), )

            elem_path.append(qlast.Ptr(ptr=qlast.ObjectRef(name=pn)))

            ptype = p.get_target(schema)
            assert ptype is not None

            if isinstance(ptype, s_objtypes.ObjectType):
                subshape = get_config_type_shape(schema, ptype,
                                                 path + elem_path)
                subshape.append(
                    qlast.ShapeElement(
                        expr=qlast.Path(steps=[
                            qlast.Ptr(ptr=qlast.ObjectRef(name='_tname'), ),
                        ], ),
                        compexpr=qlast.Path(steps=path + elem_path + [
                            qlast.Ptr(ptr=qlast.ObjectRef(name='__type__')),
                            qlast.Ptr(ptr=qlast.ObjectRef(name='name')),
                        ], ),
                    ), )
            else:
                subshape = []

            shape.append(
                qlast.ShapeElement(
                    expr=qlast.Path(steps=elem_path),
                    elements=subshape,
                ), )

            seen.add(pn)

    return shape
예제 #5
0
def extend_path(expr: qlast.Expr, field: str) -> qlast.Path:
    step = qlast.Ptr(ptr=qlast.ObjectRef(name=field))

    if isinstance(expr, qlast.Path):
        return qlast.Path(
            steps=[*expr.steps, step],
            partial=expr.partial,
        )
    else:
        return qlast.Path(steps=[expr, step])
예제 #6
0
파일: viewgen.py 프로젝트: sbdchd/edgedb
def _inline_type_computable(
    ir_set: irast.Set,
    stype: s_objtypes.ObjectType,
    compname: str,
    propname: str,
    *,
    shape_ptrs: List[ShapePtr],
    ctx: context.ContextLevel,
) -> None:
    assert isinstance(stype, s_objtypes.ObjectType)

    ptr: Optional[s_pointers.Pointer]
    try:
        ptr = setgen.resolve_ptr(stype, compname, track_ref=None, ctx=ctx)
        # The pointer might exist on the base type. That doesn't count,
        # and we need to re-inject it.
        if not ptr.get_computable(ctx.env.schema):
            ptr = None
    except errors.InvalidReferenceError:
        ptr = None

    if ptr is None:
        ql = qlast.ShapeElement(
            expr=qlast.Path(
                steps=[qlast.Ptr(
                    ptr=qlast.ObjectRef(name=compname),
                    direction=s_pointers.PointerDirection.Outbound,
                )],
            ),
            compexpr=qlast.Path(
                steps=[
                    qlast.Source(),
                    qlast.Ptr(
                        ptr=qlast.ObjectRef(name='__type__'),
                        direction=s_pointers.PointerDirection.Outbound,
                    ),
                    qlast.Ptr(
                        ptr=qlast.ObjectRef(name=propname),
                        direction=s_pointers.PointerDirection.Outbound,
                    )
                ]
            )
        )
        with ctx.newscope(fenced=True) as scopectx:
            scopectx.anchors = scopectx.anchors.copy()
            scopectx.anchors[qlast.Source().name] = ir_set
            ptr = _normalize_view_ptr_expr(
                ql, stype, path_id=ir_set.path_id, ctx=scopectx)

    view_shape = ctx.env.view_shapes[stype]
    view_shape_ptrs = {p for p, _ in view_shape}
    if ptr not in view_shape_ptrs:
        view_shape.insert(0, (ptr, qlast.ShapeOp.ASSIGN))
        shape_ptrs.insert(0, (ir_set, ptr, qlast.ShapeOp.ASSIGN))
예제 #7
0
def get_config_type_shape(schema, stype,
                          path) -> typing.List[qlast.ShapeElement]:
    shape = []
    seen = set()

    stypes = [stype] + list(stype.descendants(schema))

    for t in stypes:
        t_name = t.get_name(schema)

        for pn, p in t.get_pointers(schema).items(schema):
            if pn in ('id', '__type__') or pn in seen:
                continue

            elem_path = []

            if t is not stype:
                elem_path.append(
                    qlast.TypeIndirection(type=qlast.TypeName(
                        maintype=qlast.ObjectRef(
                            module=t_name.module,
                            name=t_name.name,
                        ), ), ), )

            elem_path.append(qlast.Ptr(ptr=qlast.ObjectRef(name=pn)))

            ptype = p.get_target(schema)

            if ptype.is_object_type():
                subshape = get_config_type_shape(schema, ptype,
                                                 path + elem_path)
                subshape.append(
                    qlast.ShapeElement(
                        expr=qlast.Path(steps=[
                            qlast.Ptr(ptr=qlast.ObjectRef(name='_tname'), ),
                        ], ),
                        compexpr=qlast.Path(steps=path + elem_path + [
                            qlast.Ptr(ptr=qlast.ObjectRef(name='__type__')),
                            qlast.Ptr(ptr=qlast.ObjectRef(name='name')),
                        ], ),
                    ), )
            else:
                subshape = []

            shape.append(
                qlast.ShapeElement(
                    expr=qlast.Path(steps=elem_path),
                    elements=subshape,
                ), )

            seen.add(pn)

    return shape
예제 #8
0
def get_param_anchors_for_callable(
    params: s_func.ParameterLikeList,
    schema: s_schema.Schema,
    *,
    inlined_defaults: bool,
) -> Tuple[Dict[str, irast.Parameter], List[qlast.AliasedExpr], ]:
    anchors = {}
    aliases = []

    if inlined_defaults:
        anchors['__defaults_mask__'] = irast.Parameter(
            name='__defaults_mask__',
            typeref=irtyputils.type_to_typeref(  # note: no cache
                schema,
                cast(s_scalars.ScalarType, schema.get('std::bytes')),
            ),
        )

    pg_params = s_func.PgParams.from_params(schema, params)
    for pi, p in enumerate(pg_params.params):
        p_shortname = p.get_shortname(schema)
        anchors[p_shortname] = irast.Parameter(
            name=p_shortname,
            typeref=irtyputils.type_to_typeref(schema, p.get_type(schema)))

        if p.get_default(schema) is None:
            continue

        if not inlined_defaults:
            continue

        aliases.append(
            qlast.AliasedExpr(
                alias=p_shortname,
                expr=qlast.
                IfElse(condition=qlast.BinOp(left=qlast.FunctionCall(
                    func=('std', 'bytes_get_bit'),
                    args=[
                        qlast.Path(
                            steps=[qlast.ObjectRef(name='__defaults_mask__')]),
                        qlast.IntegerConstant(value=str(pi)),
                    ]),
                                             right=qlast.IntegerConstant(
                                                 value='0'),
                                             op='='),
                       if_expr=qlast.Path(
                           steps=[qlast.ObjectRef(name=p_shortname)]),
                       else_expr=qlast._Optional(
                           expr=p.get_ql_default(schema)))))

    return anchors, aliases
예제 #9
0
파일: cast.py 프로젝트: xing0713/edgedb
def _cast_array(ir_set: irast.Set, orig_stype: s_types.Type,
                new_stype: s_types.Type, *, srcctx: parsing.ParserContext,
                ctx: context.ContextLevel) -> irast.Base:

    direct_cast = _find_cast(orig_stype, new_stype, srcctx=srcctx, ctx=ctx)

    if direct_cast is None:
        if not new_stype.is_array():
            raise errors.QueryError(
                f'cannot cast {orig_stype.get_displayname(ctx.env.schema)!r} '
                f'to {new_stype.get_displayname(ctx.env.schema)!r}',
                context=srcctx)
        el_type = new_stype.get_subtypes(ctx.env.schema)[0]
    else:
        el_type = new_stype

    orig_el_type = orig_stype.get_subtypes(ctx.env.schema)[0]

    el_cast = _find_cast(orig_el_type, el_type, srcctx=srcctx, ctx=ctx)

    if el_cast is not None and el_cast.get_from_cast(ctx.env.schema):
        # Simple cast
        return _cast_to_ir(ir_set, el_cast, orig_stype, new_stype, ctx=ctx)
    else:
        pathctx.register_set_in_scope(ir_set, ctx=ctx)

        with ctx.new() as subctx:
            subctx.anchors = subctx.anchors.copy()
            source_alias = subctx.aliases.get('a')
            subctx.anchors[source_alias] = ir_set

            unpacked = qlast.FunctionCall(
                func=('std', 'array_unpack'),
                args=[
                    qlast.Path(steps=[qlast.ObjectRef(name=source_alias)], ),
                ],
            )

            elements = qlast.FunctionCall(
                func=('std', 'array_agg'),
                args=[
                    qlast.TypeCast(
                        expr=unpacked,
                        type=typegen.type_to_ql_typeref(el_type, ctx=subctx),
                    ),
                ],
            )

            array_ir = dispatch.compile(elements, ctx=subctx)

            if direct_cast is not None:
                array_stype = s_types.Array.from_subtypes(
                    ctx.env.schema, [el_type])
                return _cast_to_ir(array_ir,
                                   direct_cast,
                                   array_stype,
                                   new_stype,
                                   ctx=ctx)
            else:
                return array_ir
예제 #10
0
    def reduce_Expr_PathStep(self, *kids):
        path = kids[0].val
        if not isinstance(path, qlast.Path):
            path = qlast.Path(steps=[path])

        path.steps.append(kids[1].val)
        self.val = path
예제 #11
0
def new_set(
    *,
    stype: s_types.Type,
    ctx: context.ContextLevel,
    ircls: Type[irast.Set] = irast.Set,
    **kwargs: Any,
) -> irast.Set:
    """Create a new ir.Set instance with given attributes.

    Absolutely all ir.Set instances must be created using this
    constructor.
    """
    if (stype not in ctx.type_rewrites
            and isinstance(stype, s_objtypes.ObjectType)
            and ctx.env.options.apply_query_rewrites
            and (filters := stype.get_access_policy_filters(ctx.env.schema))):
        qry = qlast.SelectQuery(result=qlast.Path(
            steps=[s_utils.name_to_ast_ref(stype.get_name(ctx.env.schema))]), )
        for f in filters:
            assert isinstance(f.qlast, qlast.Expr)
            qry.where = astutils.extend_binop(qry.where, f.qlast)

        with ctx.detached() as subctx:
            subctx.expr_exposed = False
            # This is a global rewrite operation that is done once
            # per type, and so we don't really care if we're in a
            # temporary scope or not.
            subctx.path_scope = subctx.env.path_scope.root
            subctx.in_temp_scope = False
            # Put a placeholder to prevent recursion.
            subctx.type_rewrites[stype] = irast.Set()
            filtered_set = dispatch.compile(qry, ctx=subctx)
            assert isinstance(filtered_set, irast.Set)
            subctx.type_rewrites[stype] = filtered_set
예제 #12
0
    def reduce_PathStepName(self, *kids):
        from edb.schema import pointers as s_pointers

        self.val = qlast.Path(steps=[
            qlast.Ptr(ptr=kids[0].val,
                      direction=s_pointers.PointerDirection.Outbound)
        ])
예제 #13
0
 def reduce_NodeName_OptShape(self, *kids):
     self.val = qlast.Shape(expr=qlast.Path(steps=[
         qlast.ObjectRef(name=kids[0].val.name,
                         module=kids[0].val.module,
                         context=kids[0].context)
     ]),
                            elements=kids[1].val)
예제 #14
0
    def _visit_query(self, node):
        # populate input variables with defaults, where applicable
        if node.variable_definitions:
            self.visit(node.variable_definitions)

        # base Query needs to be configured specially
        base = self._context.gqlcore.get('Query')

        # special treatment of the selection_set, different from inner
        # recursion
        query = qlast.SelectQuery(
            result=qlast.Shape(
                expr=qlast.Path(
                    steps=[qlast.ObjectRef(name='Query',
                                           module='stdgraphql')]
                ),
                elements=[]
            ),
            limit=qlast.IntegerConstant(value='1')
        )

        self._context.fields.append({})
        self._context.path.append([Step(None, base)])
        query.result.elements = self.visit(node.selection_set)
        self._context.fields.pop()
        self._context.path.pop()

        return query
예제 #15
0
    def nullify_expr_field(self, schema, context, field, op):
        from edb.edgeql.compiler import astutils as qlastutils

        if field.name == 'expr':
            base = self.get_attribute_value('bases').first(schema)

            if base.is_object_type():
                base_name = base.get_name(schema)
                ql = qlast.SelectQuery(
                    result=qlast.Path(steps=[
                        qlast.ObjectRef(
                            name=base_name.name,
                            module=base_name.module,
                        ),
                    ], ),
                    where=qlast.BooleanConstant(value='false'),
                )
            else:
                ql = qlast.TypeCast(
                    expr=qlast.Set(),
                    type=qlastutils.type_to_ql_typeref(base, schema=schema),
                )

            op.new_value = s_expr.Expression.compiled(
                s_expr.Expression.from_ast(ql,
                                           schema=schema,
                                           modaliases=context.modaliases),
                schema=schema,
            )

            return True
        else:
            super().nullify_expr_field(schema, context, field, op)
예제 #16
0
파일: config.py 프로젝트: syyunn/edgedb
def compile_ConfigInsert(
        expr: qlast.ConfigInsert, *, ctx: context.ContextLevel) -> irast.Set:

    info = _validate_op(expr, ctx=ctx)

    if not expr.system:
        raise errors.UnsupportedFeatureError(
            f'CONFIGURE SESSION INSERT is not supported'
        )

    level = 'SYSTEM' if expr.system else 'SESSION'
    subject = ctx.env.get_track_schema_object(
        f'cfg::{expr.name.name}', default=None)
    if subject is None:
        raise errors.ConfigurationError(
            f'{expr.name.name!r} is not a valid configuration item',
            context=expr.context,
        )

    insert_stmt = qlast.InsertQuery(
        subject=qlast.Path(
            steps=[
                qlast.ObjectRef(
                    name=expr.name.name,
                    module='cfg',
                )
            ]
        ),
        shape=expr.shape,
    )

    for el in expr.shape:
        if isinstance(el.compexpr, qlast.InsertQuery):
            _inject_tname(el.compexpr, ctx=ctx)

    with ctx.newscope() as subctx:
        subctx.expr_exposed = True
        subctx.modaliases = ctx.modaliases.copy()
        subctx.modaliases[None] = 'cfg'
        subctx.special_computables_in_mutation_shape |= {'_tname'}
        insert_ir = dispatch.compile(insert_stmt, ctx=subctx)
        insert_ir_set = setgen.ensure_set(insert_ir, ctx=subctx)
        assert isinstance(insert_ir_set.expr, irast.InsertStmt)
        insert_subject = insert_ir_set.expr.subject

        _validate_config_object(insert_subject, level=level, ctx=subctx)

    return setgen.ensure_set(
        irast.ConfigInsert(
            name=info.param_name,
            cardinality=info.cardinality,
            system=expr.system,
            requires_restart=info.requires_restart,
            backend_setting=info.backend_setting,
            expr=insert_subject,
            context=expr.context,
        ),
        ctx=ctx,
    )
예제 #17
0
    def reduce_ShapePathPtr_DOT_PathStepName(self, *kids):
        from edb.schema import pointers as s_pointers

        self.val = qlast.Path(steps=[
            qlast.TypeIndirection(type=kids[0].val, ),
            qlast.Ptr(ptr=kids[2].val,
                      direction=s_pointers.PointerDirection.Outbound),
        ])
예제 #18
0
    def reduce_Expr_DOT_FCONST(self, *kids):
        # this is a valid link-like syntax for accessing unnamed tuples
        path = kids[0].val
        if not isinstance(path, qlast.Path):
            path = qlast.Path(steps=[path])

        path.steps.extend(self._float_to_path(kids[2], kids[1].context))
        self.val = path
예제 #19
0
    def visit_TypeRef(self, node):
        # Bare TypeRef only appears as rhs of IS [NOT] and is always
        # an object type reference.
        mtn = node.name_hint

        result = qlast.Path(
            steps=[qlast.ObjectRef(module=mtn.module, name=mtn.name)])

        return result
예제 #20
0
def graft(prefix: Optional[qlast.Path],
          new: qlast.Path,
          always_partial: bool = False) -> qlast.Path:
    if new.partial or always_partial:
        assert prefix is not None
        return qlast.Path(steps=prefix.steps + new.steps,
                          partial=prefix.partial)
    else:
        return new
예제 #21
0
def update_path(prefix: Optional[qlast.Path],
                query: Optional[qlast.Expr]) -> Optional[qlast.Path]:
    if query is None:
        return None
    elif isinstance(query, qlast.ReturningMixin):
        if query.result_alias is not None:
            return qlast.Path(steps=[qlast.ObjectRef(name=query.result_alias)])
        else:
            query = query.result

    while isinstance(query, qlast.Shape):
        query = query.expr

    if isinstance(query, qlast.Path):
        return graft(prefix, query)
    else:
        # XXX: synthesize a real prefix name?
        return qlast.Path(partial=True, steps=[])
예제 #22
0
 def reduce_AT_ShortNodeName(self, *kids):
     self.val = qlast.Path(
         steps=[
             qlast.Ptr(
                 ptr=kids[1].val,
                 type='property'
             )
         ]
     )
예제 #23
0
파일: tracer.py 프로젝트: stjordanis/edgedb
def trace_GroupingAtom(node: qlast.GroupingAtom, *,
                       ctx: TracerContext) -> None:
    if isinstance(node, qlast.ObjectRef):
        trace(qlast.Path(steps=[node]), ctx=ctx)
    elif isinstance(node, qlast.Path):
        trace(node, ctx=ctx)
    else:
        for el in node.elements:
            trace_GroupingAtom(el, ctx=ctx)
예제 #24
0
def compile_GlobalExpr(
        expr: qlast.GlobalExpr, *, ctx: context.ContextLevel) -> irast.Set:
    glob = ctx.env.get_track_schema_object(
        s_utils.ast_ref_to_name(expr.name), expr.name,
        modaliases=ctx.modaliases, type=s_globals.Global)
    assert isinstance(glob, s_globals.Global)

    if glob.is_computable(ctx.env.schema):
        obj_ref = s_utils.name_to_ast_ref(
            glob.get_target(ctx.env.schema).get_name(ctx.env.schema))
        return dispatch.compile(qlast.Path(steps=[obj_ref]), ctx=ctx)

    objctx = ctx.env.options.schema_object_context
    if objctx in (s_constr.Constraint, s_indexes.Index):
        typname = objctx.get_schema_class_displayname()
        raise errors.SchemaDefinitionError(
            f'global variables cannot be referenced from {typname}',
            context=expr.context)

    default = glob.get_default(ctx.env.schema)

    param_set: qlast.Expr | irast.Set
    present_set: qlast.Expr | irast.Set | None
    if ctx.env.options.func_params is None:
        param_set, present_set = setgen.get_global_param_sets(glob, ctx=ctx)
    else:
        param_set, present_set = setgen.get_func_global_param_sets(
            glob, ctx=ctx)

    if default and not present_set:
        # If we have a default value and the global is required,
        # then we can use the param being {} as a signal to use
        # the default.
        with ctx.new() as subctx:
            subctx.anchors = subctx.anchors.copy()
            main_param = subctx.maybe_create_anchor(param_set, 'glob')
            param_set = func.compile_operator(
                expr, op_name='std::??',
                qlargs=[main_param, default.qlast], ctx=subctx)
    elif default and present_set:
        # ... but if {} is a valid value for the global, we need to
        # stick in an extra parameter to indicate whether to use
        # the default.
        with ctx.new() as subctx:
            subctx.anchors = subctx.anchors.copy()
            main_param = subctx.maybe_create_anchor(param_set, 'glob')

            present_param = subctx.maybe_create_anchor(present_set, 'present')

            param_set = func.compile_operator(
                expr, op_name='std::IF',
                qlargs=[main_param, present_param, default.qlast], ctx=subctx)
    elif not isinstance(param_set, irast.Set):
        param_set = dispatch.compile(param_set, ctx=ctx)

    return param_set
예제 #25
0
    def visit_ObjectField(self, node):
        fname = node.name.value

        # handle boolean ops
        if fname == 'and':
            return self._visit_list_of_inputs(node.value, 'AND')
        elif fname == 'or':
            return self._visit_list_of_inputs(node.value, 'OR')
        elif fname == 'not':
            return qlast.UnaryOp(op='NOT', operand=self.visit(node.value))

        # handle various scalar ops
        op = gt.GQL_TO_OPS_MAP.get(fname)

        if op:
            value = self.visit(node.value)
            return qlast.BinOp(left=self._context.filter, op=op, right=value)

        # we're at the beginning of a scalar op
        _, target = self._get_parent_and_current_type()

        name = self.get_path_prefix()
        name.append(qlast.Ptr(ptr=qlast.ObjectRef(name=fname)))
        name = qlast.Path(steps=name)

        ftype = target.get_field_type(fname)
        typename = ftype.name
        if typename not in {'std::str', 'std::uuid'}:
            gql_type = gt.EDB_TO_GQL_SCALARS_MAP.get(typename)
            if gql_type == graphql.GraphQLString:
                # potentially need to cast the 'name' side into a
                # <str>, so as to be compatible with the 'value'
                name = qlast.TypeCast(
                    expr=name,
                    type=qlast.TypeName(maintype=qlast.ObjectRef(name='str')),
                )

        self._context.filter = name

        value = self.visit(node.value)
        # we need to cast a target string into <uuid> or enum
        if typename == 'std::uuid' and not isinstance(value.right,
                                                      qlast.TypeCast):
            value.right = qlast.TypeCast(
                expr=value.right,
                type=qlast.TypeName(maintype=qlast.ObjectRef(name='uuid')),
            )
        elif ftype.is_enum():
            value.right = qlast.TypeCast(
                expr=value.right,
                type=qlast.TypeName(maintype=qlast.ObjectRef(name=ftype.name)),
            )

        return value
예제 #26
0
    def reduce_PathStepName_OptTypeIntersection(self, *kids):
        from edb.schema import pointers as s_pointers

        steps = [
            qlast.Ptr(ptr=kids[0].val,
                      direction=s_pointers.PointerDirection.Outbound),
        ]

        if kids[1].val is not None:
            steps.append(kids[1].val)

        self.val = qlast.Path(steps=steps)
예제 #27
0
def make_free_object(els: Dict[str, qlast.Expr]) -> qlast.Shape:
    return qlast.Shape(
        expr=None,
        elements=[
            qlast.ShapeElement(
                expr=qlast.Path(
                    steps=[qlast.Ptr(ptr=qlast.ObjectRef(name=name))]),
                compexpr=expr
            )
            for name, expr in els.items()
        ],
    )
예제 #28
0
    def _apply_field_ast(
        self,
        schema: s_schema.Schema,
        context: sd.CommandContext,
        node: qlast.DDLOperation,
        op: sd.AlterObjectProperty,
    ) -> None:
        objtype = self.get_referrer_context(context)

        if op.property == 'target' and objtype:
            # Due to how SDL is processed the underlying AST may be an
            # AlterConcreteLink, which requires different handling.
            if isinstance(node, qlast.CreateConcreteLink):
                if not node.target:
                    expr = self.get_attribute_value('expr')
                    if expr is not None:
                        node.target = expr.qlast
                    else:
                        t = op.new_value
                        assert isinstance(t, (so.Object, so.ObjectShell))
                        node.target = utils.typeref_to_ast(schema, t)
            else:
                assert isinstance(op.new_value, (so.Object, so.ObjectShell))
                top_op = self.get_top_referrer_op(context)
                conv_expr: Optional[qlast.Expr]
                if (top_op is not None and
                    (isinstance(top_op, sd.CreateObject) or
                     (top_op.orig_cmd_type is not None
                      and issubclass(top_op.orig_cmd_type, sd.CreateObject)))):
                    # This op is part of CREATE TYPE, so avoid tripping up
                    # the DDL check on SET TYPE by generating an appropriate
                    # conversion expression: USING (.foo[IS Type]).
                    lname = sn.shortname_from_fullname(self.classname).name
                    conv_expr = qlast.Path(
                        partial=True,
                        steps=[
                            qlast.Ptr(ptr=qlast.ObjectRef(name=lname)),
                            qlast.TypeIntersection(type=utils.typeref_to_ast(
                                schema, op.new_value))
                        ],
                    )
                else:
                    conv_expr = None
                node.commands.append(
                    qlast.SetPointerType(
                        value=utils.typeref_to_ast(schema, op.new_value),
                        expr=conv_expr,
                    ))
        elif op.property == 'on_target_delete':
            node.commands.append(qlast.OnTargetDelete(cascade=op.new_value))
        else:
            super()._apply_field_ast(schema, context, node, op)
예제 #29
0
파일: spec.py 프로젝트: syyunn/edgedb
def generate_config_query(schema) -> str:
    cfg = schema.get('cfg::Config')

    ref = qlast.ObjectRef(name='Config', module='cfg')
    query = qlast.SelectQuery(
        result=qlast.Shape(
            expr=qlast.Path(steps=[ref]),
            elements=qlcompiler.get_config_type_shape(schema, cfg, path=[ref]),
        ),
        limit=qlast.IntegerConstant(value='1', ),
    )

    return qlcodegen.generate_source(query)
예제 #30
0
def get_param_anchors_for_callable(params, schema):
    anchors = {}
    aliases = []

    anchors['__defaults_mask__'] = irast.Parameter(
        name='__defaults_mask__',
        typeref=irtyputils.type_to_typeref(schema, schema.get('std::bytes')))

    pg_params = s_func.PgParams.from_params(schema, params)
    for pi, p in enumerate(pg_params.params):
        p_shortname = p.get_shortname(schema)
        anchors[p_shortname] = irast.Parameter(
            name=p_shortname,
            typeref=irtyputils.type_to_typeref(schema, p.get_type(schema)))

        if p.get_default(schema) is None:
            continue

        aliases.append(
            qlast.AliasedExpr(
                alias=p_shortname,
                expr=qlast.
                IfElse(condition=qlast.BinOp(left=qlast.FunctionCall(
                    func=('std', 'bytes_get_bit'),
                    args=[
                        qlast.Path(
                            steps=[qlast.ObjectRef(name='__defaults_mask__')]),
                        qlast.IntegerConstant(value=str(pi)),
                    ]),
                                             right=qlast.IntegerConstant(
                                                 value='0'),
                                             op='='),
                       if_expr=qlast.Path(
                           steps=[qlast.ObjectRef(name=p_shortname)]),
                       else_expr=qlast._Optional(
                           expr=p.get_ql_default(schema)))))

    return anchors, aliases