Пример #1
0
    def _parse_subject_constraints(self, subject, subjdecl):
        # Perform initial collection of constraints defined in subject context.
        # At this point all referenced constraints should be fully initialized.

        for constrdecl in subjdecl.constraints:
            attrs = {a.name.name: a.value for a in constrdecl.fields}
            assert 'subject' not in attrs  # TODO: Add proper validation

            constr_name = self._get_ref_name(constrdecl.name)
            if constrdecl.args:
                args = [
                    qlcodegen.generate_source(arg, pretty=False)
                    for arg in constrdecl.args
                ]
            else:
                args = []

            modaliases = {None: subject.get_name(self._schema).module}
            self._schema, c, _ = \
                s_constr.Constraint.create_concrete_constraint(
                    self._schema,
                    subject,
                    name=constr_name,
                    is_abstract=constrdecl.delegated,
                    sourcectx=constrdecl.context,
                    subjectexpr=constrdecl.subject,
                    args=args,
                    modaliases=modaliases,
                )

            self._schema = subject.add_constraint(self._schema, c)
Пример #2
0
    def _parse_field_setters(self, scls,
                             field_decls: typing.List[s_ast.Field]):
        fields = type(scls).get_fields()
        updates = {}

        for field_decl in field_decls:
            fieldname = field_decl.name.name

            attrfield = fields.get(fieldname)
            if attrfield is None or not attrfield.allow_ddl_set:
                raise errors.SchemaError(f'unexpected field {fieldname}',
                                         context=field_decl.context)

            if issubclass(attrfield.type, s_expr.ExpressionText):
                updates[fieldname] = qlcodegen.generate_source(
                    field_decl.value)

            else:
                updates[fieldname] = qlcompiler.evaluate_ast_to_python_val(
                    field_decl.value,
                    self._schema,
                    modaliases=self._mod_aliases)

        if updates:
            self._schema = scls.update(self._schema, updates)
Пример #3
0
 def edb_base_name(self):
     base = self.edb_base.get_name(self.edb_schema)
     return codegen.generate_source(
         qlast.ObjectRef(
             module=base.module,
             name=base.name,
         ))
Пример #4
0
    def _init_constraints(self, constraints):
        for constraint, decl in constraints.items():
            attrs = {a.name.name: a.value for a in decl.attributes}
            assert 'subject' not in attrs  # TODO: Add proper validation
            assert 'subjectexpr' not in attrs  # TODO: Add proper validation

            expr = attrs.pop('expr', None)
            if expr is not None:
                constraint.expr = s_expr.ExpressionText(
                    qlcodegen.generate_source(expr))

            subjexpr = decl.subject
            if subjexpr is not None:
                constraint.subjectexpr = s_expr.ExpressionText(
                    qlcodegen.generate_source(subjexpr))

            paramnames, paramdefaults, paramtypes, paramkinds, variadic = \
                s_func.parameters_from_ast(decl, self._mod_aliases,
                                           self._schema)

            for pname, pdefault, ptype in zip(paramnames, paramdefaults,
                                              paramtypes):
                if pname is not None:
                    raise s_err.SchemaDefinitionError(
                        'constraints do not support named parameters',
                        context=decl.context)

                if pdefault is not None:
                    raise s_err.SchemaDefinitionError(
                        'constraints do not support parameters '
                        'with defaults',
                        context=decl.context)

                if ptype is None:
                    raise s_err.SchemaDefinitionError('untyped parameter',
                                                      context=decl.context)

            constraint.paramtypes = paramtypes
            constraint.varparam = variadic
Пример #5
0
    def _init_constraints(self, constraints):
        for constraint, decl in constraints.items():
            attrs = {a.name.name: a.value for a in decl.fields}
            assert 'subject' not in attrs  # TODO: Add proper validation
            assert 'subjectexpr' not in attrs  # TODO: Add proper validation

            expr = attrs.pop('expr', None)
            if expr is not None:
                self._schema = constraint.set_field_value(
                    self._schema, 'expr',
                    s_expr.ExpressionText(qlcodegen.generate_source(expr)))

            subjexpr = decl.subject
            if subjexpr is not None:
                self._schema = constraint.set_field_value(
                    self._schema, 'subjectexpr',
                    s_expr.ExpressionText(qlcodegen.generate_source(subjexpr)))

            self._schema, params = s_func.FuncParameterList.from_ast(
                self._schema,
                decl,
                self._mod_aliases,
                func_fqname=constraint.get_name(self._schema))

            for param in params.objects(self._schema):
                if param.get_kind(self._schema) is ft.ParameterKind.NAMED_ONLY:
                    raise errors.InvalidConstraintDefinitionError(
                        'named only parameters are not allowed '
                        'in this context',
                        context=decl.context)

                if param.get_default(self._schema) is not None:
                    raise errors.InvalidConstraintDefinitionError(
                        'constraints do not support parameters '
                        'with defaults',
                        context=decl.context)

            self._schema = constraint.set_field_value(self._schema, 'params',
                                                      params)
Пример #6
0
def rewrite_refs(expr, callback):
    """Rewrite class references in EdgeQL expression."""

    tree = qlparser.parse_fragment(expr)

    def _cb(node):
        if isinstance(node, qlast.ObjectRef):
            name = sn.Name(name=node.name, module=node.module)
            upd = callback(name)
            if name != upd:
                node.name = upd.name
                node.module = upd.module

    ast.find_children(tree, _cb)

    return qlcodegen.generate_source(tree, pretty=False)
Пример #7
0
    def from_ast(cls, schema, modaliases, num: int,
                 astnode) -> 'ParameterDesc':
        paramd = None
        if astnode.default is not None:
            paramd = codegen.generate_source(astnode.default)

        paramt = utils.resolve_typeref(
            utils.ast_to_typeref(astnode.type,
                                 modaliases=modaliases,
                                 schema=schema), schema)

        if astnode.kind is ft.ParameterKind.VARIADIC:
            paramt = s_types.Array.from_subtypes(schema, (paramt, ))

        return cls(num=num,
                   name=astnode.name,
                   type=paramt,
                   typemod=astnode.typemod,
                   kind=astnode.kind,
                   default=paramd)
Пример #8
0
def parameters_from_ast(astnode, modaliases, schema):
    paramdefaults = []
    paramnames = []
    paramtypes = []
    paramkinds = []
    variadic = None
    for argi, arg in enumerate(astnode.args):
        paramnames.append(arg.name)
        paramkinds.append(arg.qualifier)

        default = None
        if arg.default is not None:
            default = codegen.generate_source(arg.default)
        paramdefaults.append(default)

        paramtypes.append(utils.ast_to_typeref(
            arg.type, modaliases=modaliases, schema=schema))

        if arg.qualifier == qlast.SetQualifier.VARIADIC:
            variadic = argi

    return paramnames, paramdefaults, paramtypes, paramkinds, variadic
Пример #9
0
    def _cmd_tree_from_ast(cls, astnode, context, schema):
        cmd = super()._cmd_tree_from_ast(astnode, context, schema)

        modaliases = context.modaliases

        paramnames, paramdefaults, paramtypes, paramkinds, variadic = \
            parameters_from_ast(astnode, modaliases, schema)

        if variadic is not None:
            cmd.add(
                sd.AlterObjectProperty(property='varparam',
                                       new_value=variadic))

        cmd.add(
            sd.AlterObjectProperty(property='paramnames',
                                   new_value=paramnames))

        cmd.add(
            sd.AlterObjectProperty(property='paramtypes',
                                   new_value=paramtypes))

        cmd.add(
            sd.AlterObjectProperty(property='paramkinds',
                                   new_value=paramkinds))

        cmd.add(
            sd.AlterObjectProperty(property='paramdefaults',
                                   new_value=paramdefaults))

        cmd.add(
            sd.AlterObjectProperty(property='returntype',
                                   new_value=utils.ast_to_typeref(
                                       astnode.returning,
                                       modaliases=modaliases,
                                       schema=schema)))

        cmd.add(
            sd.AlterObjectProperty(property='aggregate',
                                   new_value=astnode.aggregate))

        cmd.add(
            sd.AlterObjectProperty(property='set_returning',
                                   new_value=astnode.set_returning))

        if astnode.initial_value is not None:
            iv = codegen.generate_source(astnode.initial_value)
            cmd.add(
                sd.AlterObjectProperty(property='initial_value', new_value=iv))

        if astnode.code is not None:
            cmd.add(
                sd.AlterObjectProperty(property='language',
                                       new_value=astnode.code.language))
            if astnode.code.from_name is not None:
                cmd.add(
                    sd.AlterObjectProperty(property='from_function',
                                           new_value=astnode.code.from_name))
            else:
                cmd.add(
                    sd.AlterObjectProperty(property='code',
                                           new_value=astnode.code.code))

        return cmd
Пример #10
0
    def _parse_subject_constraints(self, subject, subjdecl):
        # Perform initial collection of constraints defined in subject context.
        # At this point all referenced constraints should be fully initialized.

        constr = {}

        for constrdecl in subjdecl.constraints:
            attrs = {a.name.name: a.value for a in constrdecl.attributes}
            assert 'subject' not in attrs  # TODO: Add proper validation

            constr_name = self._get_ref_name(constrdecl.name)
            constr_base = self._schema.get(constr_name,
                                           type=s_constr.Constraint,
                                           module_aliases=self._mod_aliases)

            constraint = constr_base.derive(self._schema, subject)
            constraint.is_abstract = constrdecl.delegated
            constraint.acquire_ancestor_inheritance(self._schema)
            constraint.sourcectx = constrdecl.context

            if constrdecl.args:
                args = [
                    edgeql_codegen.generate_source(arg, pretty=False)
                    for arg in constrdecl.args
                ]
            else:
                args = []

            subjectexpr = constrdecl.subject
            if subjectexpr is not None:
                constraint.set_attribute(
                    'subjectexpr',
                    s_constr.Constraint.normalize_constraint_expr(
                        self._schema, {},
                        subjectexpr,
                        subject=subject,
                        constraint=constraint),
                    source_context=constrdecl.subject.context,
                )

            s_constr.Constraint.process_specialized_constraint(
                self._schema, constraint, args)

            # There can be only one specialized constraint per constraint
            # class per subject. At this point all placeholders have been
            # folded, so it is possible to merge the constraints consistently
            # by merging their final exprs.
            #
            try:
                prev = constr[constraint.bases[0].name]
            except KeyError:
                constr[constraint.bases[0].name] = constraint
            else:
                constraint.merge(prev, schema=self._schema)
                constraint.merge_localexprs(prev, schema=self._schema)
                constr[constraint.bases[0].name] = constraint

        for c in constr.values():
            # Note that we don't do finalization for the constraint
            # here, since it's possible that it will be further used
            # in a merge of it's subject.
            #
            self._schema.add(c)
            subject.add_constraint(c)
Пример #11
0
    def _parse_ptr_default(self, expr, source, ptr):
        """Set the default value for a pointer."""
        if not isinstance(expr, edgeql.ast.SelectQuery):
            expr = edgeql.ast.Constant(value=self._get_literal_value(expr))

        ptr.default = s_expr.ExpressionText(qlcodegen.generate_source(expr))