-
Notifications
You must be signed in to change notification settings - Fork 14
Description
gel-go Bug Report: Incorrect Code Generation for Polymorphic Type Intersections
Summary
gel-go v1.4.3 generates incorrect Go types for polymorphic type intersection queries using the syntax field[is SubType]: { ... }, causing a runtime panic when the actual data doesn't match the type filter.
Panic: interface conversion: *codecs.objectDecoder is not codecs.OptionalDecoder: missing method DecodeMissing
Environment
- gel-go version: v1.4.3
- EdgeDB version: 6.11+ / 7.0+
- Go version: 1.23+ (likely all versions)
- Platform: Windows (likely all platforms)
The Problem
Valid EdgeQL That Triggers Bug
SELECT Item {
fields: {
name,
field_type[is ConceptLinkFieldType]: {
target: { id }
}
}
}Generated Go code (INCORRECT):
type FieldsItem struct {
Name string `gel:"name"`
FieldType FieldTypeItem `gel:"field_type"` // ← Not optional!
}
type FieldTypeItem struct {
Target TargetItem `gel:"target"` // ← Not optional!
}Runtime behavior: When a field's field_type is PrimitiveFieldType (not ConceptLinkFieldType), the type intersection returns empty/null, but gel-go tries to decode it into a non-optional struct → panic.
Working Syntax (Generates Correct Code)
SELECT Item {
fields: {
name,
field_type: {
[is ConceptLinkFieldType].target: { id }
}
}
}Generated Go code (CORRECT):
type FieldsItem struct {
Name string `gel:"name"`
FieldType FieldTypeItem `gel:"field_type"`
}
type FieldTypeItem struct {
Target TargetItem `gel:"target"`
}
type TargetItem struct {
geltypes.Optional // ← Correctly optional!
Id geltypes.UUID `gel:"id"`
}Minimal Reproduction
1. Schema
module default {
abstract type FieldType {}
type PrimitiveFieldType extending FieldType {
required property identifier -> str;
}
type ConceptLinkFieldType extending FieldType {
required link target -> Item;
}
type Item {
required property name -> str;
multi link fields -> Field;
}
type Field {
required property name -> str;
required link item -> Item;
required link field_type -> FieldType;
}
}2. Create Test Data
-- Create item
WITH item := (INSERT Item { name := 'Test' })
-- Create field with PRIMITIVE type (not ConceptLink)
INSERT Field {
name := 'TestField',
item := item,
field_type := (INSERT PrimitiveFieldType { identifier := 'text' })
};3. Query with Bug-Triggering Syntax
-- This will panic when executed via gel-go
SELECT Item {
name,
fields: {
name,
field_type[is ConceptLinkFieldType]: {
target: { id }
}
}
}Expected: Should return with field_type empty/null since the actual type is PrimitiveFieldType
Actual: Panic at runtime: interface conversion: *codecs.objectDecoder is not codecs.OptionalDecoder
4. Verify Working Syntax
-- This works correctly
SELECT Item {
name,
fields: {
name,
field_type: {
[is ConceptLinkFieldType].target: { id }
}
}
}Returns successfully with target: null for primitive fields.
Root Cause
The syntax link[is SubType]: { shape } is valid EdgeQL documented in the official EdgeDB SELECT documentation (e.g., characters[is Hero]: { secret_identity }).
However, gel-go's code generator does not recognize that this creates an optional shape (since the type filter may not match). It generates non-optional struct fields, causing a panic when decoding null/empty data from non-matching types.
The workaround syntax field: { [is SubType].property } correctly generates optional types.
Expected Behavior
Both syntaxes should generate equivalent Optional types:
type FieldTypeItem struct {
geltypes.Optional // ← Should be optional for both syntaxes
Target TargetItem `gel:"target"`
}Workaround
Use the alternative syntax: field: { [is SubType].property } instead of field[is SubType]: { property }