11using EdgeDB . Serializer ;
22using System ;
33using System . Collections . Generic ;
4+ using System . Diagnostics . CodeAnalysis ;
45using System . Linq ;
56using System . Linq . Expressions ;
67using System . Reflection ;
@@ -22,13 +23,24 @@ private string BuildInsertLambdaShape(LambdaExpression expression)
2223 {
2324 return $ "{{ { ExpressionTranslator . Translate ( expression , Builder . QueryVariables , Context , Builder . QueryGlobals ) } }}";
2425 }
25-
26- private string BuildInsertShape ( Type ? shapeType = null , object ? shapeValue = null )
26+
27+ private string GetPropertyValue ( object ? inst , string ? path , string type , PropertyInfo info )
28+ {
29+ if ( inst is IJsonVariable json && json . HasProperty ( info . Name ) )
30+ return $ "<{ type } >{ json . Name } { path } ['{ info . Name } ']";
31+
32+ var varName = QueryUtils . GenerateRandomVariableName ( ) ;
33+ SetVariable ( varName , info . GetValue ( inst ) ) ;
34+ return $ "<{ type } >${ varName } ";
35+ }
36+
37+ private List < Type > _subInserts = new ( ) ;
38+ private string BuildInsertShape ( Type ? shapeType = null , object ? shapeValue = null , string ? path = null )
2739 {
2840 List < string > shape = new ( ) ;
2941
30- var type = shapeType ?? Context . CurrentType ;
3142 var value = shapeValue ?? Context . Value ;
43+ var type = shapeType ?? ( value is IJsonVariable var ? var . InnerType : Context . CurrentType ) ;
3244
3345 if ( value is LambdaExpression expression )
3446 return BuildInsertLambdaShape ( expression ) ;
@@ -43,45 +55,50 @@ private string BuildInsertShape(Type? shapeType = null, object? shapeValue = nul
4355
4456 if ( edgeqlType != null )
4557 {
46- var varName = QueryUtils . GenerateRandomVariableName ( ) ;
47- SetVariable ( varName , property . GetValue ( Context . Value ) ) ;
48- shape . Add ( $ "{ propertyName } := <{ edgeqlType } >${ varName } ") ;
58+ shape . Add ( GetPropertyValue ( value , path , edgeqlType , property ) ) ;
4959 continue ;
5060 }
5161
52- // TODO: sub queries!
5362 // might be a link?
5463 if ( TypeBuilder . IsValidObjectType ( property . PropertyType ) )
5564 {
56- // is it a object we've seen before?
57- var subValue = property . GetValue ( value ) ;
58- if ( QueryObjectManager . TryGetObjectId ( subValue , out var id ) )
65+ if ( value is IJsonVariable jsonVariable )
5966 {
60- // insert a sub query
61- var globalName = GetOrAddGlobal ( subValue , new SubQuery ( $ "(select { property . PropertyType . GetEdgeDBTypeName ( ) } filter .id = <uuid>\" { id } \" )") ) ;
62- shape . Add ( $ "{ propertyName } := { globalName } ") ;
63- continue ;
67+ if ( _subInserts . Any ( x => jsonVariable . InnerType == x ) )
68+ throw new InvalidOperationException ( "cannot preform sub type inserts of the same type within a json imported union" ) ;
6469 }
6570 else
6671 {
67- if ( subValue is null )
68- shape . Add ( $ "{ propertyName } := {{}}") ;
72+ // is it a object we've seen before?
73+ var subValue = property . GetValue ( value ) ;
74+ if ( QueryObjectManager . TryGetObjectId ( subValue , out var id ) )
75+ {
76+ // insert a sub query
77+ var globalName = GetOrAddGlobal ( subValue , new SubQuery ( $ "(select { property . PropertyType . GetEdgeDBTypeName ( ) } filter .id = <uuid>\" { id } \" )") ) ;
78+ shape . Add ( $ "{ propertyName } := { globalName } ") ;
79+ continue ;
80+ }
6981 else
7082 {
71- RequiresIntrospection = true ;
72- var globalName = GetOrAddGlobal ( subValue , new SubQuery ( ( info ) =>
83+ if ( subValue is null )
84+ shape . Add ( $ "{ propertyName } := {{}}") ;
85+ else
7386 {
74- var name = property . PropertyType . GetEdgeDBTypeName ( ) ;
75- var exclusiveProps = QueryUtils . GetProperties ( info , property . PropertyType , true ) ;
76- var exclusiveCondition = exclusiveProps . Any ( ) ?
77- $ " unless conflict on { ( exclusiveProps . Count ( ) > 1 ? $ "({ string . Join ( ", " , exclusiveProps . Select ( x => $ ".{ x . GetEdgeDBPropertyName ( ) } ") ) } )" : $ ".{ exclusiveProps . First ( ) . GetEdgeDBPropertyName ( ) } ") } else (select { name } )"
78- : string . Empty ;
79- return $ "(insert { name } { BuildInsertShape ( property . PropertyType , subValue ) } { exclusiveCondition } )";
80- } ) ) ;
81- shape . Add ( $ "{ propertyName } := { globalName } ") ;
87+ RequiresIntrospection = true ;
88+ var globalName = GetOrAddGlobal ( subValue , new SubQuery ( ( info ) =>
89+ {
90+ var name = property . PropertyType . GetEdgeDBTypeName ( ) ;
91+ var exclusiveProps = QueryUtils . GetProperties ( info , property . PropertyType , true ) ;
92+ var exclusiveCondition = exclusiveProps . Any ( ) ?
93+ $ " unless conflict on { ( exclusiveProps . Count ( ) > 1 ? $ "({ string . Join ( ", " , exclusiveProps . Select ( x => $ ".{ x . GetEdgeDBPropertyName ( ) } ") ) } )" : $ ".{ exclusiveProps . First ( ) . GetEdgeDBPropertyName ( ) } ") } else (select { name } )"
94+ : string . Empty ;
95+ return $ "(insert { name } { BuildInsertShape ( property . PropertyType , subValue , path is null ? property . Name : path += $ ".{ property . Name } ") } { exclusiveCondition } )";
96+ } ) ) ;
97+ shape . Add ( $ "{ propertyName } := { globalName } ") ;
98+ }
99+
100+ continue ;
82101 }
83-
84- continue ;
85102 }
86103 }
87104
@@ -146,22 +163,7 @@ public void ElseDefault()
146163
147164 public void Else ( IQueryBuilder builder )
148165 {
149- // remove addon & autogen nodes.
150- var userNodes = builder . Nodes . Where ( x => ! builder . Nodes . Any ( y => y . SubNodes . Contains ( x ) ) || ! x . IsAutoGenerated ) ;
151-
152- // TODO: better checks for this, future should add a callback to add the
153- // node with its context so any parent builder can change contexts for nodes
154- foreach ( var node in userNodes )
155- node . Context . SetAsGlobal = false ;
156-
157- foreach ( var variable in builder . Variables )
158- {
159- Builder . QueryVariables [ variable . Key ] = variable . Value ;
160- }
161-
162- var newBuilder = new QueryBuilder < object ? > ( userNodes . ToList ( ) , builder . Globals . ToList ( ) , builder . Variables . ToDictionary ( x => x . Key , x=> x . Value ) ) ;
163-
164- var result = newBuilder . BuildWithGlobals ( ) ;
166+ var result = builder . BuildWithoutAutogeneratedNodes ( Builder ) ;
165167 _children . Append ( $ " else ({ result . Query } )") ;
166168 }
167169 }
0 commit comments