Giter Club home page Giter Club logo

edgedb / edgedb Goto Github PK

View Code? Open in Web Editor NEW
12.3K 102.0 380.0 58.17 MB

A graph-relational database with declarative schema, built-in migration system, and a next-generation query language

Home Page: https://edgedb.com

License: Apache License 2.0

Python 89.17% Makefile 0.01% JavaScript 0.19% Rust 2.30% Cython 3.66% CSS 0.06% EdgeQL 4.61%
database object-relational graphql edgedb high-performance edgeql rdbms relational-database graph-relational

edgedb's Introduction

EdgeDB

Stars license discord

Quickstart   •   Website   •   Docs   •   Playground   •   Blog   •   Discord   •   Twitter



What is EdgeDB?

EdgeDB is a new kind of database
that takes the best parts of
relational databases, graph
databases, and ORMs. We call it
a graph-relational database.



🧩 Types, not tables 🧩


Schema is the foundation of your application. It should be something you can read, write, and understand.

Forget foreign keys; tabular data modeling is a relic of an older age, and it isn't compatible with modern languages. Instead, EdgeDB thinks about schema the same way you do: as object types containing properties connected by links.

type Person {
  required name: str;
}

type Movie {
  required title: str;
  multi actors: Person;
}

This example is intentionally simple, but EdgeDB supports everything you'd expect from your database: a strict type system, indexes, constraints, computed properties, stored procedures...the list goes on. Plus it gives you some shiny new features too: link properties, schema mixins, and best-in-class JSON support. Read the schema docs for details.


🌳 Objects, not rows 🌳


EdgeDB's super-powered query language EdgeQL is designed as a ground-up redesign of SQL. EdgeQL queries produce rich, structured objects, not flat lists of rows. Deeply fetching related objects is painless...bye, bye, JOINs.

select Movie {
  title,
  actors: {
    name
  }
}
filter .title = "The Matrix"

EdgeQL queries are also composable; you can use one EdgeQL query as an expression inside another. This property makes things like subqueries and nested mutations a breeze.

insert Movie {
  title := "The Matrix Resurrections",
  actors := (
    select Person
    filter .name in {
      'Keanu Reeves',
      'Carrie-Anne Moss',
      'Laurence Fishburne'
    }
  )
}

There's a lot more to EdgeQL: a comprehensive standard library, computed properties, polymorphic queries, with blocks, transactions, and much more. Read the EdgeQL docs for the full picture.


🦋 More than a mapper 🦋


While EdgeDB solves the same problems as ORM libraries, it's so much more. It's a full-fledged database with a powerful and elegant query language, a migrations system, a suite of client libraries in different languages, a command line tool, and—coming soon—a cloud hosting platform. The goal is to rethink every aspect of how developers model, migrate, manage, and query their database.

Here's a taste-test of EdgeDB's next-level developer experience: you can install our CLI, spin up an instance, and open an interactive EdgeQL shell with just three commands.

$ curl --proto '=https' --tlsv1.2 -sSf https://sh.edgedb.com | sh
$ edgedb project init
$ edgedb
edgedb> select "Hello world!"

Windows users: use this Powershell command to install the CLI.

PS> iwr https://ps1.edgedb.com -useb | iex

Get started

To start learning about EdgeDB, check out the following resources:

  • The quickstart. If you're just starting out, the 10-minute quickstart guide is the fastest way to get up and running.
  • EdgeDB Cloud 🌤️. The best most effortless way to host your EdgeDB database in the cloud.
  • The interactive tutorial. For a structured deep-dive into the EdgeQL query language, try the web-based tutorial— no need to install anything.
  • The e-book. For the most comprehensive walkthrough of EdgeDB concepts, check out our illustrated e-book Easy EdgeDB. It's designed to walk a total beginner through EdgeDB in its entirety, from the basics through advanced concepts.
  • The docs. Jump straight into the docs for schema modeling or EdgeQL!

Contributing

PRs are always welcome! To get started, follow this guide to build EdgeDB from source on your local machine.

File an issue 👉
Start a Discussion 👉
Join the discord 👉


License

The code in this repository is developed and distributed under the Apache 2.0 license. See LICENSE for details.

edgedb's People

Contributors

1st1 avatar aljazerzen avatar ambv avatar beerose avatar colinhacks avatar dhghomon avatar diksipav avatar dnwpark avatar efaust avatar elliotwaite avatar elprans avatar fantix avatar fmoor avatar fogapod avatar i0bs avatar jaclarke avatar miroslavpetrik avatar msullivan avatar nsidnev avatar quinchs avatar raddevon avatar rednafi avatar robertblumen avatar robertoprevato avatar schettino72 avatar scotttrinh avatar tailhook avatar vpetrovykh avatar zackelan avatar zchenb avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

edgedb's Issues

Fix introspection of constraint arguments

Currently, schema::Constraint.args is declared as map<std::str, std::str>, yet Constraint.args field is defined as ExpressionText (and is stored as such). It should be possible to introspect args separately. The best approach, IMO, is to create schema::Argument as such:

CREATE CONCEPT schema::Argument {
    CREATE REQUIRED LINK schema::param TO schema::Parameter;
    CREATE REQUIRED LINK schema::val TO std::str;
};

error: "resolve_type_name: unknown type: UUID"

Steps to reproduce:

  1. Create a new cluster
  2. Create a new DB test1 and switch to it
  3. Create a new module test1: CREATE MODULE test1;
  4. Create an atom:
    CREATE ATOM test1::a1 EXTENDING std::str {
        CREATE CONSTRAINT std::enum(['a', 'b']);
    };
    
  5. DROP ATOM test1::a1;

This will lead to this exception:

1. asyncpg.exceptions.RaiseError: resolve_type_name: unknown type: "288c3ba6-6741-11e7-8575-ab3c1ce9c654"

---------------------------------------- Traceback -----------------------------------------

    /Users/yury/dev/edge/edgedb/edgedb/server/protocol.py, line 217, in _on_edge_connect
        > self.backend = fut.result()
    /Users/yury/dev/edge/edgedb/edgedb/server/pgsql/backend.py, line 1571, in open_database
        > await bk.getschema()
    /Users/yury/dev/edge/edgedb/edgedb/server/pgsql/backend.py, line 427, in getschema
        > self.schema = await self.readschema()
    /Users/yury/dev/edge/edgedb/edgedb/server/pgsql/backend.py, line 410, in readschema
        > await self.read_constraints(schema)
    /Users/yury/dev/edge/edgedb/edgedb/server/pgsql/backend.py, line 791, in read_constraints
        > self.connection)
    /Users/yury/dev/edge/edgedb/edgedb/server/pgsql/datasources/schema/constraints.py, line 42, in fetch
        > """, name)
    /Users/yury/dev/venvs/edgedb/lib/python3.6/site-packages/asyncpg/connection.py, line 314, in fetch
        > return await self._execute(query, args, 0, timeout)
    /Users/yury/dev/venvs/edgedb/lib/python3.6/site-packages/asyncpg/connection.py, line 997, in _execute
        > return await self._do_execute(query, executor, timeout)
    /Users/yury/dev/venvs/edgedb/lib/python3.6/site-packages/asyncpg/connection.py, line 1018, in _do_execute
        > result = await executor(stmt, None)
    asyncpg/protocol/protocol.pyx, line 189, in bind_execute (asyncpg/protocol/protocol.c:60713)


asyncpg.exceptions.RaiseError: resolve_type_name: unknown type: "288c3ba6-6741-11e7-8575-ab3c1ce9c654"

Add the equivalent of "CALLED ON NULL INPUT"/"RETURNS NULL ON NULL INPUT" for EdgeQL functions.

PostgreSQL functions have the CALLED ON NULL INPUT and RETURNS NULL ON NULL INPUT attributes that determine whether the function is called when one of the arguments is NULL.

We should have the ability to specify the same attribute on EdgeQL functions. Arguably, the RETURNS NULL ON NULL INPUT should be the default, as that's the assumed behaviour of most EdgeDB functions.

PostgreSQL has the STRICT shorthand for RETURNS NULL..., but no short counterpart. I feel like the standard blah ON NULL INPUT is too verbose.

Implement `self` and `subject` as reserved keywords.

We need to parse self and subject as reserved keywords, as these have special meaning in schema expressions in defaults, constraints, indexes etc.

We need to generate a separate AST node for these to reliably distinguish self from its quoted counterpart.

Add function-like signatures to constraints

While working with @vpetrovykh on #8, we realized that $param in constraints isn't strictly defined, which causes problems when you try to use function calls in your constraints' exprs (in fact, everything seems to be working by accident right now).

So when we changed

CREATE CONSTRAINT std::enum INHERITING std::constraint {
    SET errmessage := '{subject} must be one of: {param}.';
    SET expr := (subject IN $param);
};

to

CREATE CONSTRAINT std::enum INHERITING std::constraint {
    SET errmessage := '{subject} must be one of: {param}.';
    SET expr := (array_contains($param, subject));
};

the compiler could no longer compile the expr expression, as the type of $param is unknown.

We propose to add function-like signatures to constraints, as in:

CREATE CONSTRAINT std::enum($param: array<any>) INHERITING std::constraint {
    SET errmessage := '{subject} must be one of: {param}.';
    SET expr := (array_contains($param, subject));
};

which would at least make inference possible for parameters of constraints.

There's still an open issue of how to determine the type of the subject link though.

Thoughts?

Fix compilation of shapes with polymorphic links

An example query which doesn't work right now:

SELECT schema::Constraint {
               name,
                params: {
                    num,
                    type: {
                        name,
                        schema::Array.element_type
                    }
                }
            } FILTER .name LIKE '%enum%';

If, however, we specialize the shape itself, everything is working:

SELECT schema::Constraint {
               name,
                params: {
                    num,
                    type: schema::Array {
                        name,
                        element_type
                    }
                }
            } FILTER .name LIKE '%enum%';

Strings in EdgeQL and eschema.

Currently EdgeQL strings are very simple and don't even have line continuation. The original rationale was that explicit string concatenation solves the problem without inventing new syntax. It also allows us to treat $$-strings as essentially raw strings, where everything is exactly as written, including -escapes.

Line continuation is somewhat desirable for the cases when logically there should be no newlines, but the amount of text is large (e.g. descriptions).

Schema aggravates this problem by being white-space sensitive. Currently schema parser will automagically dedent raw strings and handle line continuation symbol before handing the strings off to the EdgeQL parser. The case for needing nice line continuation in the Schema is stronger.

concept Foo:
    description :=
        "This is all one" +
        "string without newlines."

v.s. something like

concept Foo:
    description :=
        "This is all one \
        string without newlines."
        # dedent will get rid of the whitespace before the word "string"

There's a :> operator in the schema that attempts to streamline strings, but because it lacks a terminal symbol it is difficult to highlight the string after it with regular expressions. This operator needs to be removed.

An option to consider is adding additional string types for $$-string. From lower ascii set only alphabetic characters, digits and "_" are allowed in the $foo_1$ marker. This can be used to add a special separator for different string types. We seem to need strings that automatically dedent themselves, so examples of syntax for that could be:

  • $d:$ ...content... $$
  • $d:foo_1$ ...content... $foo_1$
  • $:<$ ...content... $$
  • $foo_1:<$ ...content... $foo_1$

TODO summary:

  • remove :>
  • remove very exceptional line continuation rule from eschema
  • add more string literal types to EdgeQL
  • add line continuation to some/all string literals in EdgeQL

Escape sequences in string literals

Currently EdgeQL doesn't recognize any escape sequences in string literals (like plain vanilla strings in SQL). This may be an issue since we like to position Edge as a modern DB.

It's worthwhile comparing how different popular modern languages handle character escaping.

Compare to:

  • JS
  • Python 2 and 3
  • Ruby
  • Java
  • C++
  • GO

FOR and GROUP syntax rework

GROUP and FOR constructs seem to share a lot of similarities. Additionally, GROUP has certain features w.r.t. scoping that are a bit confusing as is. The proposal is to merge FOR and GROUP syntax into one general top-level statement and stop treating FOR as a clause of other statements.

The proposed syntax is as follows:

  1. Simple iterator
FOR (X IN expr1)
expr2
FILTER ...
ORDER BY ...
OFFSET ... LIMIT ...;
  1. Group iterator
FOR (
    X, Y1, ..., Yn IN 
    GROUP Foo BY
        Foo.a1,
        Foo.a2,
        ...
        Foo.an
)
expr2
FILTER ...
ORDER BY ...
OFFSET ... LIMIT ...;

The fundamental idea is that this allows to clearly disambiguate when expr2 is referring to the grouped subset or to one of the grouping parameters vs. the general sets. This syntax also make more clear that clauses such as FILTER and LIMIT are applied to the result of FOR.

Add tests for eschema attribute declaration

We also need a new syntax for them.

Currently (?? -- we don't have any tests for this) in eschema:

attribute foobar:
    target := std::str

Currently in EdgeQL:

CREATE ATTRIBUTE std::pattern std::str;

What we (probably want) in eschema:

attribute foobar std::str

Consolidate documentation schema

Currently the documentation uses several disparate schemas for examples. This is sub-optimal as it makes it harder to follow. We need to consolidate all the documentation examples into a single schema (potentially with 2 modules).

The schema theme could be "GitHub" as opposed to a more generic and flavorless "issue tracker".

Drop `.1` and `1.` as valid float literals

Float literals with omitted leading or trailing zero are slightly error prone (they look nearly identical to an int, but are actually of a different type, which may matter in a few cases).

Additionally, the grammar for parsing tuple indexes is simplified if floats always have digits around the ..

Remove all text search functionality

Generic full text search capability is too complex for the current stage of implementation. There is no value in providing a half-working stub.

Parse all eschema type names with edgeql parser

function foo(..) -> EDGEQL
link foo:name to EDGEQL

Ideally, we want to replace eschema.ast.ObjectName with edgeql.ast.TypeName or edgeql.ast.ClassRef. The idea is to use the same types as a corresponding EdgeQL syntax uses.

Implement new syntax for defining constraint's expr

CREATE CONSTRAINT std::enum(array<std::any>) {
    SET errmessage := '{subject} must be one of: {$0}.';
    SET expr := array_contains($0, subject);
};

should become

CREATE CONSTRAINT std::enum(array<std::any>) {
    SET errmessage := '{subject} must be one of: {$0}.';
    FROM edgeql $$
        SELECT array_contains($0, subject);
    $$;
};

improve eschema documentation

Missing documentation and (mostly) syntax tests for:

  • attributes
  • final concepts/atoms
  • abstract and delegated constraints
  • document ON for constraints and indexes (in particular that it requires parens)

General documentation update

Here's a list of commits that require some amount of documentation updates:

  • lexical.rst has a bunch of empty sections.

  • graphql: Implement reflection of ObjectTypes. (commit 0d8d5a7)

    ObjectTypes get reflected as type INTERFACE into GraphQL. Additionally,
    non-abstract ObjectTypes get reflected as type OBJECT, but with the
    "Type" appended at the end of their name.

    This allows the return type of fields/functions to be specified in terms
    of INTERFACE types and the actual object __typename to reflect the
    OBJECT type of the specific instance.

  • Allow aliasing links in shapes (commit ec91dce)

    When a computable expression contains a path, use the trailing
    link or property as a base for the computable in shape.
    For example, in Spam { alias := Foo.bar }, Spam.alias
    is derived from Foo.bar inheriting its properties.

  • edgeql: Add re_replace function to std. (commit 9c20ef1)

  • graphql: Use a filter argument for more flexible filtering. (commit aa1c201)

    Rather than taking arguments corresponding to the individual fields, use
    a single filter argument to specify the filtering conditions. This is
    more generic and easier to add more functionality to in the future.

  • graphql: Add orderBy argument. (commit 20f59c4)

    All fields that return a list of objects can now be ordered by one or
    more of the scalar fields on that object.

  • Disallow overriding the 'id' property (commit e502f4c)

    The value of the id property of an object coresponds to object's identity
    (and value). It is both unsafe and unintuitive to allow arbitrary
    re-definition of id.

    SELECT Foo ORDER BY Foo;
    SELECT Foo ORDER BY Foo.id;
    

    The above queries are equivalent by default, but would stop being equivalent
    if id was re-defined in a view.

    Fixes: #214

  • graphql: Add slicing support. (commit f019077)

    Add after, first, before and last arguments to anything that
    returns an object list. The arguemnts have the same semantics as in
    Relay Connections regardless of whether the field returns a Connection
    or a plain List.

  • edgeql: Update the type specification syntax. (commit 03b3d52)

    Introduce type expressions - syntactical constructs denoting types and
    type composition.

    Operator | produces a union type that is a duck type having the
    intersection of all of the links and properties of the component types.
    Semantically any object that is an instance of at least one of the
    component types is also an instance of the union type.

    Operator & produces an intersection type that is a duck type having
    the union of all of the links and properties of the component types.
    Semantically only an object that is an instance of all of the component
    types is also an instance of the intersection type.

    Syntactically type expressions are general and can be used anywhere
    where a type can be used. There may be some exceptions, notably only
    base types can be used in extending specification.

  • edgeql: Add REQUIRED expr syntax. (commit 1bf7fd9)

    Issue #217.

  • edgeql: Add INDEX syntax. (commit 1ae3b8b)

    Issue #148.

  • Add schema::Database type to allow listing cluster databases (commit a6dbe9d)

  • edgeql: Add ON TARGET DELETE... syntax to concrete links. (commit 69feb44)

  • schema: Add on target delete ... syntax to the schema. (commit 9306fff)

  • edgeql: Disable GROUP statements util they are implemented. (commit d9ad223)

  • edgeql: Add array_get. (commit 2b309f9)

    Function array_get returns an array element or an empty set if the
    index is out of bounds.

  • Implement new syntax for function parameters (commit 78b97c3)

    Paremeter kind and parameter type are now different things.
    The following parameter kinds are supported right now:

    • regular positional parameters
    • VARIADIC
    • NAMED ONLY

    The syntax for declaring functions & constraints not longer
    allows to specify unnamed parameters -- names are required.

    Old syntax:

      CREATE FUNCTION foo(int64)
      CREATE FUNCTION foo(VARIADIC SET OF str)
      CREATE FUNCTION foo($a: VARIADIC SET OF str)
    

    New syntax:

      CREATE FUNCTION foo($p: int64)
      CREATE FUNCTION foo(VARIADIC $name: SET OF str)
      CREATE FUNCTION foo(VARIADIC $a: SET OF str)
    

    Syntax for declaring named-only parameters (not yet supported by the
    compiler):

      CREATE FUNCTION foo($pos1: int64, $pos2: str,
                          NAMED ONLY $n1: str, NAMED ONLY $n2: int64)
    

    Named-only parameters will only be supported by functions (not
    constraints).

  • edgeql: Add JSON funcitonality. (commit 6d3352c)

    New JSON functions:

    • str_to_json
    • json_to_str
    • json_typeof
    • json_array_unpack
    • json_object_unpack
    • json_get

    The [] indexing operator is also available for JSON. This operator is
    strict and will raise an exception if it is used with a non-existent
    index value (this is true for JSON, strings and arrays).

    There's a new array_get function that doesn't perform the boundary
    check on the index value and returns an empty set if there is no such
    index.

  • Add support for casting objects and tuples to std::json (commit 8b7a72e)

    <json>Object now always returns a std::json value containing
    the output representation of the object. That is, the result is
    the same as the output of SELECT Object in JSON mode, including
    the type shape.

    Now, casting a non-named tuple to std::json returns a JSON array,
    and casting a named tuple to std::json returns a JSON object.

    Casting non-scalar JSON values to scalars is now an error, as well as
    casting a non-matching JSON scalar value.

    Issue: #251.

  • Prohibit VARIADIC parameters from having default values (commit 952be2f)

  • Implement named and variadic arguments; fix type system. (commit 57a24bf)

    1. Now we support named arguments and variadic parameters:

      SELECT foo(1, 2, 3, $arg := 'val')

    2. Type system was fixed to correctly handle implicit casts for
      ints and floats.

  • Add support for on target delete clause for links (commit ef120bd)

    The new on target delete clause of concrete links is a mechanism
    to specify what happens when a target object of a link instance
    is deleted.

    Currently implemented modes are:

    • RESTRICT -- produce an error indicating that deletion cannot be
      done due to an existing link. This is the default.
    • DEFERRED RESTRICT -- same as the above, but the check is postponed
      until the end of the current transaction, if there is no transaction,
      equivalent to RESTRICT.
    • SET EMPTY -- remove the link, can only be used with links that are
      not required.
    • DELETE SOURCE -- remove the link and the source of the link
      (cascaded deletion).
  • Update function declaration and call syntax (commit 6377f93)

    No longer use '$' as a prefix for parameter names in function
    signatures and call expressions. This is to declutter the syntax
    in expressions like the following:

      func($foo, $default := $something)
    

    which now becomes

      func($foo, default:=$something)
    

    It's now immediately clear what refers to a variable and what sets a
    value for a named argument.

  • edgeql: Alter the precedence rules. (commit c9a3164)

    Move shapes {} to a higher precedence, same group as [].

    Move DETACHED in between :: and . in precedence.

    Update existing tests and add more tests on interactions between
    precedence, shapes, scopes, and DETACHED.

  • Add new b'bytes' literal (commit 7cecc9b)

    Can contain (lexical structure):

    • any printable ascii character
    • \xXX hex escapes
    • ', ", \
    • \n, \t, \r
    • new lines

    Requires a 'b' prefix before quotes, e.g.:

      SELECT b'bytes';
    

    Supports slicing and indexing:

      db> SELECT b'bytes'[1]
      b'y'
    
      db> SELECT b'bytes'[0:2]
      b'by'
    
  • Enforce lexical structure in string literals; support escape seqs (commit 094fc18)

    Allowed escape codes in string literals:

    • \n, \t, \r
    • \, ', "
    • \xXX, \uXXXX, \UXXXXXXXX

    Otherwise string literals allow any unicode characters and new lines.

  • Add support for raw string literals; tweak lexer/ast. (commit 399cb02)

    1. Add raw strings.
    • $$ ... $$ strings are now raw strings.

    • New syntax: r'...' and r"..." -- raw string literals.

    Raw strings do not process any escapes, meaning that \ symbol
    acts just as any other one.

    1. Tweak string literals.

    Regular strings no longer accept \xhh codes over 0x7F. This is
    modeled after Rust strings [1], quoting:

    "Higher values are not permitted because it is ambiguous whether
    they mean Unicode code points or byte values."

    1. New AST nodes.

    EdgeQL and IR implementations got two new nodes: StringConstant and
    RawStringConstant. SQL has also a new node: EscapedStringConstant
    (compiles to an E'...' string).

    [1] https://doc.rust-lang.org/reference/tokens.html#character-escapes

  • schema: Add support for spaces + tabs indents. (commit af76bc2)

    Indentation must be consistent, so if a mix of tabs and spaces is used,
    tabs must come first and shallow indentation must be an exact prefix of
    deeper indentation.

    It is illegal to use a tab after a space in indentation.

    It is illegal to use a line continuation immediately after indentation.
    Some other content must appear first on that line.

    Whitespace is still ignored in parentheses or in the middle of a line
    even if it is extended via line continuation.

  • Implement support for polymorphic functions (commit a8424aa)

  • Update re_* functions to have "pattern" as a first parameter (commit c69770b)

    Closes #269.

  • Make regular division return floats and add a floor division operator (commit d0b572e)

    In another break with tradition, / now always performs a true division:
    even if the operands are integers, the result is a floating point
    approximation of the division result. The new // operator allows
    pefforming floor division explicitly.

    In this change we largely follow the motivation of Python's PEP 238.
    Classic behavior of integer division makes it hard to write polymorphic
    functions that work with arbitrary numeric types, especially if one
    considers numbers beyond the real plane, as blind casting of one of the
    operands may not work as expected.

  • Allow indexing named tuples by position; fix named tuples serialization (commit 3e0832c)

    Named tuples can now be indexed by position. The below two queries are
    equivalent:

      db> SELECT (a:=1).a;
      db> SELECT (a:=1).0;
    

    Named tuples will now be correctly serialized to JSON in more cases,
    for example:

      db> SELECT [(a:=1)][0];
      {"a": 1}
    

    Serialization of nested named tuples is still broken in some cases
    though:

      db> SELECT [(a:=(x:=1))][0];
      {"a": {"f1": 1}}
    
  • Rename "any" to "anytype" (commit ac30a5f)

    We want to add a "std::any()" function and it seems that renaming
    "any" to "anytype" is a better option than specialcasing any()
    production in the grammar. Also "anytype" plays nice with "anyscalar"
    and "anyint".

  • Rework the way relationship cardinality constraints are expressed (commit f77fe8c)

    We currently represent relationship cardinality as the cardinality
    attribute in concrete link and property definitions. The accepted
    values are '11' (one-to-one), '1*' (one-to-many), '*1' (may-to-one),
    and '**' (many-to-many). While this is accepted parlour, the
    interpretation of the constraints, together with the separate required
    qualifier produces a fair amount of cognitive load.

    In reality, the current monolithic relationship cardinality actually
    represents two distinct properties: the cardinality of the target set
    when traversing a pointer from a given source (the second '1' or ''),
    and the exclusivity constraint on the target (the first '1' or '
    ').
    The first property needs to be specified far more often than the second,
    so it makes sense to separate them.

    Now, a concrete link or property declaration can include the new target
    set cardinality qualifier in the form of the new single and multi
    keywords. For example:

      type User:
          link friends -> User:
              cardinality: '**'
    

    becomes:

      type User:
          multi link friends -> User
    

    The single qualifier is the default, but can still be specified:

      type Issue:
          single link status -> Status
    

    The required qualifier can be combined with the single/multi
    qualifier to form a precise target set cardinality requirement:
    single means zero-or-one, required single means exactly one,
    multi means zero-or-more, required multi means one-or-more.

    The second relationship cardinality property is target exclusivity, i.e.
    how many sources can relate to a given target, is now represented by the
    exclusive constraint, which is the current unique constraint, but with
    a new, more appropriate name. It is more natural to say that a given
    relationship is exclusive, rather than unique. For example, in the
    relationship Person -> owns -> Chair, "this chair is exclusive to this
    person" is better than "the Person/Chair relationship is unique":

      type Person:
          single link owns -> Chair:
              constraint exclusive
    

    So, to summarize:

    Former '11' is now single + constraint exclusive.
    Former '1*' is now multi + constraint exclusive.
    Former '*1' is now just single (this is the default).
    Former '**' is now just multi.

    The new qualifier syntax is also significantly more natural to use with
    computable links and properties when an explicit cardinality qualifier
    needs to be given to override the inferred value:

      type Person:
          multi link items := {'item'}
    

    This now extends to ad-hoc computables in queries as well, so:

      SELECT Person {
          multi items := {'item'}
      }
    

    instead of the awkward and somewhat arcane:

      SELECT Person {
          items := (WITH CARDINALITY '*' SELECT 'item')
      }
    

    The WITH CARDINALITY '*' syntax is now entirely unnecessary and has
    been removed.

    The new syntax also allows expressing the non-zero cardinality
    requirement with the required qualifier on the computable, but that is
    left for a subsequent commit (see #217).

    Closes: #303.

  • edgeql: Update how time and date is handled. (commit a3457f3)

    The time and date scalars are:

    • datetime
    • naivedatetime
    • naivedate
    • naivetime
    • timedelta

    There are 3 different functions for obtaining "current" datetime:

    • datetime_now
    • datetime_of_statement
    • datetime_of_transaction

    There are also a suite of functions that extract specific date or time
    parts:

    • datetime_get
    • date_get
    • time_get
    • timedelta_get
  • edgeql: Add converter functions for multiple data types. (commit 19e6a23)

    The to_str function is meant to be like a cast when called
    without the format parameter.

    to_str usage with json scalars is not equivalent to casting, it is
    producing a string representation of JSON. The inverse function to_json
    is therefore parsing a string, not casting either:

    • str_to_json becomes to_json
    • json_to_str becomes to_str

    Add various date and time converter functions.

  • Restrict usage of abstract scalars and anytype. (commit a23af17)

    Casting into an abstract scalar or anytype is now forbidden.

    Technically anytype is a valid type that is the supertype for both
    anyscalar and Object. However, it is currently illegal to use it
    anywhere outside of a function signature definition.

    Anytype is also special in the fact that it doesn't have a corresponding
    entry in the schema module (no Type object).

  • edgeql: Make casts more consistent. (commit fe0e8cb)

    Forbid casting bytes into anything other than bytes (this makes sense
    for scalar types derived from bytes).

    Make JSON casts symmetric. For any type that allows a cast into json, it
    should also allow to cast back without additional intermediate steps
    (such as casting into str first).

  • Formally implement fundamental operators as part of stdlib (commit f406f99)

    This declares currently supported binary and prefix operators
    on standard scalar types using the new CREATE OPERATOR DDL.
    Expression type inference has been switched over from a
    hardcoded table to looking up operators from the schema.

    This also allows removing a bunch of hardcoded logic from the
    compiler, since we can now consistently rely on the operators
    properly reflected in the backend.

    This commit also features correct implementation of the floor division
    (//) and division remainder (%) operators, which now truncate toward
    negative infinity, like Python does.

  • Implement array, string and byte concatenation via the ++ operator (commit de73ddf)

    The current + operator is a poor choice for concatenation, especially
    in the array case, since the latter may be interpreted as an
    element-wise vector addition. Instead, use ++ consistently as the
    concatenation operator for all data types that support it.

    Closes: #330.

  • Prohibit casting of object types (commit deacffb)

    Object types cannot be cast between themselves, as cast is a
    constructor operation, and the only valid way to construct
    an object is to INSERT it.

  • Implement new syntax for the SET command. (commit 6bd9021)

    Supported variants:

    • SET CONFIG name := expr;
    • SET MODULE default;
    • SET ALIAS my_foo AS MODULE foo;

    Partially addresses issue #347.

  • edgeql: Add more library functions. (commit 1553f27)

    Add more generic functions to std module like min, max, round, etc.

    Add some specialized functions to math module.

  • Remove invalid DETACHED test (commit c323d4b)

    DETACHED no longer works the way the test expects it to.

  • Rework schema item attributes (commit 9cf7c8a)

    Schema attributes are named values associated with schema items and are
    designed to hold arbitrary user-defined schema-level metadata.

    There are several shortcomings with the current implementation that
    need tweaking.

    First issue: attributes can currently be of any primitive type, which
    makes it really hard to represent the attribute collection as a
    coherent whole without resorting to some string serialization, and that
    can go sideways quickly if the attribute type is reasonably complex.
    Thus, we stop pretending to support arbitrary types in attributes, and
    only support std::str. Complex structures can be stored as JSON and
    coerced to a specific EdgeQL type explicitly, so this change has no
    practical usability loss. This also means that abstract attribute
    declaration does not require a type specification anymore, although we
    may revisit this in the future and allow std::str sub-types to be used,
    to, for example, allow specifying constraints on attribute values.
    Abstract attribute declarations continue to be required for
    disambiguation purposes.

    Second issue: standard schema item aspects, like link cardinality, are
    represented as attributes in the introspection schema. There is no
    reason to do it, and this creates confusing duality, since some aspects
    are represented as properties and links of the appropriate
    schema::Object subtype. We stop doing this, and only reserve
    schema::Object.attributes to things that are true annotations and bear
    no effect on the core schema behavior. Currently the only attributes
    that satisfy this requirement are "title" and "description".

    In DDL, the SET <attribute-name> := <attribute-value> is changed to
    SET ATTRIBUTE <attribute-name> := <attribute-value>.

    In schema DSL we allow setting attribute values on foreign schema items
    using the regular declaration syntax with a qualified name:

      type othermod::Foo:
          attribute attr := 'value'
    

    Issue: #306

  • Make attributes non-inheritable by default (commit 9798846)

    Automatic inheritance of attributes is sometimes inconvenient or
    undesirable. A "description" attribute, for example, is unlikely to be
    useful when inherited. Thus, we make all attributes non-inheritable by
    default, with an option to opt-in to automatic inheritance with the new
    INHERITABLE qualifier for CREATE ATTRIBUTE:

      CREATE INHERITABLE ATTRIBUTE foo;
    

    Issue: #306

Add set literals

Since we now can use {} for denoting sets, let's add this.

Without set literals it's hard to even write edgedb documentation: we'll have to explain the meaning of 1 UNION 2 or teach what array_unpack() does way too early.

@vpetrovykh Could you please open a PR to add set literals to the grammar/parser?

Drop support for INTERSECT and EXCEPT

To avoid having to deal with the questions of set distinctness for INTERSECT and EXCEPT, let's just remove them and suggest to use SELECT A WHERE A [NOT] IN B instead.

Update the `ORDER BY` clause for aggregates

The ORDER BY clause should belong to each SET OF argument and not to the aggregate call as a whole:

SELECT aggregate(X ORDER BY X, 10)

Instead of SQL-like

SELECT aggregate(X, 10 ORDER BY X)

New eschema syntax for constraints subjectexpr

Not until long ago it was possible to specify subjectexprs for parameterless constraints simply by re-using args syntax:

link translated_label to str:
    constraint unique := (subject@source, subject@lang)

To do the same thing now, we need to be explicit:

link translated_label to str:
    constraint unique:
        subject := (subject@source, subject@lang)

An idea to simplify this:

link translated_label to str:
    constraint unique on (subject@source, subject@lang)

But this would require to complicate the lexer or the grammar. Maybe we can come up with a better sugar syntax for this?

Update aggregate and UNION syntax.

DISTINCT and ALL modifiers need to be dropped from aggregate function calls. This is strongly related to the addition of UNION ALL operator, so it makes sense to do at the same time. This is something that may require input from @elprans in order to make sure that what the parser is generating aligns reasonably with the rest of the processing pipeline.

Rename abstract constraints

Currently we have a mechanism to define "abstract constraints", they apply to the derived concepts. This way we can have a base Dictionary class with a unique constraint on its key link which will be enforced on all concepts inherited from Dictionary.

One idea is to rename "abstract constraints" to "deferred constraints".

concept AbstractConstraintParent:
    link name to str:
        abstract constraint unique

test: Can't test a file

$ et test tests/test_edgeql_syntax.py

outputs

Using up to 6 processes to run tests.

unittest/loader.py E

Progress: 1/1 tests.


==============================================================================================================================================
ERROR: tests/test_edgeql_syntax (unittest.loader._FailedTest)
----------------------------------------------------------------------------------------------------------------------------------------------
ImportError: Failed to import test module: tests/test_edgeql_syntax
Traceback (most recent call last):
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/unittest/loader.py", line 153, in loadTestsFromName
    module = __import__(module_name)
ModuleNotFoundError: No module named 'tests/test_edgeql_syntax'


FAILURE
  tests ran: 1
  errors: 1

Running times:
  tests: 00:00:00.1

Refactor common.ast.ops

The notion of some language-independent operators is a rather odd one. The operators belong to the specific language where they are defined. The only thing worth salvaging and having in common is probably the Operator class itself.

In particular, operators should be transpiled from one language to another.

Need a tool for testing the examples from the docs efficiently.

Typos and outdated syntax can creep into documentation examples. We need a tool to test them together with the rest of the test suite. In particular that means that we will need to make the examples use module names in a self-consistent and sane manner.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.