edgedb: Add `module` block to SDL

The current version of SDL and migrations does not allow expressing the migration of interdependent modules because a single SDL blob is only supposed to reference one module. The solution to this is to force SDL to express the entire user-schema in the context of migration. This means that a single SDL block must denote unambiguously which modules the various entities belong to. There are two mechanisms proposed for that:

  1. Fully-qualified names for all entities (except ones belonging to std, since that’s always built-in in all contexts).
  2. A special module <name> { ... } block. All inner SDL inside this block is understood to have the default module <name>. It is possible to have multiple module blocks with the same name in a single SDL document.

The total list of modules in the schema is inferred from module block names and from fully-qualified names.

Example of SDL using module blocks:

module default {
   # the default module here is "default"
   type Foo {
      # the module "std" is also part of the default name 
      # resolution as usual
      property name -> str;
      link bar -> other_mod::Bar;
   }
}

module other_mod {
   # the default module here is "other_mod"
   type Bar {
      link bar -> Bar;
      link foo -> default::Foo;
   }
}

And the same schema expressed using only fully-qualified names SDL:

# only the "std" module can be omitted here, all other 
# names have to be fully-qualified, even "defaut"
type default::Foo {
   property name -> str;
   link bar -> other_mod::Bar;
}

type other_mod::Bar {
   link bar -> other_mod::Bar;
   link foo -> default::Foo;
}

The following schemas are also equivalent:

# Multiple module blocks with the same name
module default {
   type Foo;
}

module other_mod {
   type Bar;
}

module default {
   type Foo2;
}
# Each module block has a unique name
module default {
   type Foo;
   type Foo2;
}

module other_mod {
   type Bar;
}
# Mix of fully-qualified names and module blocks
type default::Foo;

module other_mod {
   type Bar;
}

module default {
   type Foo2;
}

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Comments: 19 (19 by maintainers)

Commits related to this issue

Most upvoted comments

The options 1 and 2 are mutually exclusive, meaning:

  • A fully qualified name (so a name of the form <module>::<shortname>) can only be used in a declaration that is not nested in any module block. It is also a requirement to use fully-qualified name in this case.
  • It is illegal to use fully-qualified name in a declaration inside a module block, only short names are allowed.

This is legal:

type default::User;
module other {
   type User;
}

This is not legal:

# this name is not fully-qualified
type User {
}
module other {
  type User { }
}