Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Query builder v2 #1

Open
wants to merge 131 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
131 commits
Select commit Hold shift + click to select a range
ec76977
Rebase to v1 driver
quinchs Oct 19, 2022
5fe680a
Generate docs
github-actions[bot] Oct 19, 2022
2806100
update querybuilder example
quinchs Oct 19, 2022
09e2337
Merge branch 'feat/querybuilder-v2' of https://github.com/edgedb/edge…
quinchs Oct 19, 2022
e148256
Merge branch 'dev' into feat/querybuilder-v2
quinchs Oct 19, 2022
0fd1140
Merge branch 'dev' into feat/querybuilder-v2
quinchs Oct 19, 2022
5ef6be1
Merge branch 'dev' into feat/querybuilder-v2
quinchs Oct 19, 2022
89e7d8a
add querybuilder back to prerelease workflow
quinchs Oct 21, 2022
7c1497b
Merge branch 'dev' into feat/querybuilder-v2
quinchs Oct 21, 2022
9107dd3
Fix cherrypicking of properties
quinchs Oct 21, 2022
bc722ab
Generate docs
github-actions[bot] Oct 21, 2022
45b683e
update config method ref
quinchs Oct 24, 2022
5972880
Merge branch 'dev' into feat/querybuilder-v2
quinchs Oct 25, 2022
e205a38
Generate docs
github-actions[bot] Oct 25, 2022
4ce520a
Merge branch 'dev' into feat/querybuilder-v2
quinchs Oct 25, 2022
26de1fd
Merge branch 'dev' into feat/querybuilder-v2
quinchs Oct 26, 2022
81cea4d
Merge branch 'dev' into feat/querybuilder-v2
quinchs Oct 28, 2022
5a8cbed
Update deploy-prerelease.yml
quinchs Oct 29, 2022
0829eb9
Update deploy-prerelease.yml
quinchs Oct 29, 2022
bdaa848
add sub shape depth
quinchs Oct 30, 2022
13c1f0a
add new select to static def
quinchs Oct 30, 2022
48d8878
Fix #8
quinchs Nov 2, 2022
033c473
make new context type for referencing self
quinchs Nov 2, 2022
89cae60
fix summaries
quinchs Nov 2, 2022
1775bc7
Merge branch 'dev' into feat/querybuilder-v2
quinchs Nov 8, 2022
7551bc3
Merge branch 'dev' into feat/querybuilder-v2
quinchs Nov 8, 2022
673fddb
Generate docs
github-actions[bot] Nov 8, 2022
db2376c
Merge branch 'dev' into feat/querybuilder-v2
quinchs Nov 14, 2022
d77fae5
Merge branch 'dev' into feat/querybuilder-v2
quinchs Nov 17, 2022
682a35b
Merge branch 'dev' into feat/querybuilder-v2
quinchs Nov 17, 2022
792aff7
Add support for custom converters in QB
quinchs Nov 17, 2022
64670cc
Add expression visitor
quinchs Dec 7, 2022
4f05896
Revert "Add expression visitor"
quinchs Dec 7, 2022
b2507f4
Merge branch 'dev' into feat/querybuilder-v2
quinchs Dec 27, 2022
5c9cb37
bump querybuilder to .net7
quinchs Dec 27, 2022
ae81067
add new shape builder. optimizer for with statements
quinchs Jan 4, 2023
efbffd3
Merge branch 'dev' into feat/querybuilder-v2
quinchs Jan 4, 2023
a549273
fix summary errors
quinchs Jan 4, 2023
d2afc77
add explicit shape definition
quinchs Feb 2, 2023
109e8bd
Merge branch 'dev' into feat/querybuilder-v2
quinchs Feb 3, 2023
74added
change pre-releases to myget
quinchs Feb 5, 2023
0cf44f5
Revert "change pre-releases to myget"
quinchs Feb 5, 2023
5359ee3
Merge branch 'dev' into feat/querybuilder-v2
quinchs May 22, 2023
7691d7b
LINQ ext
quinchs May 22, 2023
95485e1
fix merge issues
quinchs May 22, 2023
98f1e5e
Add select expressional with shape
quinchs May 22, 2023
0f9cb6c
add missing summary
quinchs May 22, 2023
df33f42
Add cardinality control to IMultiCardinalityExecutable
quinchs May 22, 2023
57288b0
Add contextual Update methods
quinchs May 22, 2023
6f5d4e3
add global contextual Update methods
quinchs May 22, 2023
943613d
Add contextual Update and With functions
quinchs May 23, 2023
15a2f22
add static update methods for QB
quinchs Jun 3, 2023
94279e5
clean up querybuilder code
quinchs Jun 28, 2023
d7a3453
Add basic expression tests
quinchs Jun 28, 2023
f1bd9d4
updated grammar
quinchs Jun 30, 2023
2a7d508
remove test code
quinchs Oct 10, 2023
2afcc52
Merge branch 'dev' into feat/querybuilder-v2
quinchs Oct 12, 2023
e7a469e
fix merge related stuff
quinchs Oct 31, 2023
5019c2d
start work on switching to stringbuilder
quinchs Nov 19, 2023
3dff00e
Merge branch 'dev' into feat/querybuilder-v2
quinchs Jan 11, 2024
0587f02
query string refactor
quinchs Jan 12, 2024
afcbcf6
Fix generator
quinchs Jan 13, 2024
6f64d6e
remove old impl of stdlib
quinchs Jan 13, 2024
2e5b5d4
fix tests and queryable project
quinchs Jan 13, 2024
5ca77ff
Continue work on rework
quinchs Jan 17, 2024
06b9167
root writer and labels
quinchs Jan 17, 2024
5090201
More questionable work on the query builder
quinchs Jan 19, 2024
6760edf
Merge branch 'dev' into feat/querybuilder-v2
quinchs Jan 25, 2024
23594db
more in-depth lexical labelling
quinchs Jan 25, 2024
fe33002
contextual shape exclusion
quinchs Jan 25, 2024
6792a25
woah! its more query builder work
quinchs Feb 20, 2024
ad2aae7
fix allocs and references
quinchs Feb 23, 2024
cf934d4
small bug fixes
quinchs Feb 24, 2024
0aa1c3f
partially fix list problems :cry:
quinchs Feb 26, 2024
878fbf4
make looselinkedlist safe
quinchs Mar 4, 2024
2451099
it actually works :O
quinchs Mar 9, 2024
975f2c6
Build -> Compile
quinchs Mar 9, 2024
8cc1ebb
debug views
quinchs Mar 9, 2024
e035d58
debug view flame-graph
quinchs Mar 9, 2024
ebaa4e4
don't look at verbose markers
quinchs Mar 9, 2024
49529e2
more changes to inner generation
quinchs Mar 9, 2024
4fcd9d5
refactor and fix FOR iterator
quinchs Mar 9, 2024
3ed6b58
compact debug view
quinchs Mar 10, 2024
165a03b
fix insert being dumb cuz of generics
quinchs Mar 10, 2024
c1eb806
groups!
quinchs Mar 11, 2024
2b25bb2
cast reduction, fix groups, smart markers, aggregation
quinchs Mar 13, 2024
c40352a
faster method translation lookup
quinchs Mar 29, 2024
cddba32
whoops x2
quinchs Mar 29, 2024
d33e5a1
new update builder
Apr 8, 2024
597206e
Merge branch 'dev' into feat/querybuilder-v2
Apr 8, 2024
c122421
Merge branch 'feat/querybuilder-v2' of https://github.com/edgedb/edge…
Apr 9, 2024
8c5ca54
benchmarking
Apr 13, 2024
fb435ed
updates?
Apr 16, 2024
2faa75e
fix summaries
Apr 16, 2024
912f81e
support enums :100:
Apr 17, 2024
e65d9bb
only write ',' when an element was written
Apr 17, 2024
b942a6b
don't require proxy to write something
Apr 17, 2024
2bc986f
make use of optional parameters
Apr 17, 2024
08258d2
Merge branch 'dev' into feat/querybuilder-v2
Apr 18, 2024
16c204c
Merge branch 'dev' into feat/querybuilder-v2
Apr 19, 2024
c728790
fix comma separation of globals
Apr 22, 2024
b34429c
don't rely on tryadd for scalar check
Apr 22, 2024
27ef99c
select of type
Apr 26, 2024
8bb87b7
add json resolve for memebrs
Apr 26, 2024
0df0c61
Add overloads for adding/removing sets for update
Apr 26, 2024
0ecd6ee
FOR iterator signature change
Apr 26, 2024
f249509
AsSetAggregation, fix group wrapping & keying
Apr 27, 2024
a84bc69
orderby doesn't box, fix unary cast exp
Apr 27, 2024
4a1aaaa
Delete is now a method, add generic overload
Apr 27, 2024
4663959
add AsSet to mirror the revers of AsSetAggregation
Apr 27, 2024
de28bc3
Handle optional function args better internally
Apr 27, 2024
3426f98
fix summaries
Apr 27, 2024
2df336e
fix context type of update
Apr 27, 2024
ccb6b1c
fix for type check
Apr 27, 2024
9268575
fix static member reference for variables
Apr 29, 2024
1fd32f2
some more enumerable translations
quinchs May 4, 2024
40a3919
some generics doohickery
May 5, 2024
017c701
Merge branch 'feat/querybuilder-v2' of https://github.com/edgedb/edge…
May 5, 2024
41e5be7
massive additions to query writer internals + reducers
May 14, 2024
d625ba7
reducers update
May 21, 2024
a75fd35
select shape reducer
May 27, 2024
9bd7e7f
fix marker move
May 27, 2024
df9bc0b
minor fixes
May 27, 2024
85ffe96
Marker -> Term, Value -> Token
May 27, 2024
847d213
code cleanup
May 27, 2024
560b997
more minor refactors
May 28, 2024
55d4c22
add EdgeQL global support
May 28, 2024
a162ec7
small refactors
Jun 5, 2024
c24d335
api consistency with context
Jun 5, 2024
e1a797a
update context usage
Jun 5, 2024
88b3329
update stdlib
Jun 5, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
more changes to inner generation
  • Loading branch information
quinchs committed Mar 9, 2024
commit 49529e28a21cb1b30a1f474228bb8b9b2140bfcc
36 changes: 35 additions & 1 deletion dbschema/migrations/00001.edgeql
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
CREATE MIGRATION m1onahwoyqgtvzlz6g2wmvst4okehoog33xcxiqqv7oaghovjtdzpq
CREATE MIGRATION m1cpt5buyevyky24nrcoyjzfl67idj3uculwgo47zpxjnkb442knjq
ONTO initial
{
CREATE MODULE tests IF NOT EXISTS;
CREATE GLOBAL default::abc -> tuple<std::str, std::int64>;
CREATE GLOBAL default::current_user_id -> std::uuid;
CREATE ABSTRACT TYPE default::AbstractThing {
Expand Down Expand Up @@ -45,4 +46,37 @@ CREATE MIGRATION m1onahwoyqgtvzlz6g2wmvst4okehoog33xcxiqqv7oaghovjtdzpq
};
CREATE REQUIRED PROPERTY username: std::str;
};
CREATE TYPE tests::Person {
CREATE LINK best_friend: tests::Person;
CREATE MULTI LINK friends: tests::Person;
CREATE PROPERTY age: std::int32;
CREATE PROPERTY email: std::str;
CREATE PROPERTY name: std::str;
};
CREATE TYPE tests::Club {
CREATE MULTI LINK admins: tests::Person;
CREATE MULTI LINK members: tests::Person;
CREATE PROPERTY name: std::str;
};
CREATE TYPE tests::ScalarContainer {
CREATE PROPERTY a: std::int16;
CREATE PROPERTY b: std::int32;
CREATE PROPERTY c: std::int64;
CREATE PROPERTY d: std::str;
CREATE PROPERTY e: std::bool;
CREATE PROPERTY f: std::float32;
CREATE PROPERTY g: std::float64;
CREATE PROPERTY h: std::bigint;
CREATE PROPERTY i: std::decimal;
CREATE PROPERTY j: std::uuid;
CREATE PROPERTY k: std::json;
CREATE PROPERTY l: std::datetime;
CREATE PROPERTY m: cal::local_datetime;
CREATE PROPERTY n: cal::local_date;
CREATE PROPERTY o: cal::local_time;
CREATE PROPERTY p: std::duration;
CREATE PROPERTY q: cal::relative_duration;
CREATE PROPERTY r: cal::date_duration;
CREATE PROPERTY s: std::bytes;
};
};
26 changes: 0 additions & 26 deletions dbschema/migrations/00013.edgeql

This file was deleted.

14 changes: 14 additions & 0 deletions dbschema/tests.esdl
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,18 @@ module tests {
r: cal::date_duration;
s: bytes;
}

type Person {
name: str;
age: int32;
email: str;
best_friend: Person;
multi friends: Person;
}

type Club {
name: str;
multi members: Person;
multi admins: Person;
}
}
94 changes: 30 additions & 64 deletions examples/EdgeDB.Examples.CSharp/Examples/QueryBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,35 +32,6 @@ public async Task ExecuteAsync(EdgeDBClient client)
{
try
{
var tests = await QueryBuilder
.Select<ObjectType>(shape =>
{
shape.IncludeMultiLink(x => x.Constraints);
shape.IncludeMultiLink(x => x.Properties, shape =>
shape.Computeds((ctx, prop) => new
{
Cardinality = (string)ctx.UnsafeLocal<object>("cardinality") == "One"
? ctx.UnsafeLocal<bool>("required")
? Cardinality.One
: Cardinality.AtMostOne
: ctx.UnsafeLocal<bool>("required")
? Cardinality.AtLeastOne
: Cardinality.Many,
TargetId = ctx.UnsafeLocal<Guid>("target.id"),
IsLink = ctx.Raw<object?>("[IS schema::Link]") != null,
IsExclusive =
ctx.Raw<bool>("exists (select .constraints filter .name = 'std::exclusive')"),
IsComputed = EdgeQL.Len(ctx.UnsafeLocal<object[]>("computed_fields")) != 0,
IsReadonly = ctx.UnsafeLocal<bool>("readonly"),
HasDefault =
ctx.Raw<bool>(
"EXISTS .default or (\"std::sequence\" in .target[IS schema::ScalarType].ancestors.name)")
})
);
})
.Filter((x, ctx) => !ctx.UnsafeLocal<bool>("builtin"))
.CompileAsync(client, true);

await QueryBuilderDemo(client);
}
catch (Exception x)
Expand All @@ -72,10 +43,10 @@ public async Task ExecuteAsync(EdgeDBClient client)
private static async Task QueryBuilderDemo(EdgeDBClient client)
{
// Selecting a type with autogen shape
var query = QueryBuilder.Select<Person>().Compile().Prettify();
var query = QueryBuilder.Select<Person>().Compile(true);

// Adding a filter, orderby, offset, and limit
var queryTest = QueryBuilder
query = QueryBuilder
.Select<Person>()
.Filter(x => EdgeQL.ILike(x.Name, "e%"))
.OrderByDesending(x => x.Name)
Expand All @@ -87,12 +58,12 @@ private static async Task QueryBuilderDemo(EdgeDBClient client)
query = QueryBuilder.Select<Person>(shape =>
shape
.Explicitly(p => new { p.Name, p.Email, p.BestFriend })
).Compile().Prettify();
).Compile(true);

// selecting things that are not types
query = QueryBuilder.SelectExpression(() =>
EdgeQL.Count(QueryBuilder.Select<Person>())
).Compile().Prettify();
).Compile(true);

// selecting 'free objects'
query = QueryBuilder.SelectExpression(ctx => new
Expand All @@ -101,7 +72,7 @@ private static async Task QueryBuilderDemo(EdgeDBClient client)
MyNumber = 42,
SeveralNumbers = new long[] { 1, 2, 3 },
People = ctx.SubQuery(QueryBuilder.Select<Person>())
}).Compile().Prettify();
}).Compile(true);

// Backlinks
query = QueryBuilder.Select<Person>(shape => shape
Expand All @@ -113,43 +84,41 @@ private static async Task QueryBuilderDemo(EdgeDBClient client)
// you can pass in a string instead of an expression to select out a 'EdgeDBObject' type.
ReferencedFriends = ctx.BackLink<Person>(x => x.Friends)
})
).Compile().Prettify();
).Compile(true);

// With object variables
query = QueryBuilder
.With(new { Args = EdgeQL.AsJson(new { Name = "Example", Email = "[email protected]" }) })
.SelectExpression(ctx => new
{
PassedName = ctx.Variables.Args.Value.Name, PassedEmail = ctx.Variables.Args.Value.Email
}).Compile().Prettify();
}).Compile(true);

// Inserting a new type
var person = new Person { Email = "[email protected]", Name = "example" };

query = QueryBuilder.Insert(person).Compile().Prettify();
query = QueryBuilder.Insert(person).Compile(true);

// Complex insert with links & dealing with conflicts
query = (await QueryBuilder
.Insert(new Person { BestFriend = person, Name = "example2", Email = "[email protected]" })
.UnlessConflict()
.ElseReturn()
.CompileAsync(client))
.Prettify();
query = await QueryBuilder
.Insert(new Person {BestFriend = person, Name = "example2", Email = "[email protected]"})
.UnlessConflict()
.ElseReturn()
.CompileAsync(client, true);

// Manual conflicts
query = QueryBuilder
.Insert(person)
.UnlessConflictOn(x => x.Email)
.ElseReturn()
.Compile()
.Prettify();
.Compile(true);

// Autogenerating unless conflict with introspection
queryTest = (await QueryBuilder
.Insert(person)
.UnlessConflict()
.ElseReturn()
.CompileAsync(client, true));
query = await QueryBuilder
.Insert(person)
.UnlessConflict()
.ElseReturn()
.CompileAsync(client, true);

// Bulk inserts
var data = new Person[]
Expand All @@ -163,33 +132,30 @@ private static async Task QueryBuilderDemo(EdgeDBClient client)
}
};

var tquery = await QueryBuilder.For(data,
query = await QueryBuilder.For(data,
x => QueryBuilder.Insert(x)
).CompileAsync(client);
).CompileAsync(client, true);

// Else statements (upsert demo)
query = (await QueryBuilder
.Insert(person)
.UnlessConflict()
.Else(q =>
q.Update(old => new Person { Name = old!.Name!.ToLower() })
)
.CompileAsync(client))
.Prettify();
query = await QueryBuilder
.Insert(person)
.UnlessConflict()
.Else(q =>
q.Update(old => new Person {Name = old!.Name!.ToLower()})
)
.CompileAsync(client, true);

// Updating a type
query = QueryBuilder
.Update<Person>(old => new Person { Name = "example new name" })
.Filter(x => x.Email == "[email protected]")
.Compile()
.Prettify();
.Compile(true);

// Deleting types
query = QueryBuilder
.Delete<Person>()
.Filter(x => EdgeQL.ILike(x.Name, "e%"))
.Compile()
.Prettify();
.Compile(true);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public void Reduce(IQueryBuilder builder, QueryWriter writer)
continue;

Value[]? tokens = null;
foreach (var marker in markers)
foreach (var marker in markers.ToArray())
{
Action<QueryNode>? modifier = marker switch
{
Expand Down
8 changes: 8 additions & 0 deletions src/EdgeDB.Net.QueryBuilder/Grammar/Terms.cs
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,14 @@ public static QueryWriter Assignment(this QueryWriter writer, Value name, Value
public static QueryWriter TypeCast(this QueryWriter writer, Value type)
=> writer.Append("<", type, ">");

public static QueryWriter Variable(this QueryWriter writer, Value type, Value name)
=> writer.Marker(
MarkerType.Variable,
$"variable_{name}",
debug: null,
Value.Of(writer => writer.TypeCast(type).Append(name))
);

public readonly struct FunctionArg
{
public readonly Value Value;
Expand Down
3 changes: 2 additions & 1 deletion src/EdgeDB.Net.QueryBuilder/Lexical/MarkerType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@

public enum MarkerType
{
Global,
GlobalReference,
GlobalDeclaration,
Function,
FunctionArg,
Shape,
Expand Down
12 changes: 12 additions & 0 deletions src/EdgeDB.Net.QueryBuilder/Lexical/Value.cs
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,18 @@ private string DebugDisplay()
return _ch is not null ? $"char \'{_ch}\'" : _value is null ? "null" : $"value {_value}";
}

public override string ToString()
{
if (_callback is not null)
return "<callback>";
if (_str is not null)
return "<str>";
if (_ch.HasValue)
return "<char>";

return "<object>";
}

public static implicit operator Value(string? value) => new(value);
public static implicit operator Value(char value) => new(value);
public static implicit operator Value(WriterProxy callback) => new(callback);
Expand Down
42 changes: 27 additions & 15 deletions src/EdgeDB.Net.QueryBuilder/QueryGlobal.cs
Original file line number Diff line number Diff line change
Expand Up @@ -74,21 +74,33 @@ public Value[] Compile(QueryNode source, QueryWriter writer, CompileContext? con
private Value[] Compile<T>(T source, Action<IQueryBuilder, QueryWriter, T, CompileContext?> compileBuilder, QueryWriter writer, CompileContext? context = null,
SchemaInfo? info = null)
{
return Value switch
{
// if its a query builder, build it and add it as a sub-query.
IQueryBuilder queryBuilder => writer
.Span(writer =>
writer.Wrapped(
writer => compileBuilder(queryBuilder, writer, source, context)
)
),
// if its a sub query that requires introspection, build it and add it.
SubQuery {RequiresIntrospection: true} when info is null => throw new InvalidOperationException(
"Cannot build without introspection! A node requires query introspection."),
SubQuery {RequiresIntrospection: true} subQuery => writer.Span(writer => subQuery.Build(info, writer)),
_ => writer.Span(writer => QueryUtils.ParseObject(writer, Value))
};
return writer.Span(writer => writer
.Marker(
MarkerType.GlobalDeclaration,
Name,
Defer.This(() => $"Reference?: {Reference?.GetType().ToString() ?? "null"}, Value?: {Value?.GetType().ToString() ?? "null"}"),
EdgeDB.Value.Of(writer =>
{
switch (Value)
{
case IQueryBuilder queryBuilder:
writer.Wrapped(writer =>
compileBuilder(queryBuilder, writer, source, context));
break;
case SubQuery {RequiresIntrospection: true} when info is null:
throw new
InvalidOperationException(
"Cannot build without introspection! A node requires query introspection.");
case SubQuery {RequiresIntrospection: true} subQuery:
subQuery.Build(info, writer);
break;
default:
QueryUtils.ParseObject(writer, Value);
break;
}
})

));
}
}
}
13 changes: 11 additions & 2 deletions src/EdgeDB.Net.QueryBuilder/QueryNodes/ForNode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,17 @@ public override void FinalizeQuery(QueryWriter writer)
if (_name is null || _jsonName is null || _expression is null)
throw new InvalidOperationException("No initialization of this node was preformed");

// append the 'FOR' statement
writer.Append("for ", _name, " in json_array_unpack(<json>", _jsonName, ") union ", Value.Of(writer => writer.Wrapped(_expression)));
writer.Append(
"for ",
_name,
" in ",
Value.Of(writer => writer.Function(
"json_array_unpack",
Value.Of(writer => writer.Variable("json", _jsonName))
)),
" union ",
Value.Of(writer => writer.Wrapped(_expression))
);
}
}
}
Loading