diff --git a/entc/gen/graph.go b/entc/gen/graph.go index 42d5050b7..c934c2141 100644 --- a/entc/gen/graph.go +++ b/entc/gen/graph.go @@ -73,7 +73,7 @@ func NewGraph(c *Config, schemas ...*load.Schema) (g *Graph, err error) { check(resolve(t), "resolve %q relations", t.Name) } for _, t := range g.Nodes { - t.resolveFKs() + check(t.resolveFKs(), "set %q foreign-keys", t.Name) } for _, schema := range schemas { g.addIndexes(schema) @@ -144,6 +144,7 @@ func (g *Graph) addEdges(schema *load.Schema) { // Assoc only. case !e.Inverse: t.Edges = append(t.Edges, &Edge{ + def: e, Type: typ, Name: e.Name, Owner: t, @@ -155,6 +156,7 @@ func (g *Graph) addEdges(schema *load.Schema) { case e.Inverse && e.Ref == nil: expect(e.RefName != "", "missing reference name for inverse edge: %s.%s", t.Name, e.Name) t.Edges = append(t.Edges, &Edge{ + def: e, Type: typ, Name: e.Name, Owner: typ, @@ -169,6 +171,7 @@ func (g *Graph) addEdges(schema *load.Schema) { expect(e.RefName == "", "reference name is derived from the assoc name: %s.%s <-> %s.%s", t.Name, ref.Name, t.Name, e.Name) expect(ref.Type == t.Name, "assoc-inverse edge allowed only as o2o relation of the same type") t.Edges = append(t.Edges, &Edge{ + def: e, Type: typ, Name: e.Name, Owner: t, @@ -177,6 +180,7 @@ func (g *Graph) addEdges(schema *load.Schema) { Optional: !e.Required, StructTag: e.Tag, }, &Edge{ + def: e, Type: typ, Owner: t, Name: ref.Name, diff --git a/entc/gen/internal/bindata.go b/entc/gen/internal/bindata.go index f55375aed..5c11a6c75 100644 --- a/entc/gen/internal/bindata.go +++ b/entc/gen/internal/bindata.go @@ -1006,7 +1006,7 @@ func templateMigrateMigrateTmpl() (*asset, error) { return a, nil } -var _templateMigrateSchemaTmpl = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xac\x57\x4b\x6f\xe3\x36\x10\x3e\x4b\xbf\x62\x20\xb8\xc5\x6e\x60\x4b\x49\x6e\x15\xe0\x43\x90\xcd\x02\xc1\x16\xe9\xa2\xc9\x9e\x82\xa0\x60\xa8\x91\x45\x58\x22\x15\x8a\x4a\xe3\xaa\xfa\xef\x05\x1f\x7a\xf9\x11\x7b\xbb\xeb\x8b\xf9\x98\x19\x72\xbe\x99\x6f\x86\x6a\x9a\xe8\xcc\xbf\x16\xe5\x46\xb2\x55\xa6\xe0\xf2\xfc\xe2\xb7\x45\x29\xb1\x42\xae\xe0\x33\xa1\xf8\x2c\xc4\x1a\x6e\x39\x0d\xe1\x2a\xcf\xc1\x08\x55\xa0\xf7\xe5\x2b\x26\xa1\xff\x90\xb1\x0a\x2a\x51\x4b\x8a\x40\x45\x82\xc0\x2a\xc8\x19\x45\x5e\x61\x02\x35\x4f\x50\x82\xca\x10\xae\x4a\x42\x33\x84\xcb\xf0\xbc\xdb\x85\x54\xd4\x3c\xf1\x19\x37\xfb\xbf\xdf\x5e\xdf\xdc\xdd\xdf\x40\xca\x72\x04\xb7\x26\x85\x50\x90\x30\x89\x54\x09\xb9\x01\x91\x82\x1a\x1d\xa6\x24\x62\xe8\x9f\x45\x6d\xeb\xfb\x4d\x03\x09\xa6\x8c\x23\x04\x15\xcd\xb0\x20\x01\xd8\xe5\x05\xfc\xcd\x54\x06\xf8\xa6\x90\x27\x30\x83\xe0\x2b\xa1\x6b\xb2\xc2\x00\x82\x82\xad\x24\x51\x18\xc0\xa2\x6d\x7d\xaf\x69\x40\x61\x51\xe6\x44\x21\x04\x19\x92\x04\x65\x00\xa1\xb6\xd2\x34\xa0\x75\xb5\x3d\x56\x94\x42\x2a\xf8\x60\xc4\x25\xe1\x2b\x84\xd9\x5f\x73\x98\x71\x88\x97\x30\x0b\xef\x44\x82\x95\x16\xf4\xbc\xa0\x69\x60\x16\x5e\x0b\x9e\xb2\x55\xe8\xce\x84\xb6\x8d\xf4\x32\x1f\x2d\x04\xda\xd4\xa2\x3f\xc0\x0b\x56\x4c\x65\xf5\x73\x48\x45\x11\xa5\x0e\x7c\xc6\x69\xfd\x4c\x94\x90\x11\x72\x15\x59\xff\xa2\x94\x61\x9e\x04\xa7\x28\x24\x8c\xe4\x48\x55\x54\xbd\xe4\x4e\x39\xf0\x3f\xfa\xfe\x2b\x91\xd6\x91\xc5\xd8\x13\x65\x3d\x79\x20\xcf\x79\xe7\x8a\x96\x88\xce\x20\x65\x3c\x01\xb5\x29\x11\xb8\x89\xb2\x0d\xd1\x4a\x92\x32\xeb\x23\xa3\xb4\xda\x1c\x58\x0a\xf8\xc6\x2a\x55\x81\x89\x8e\x35\x31\x33\x6a\xf1\x12\x18\x4f\xf0\xad\x47\xeb\x7c\x38\xe4\x30\xa0\x4d\x63\x6c\xbe\xc0\x4c\x85\x77\xa4\x40\x8d\xa1\xb9\xa2\xdd\xb3\xa6\x97\x5a\xcd\xcc\x2d\x9a\x43\xdc\xdc\x05\xa8\xc8\xeb\x82\x57\xda\x74\x49\x2a\x4a\xf2\xde\xdc\xbf\x50\x4a\xc6\x55\x0a\xc1\x2f\xd5\xb5\x95\x0a\xac\x62\x14\x81\x3e\xa0\x53\x6d\x5b\xc8\x44\x9e\x54\xc6\xf7\x6e\x31\x15\x36\xc5\x4d\xcc\x9d\xc5\xb6\x0d\x2c\x1a\xa1\x39\x7d\x62\x61\x09\x8f\x4f\x67\x36\x12\xa1\x3d\xad\xf1\xbd\x1d\x08\xa8\x81\x40\x39\x09\x17\x0b\xcf\x6b\x40\xdb\x8f\xed\x61\xb4\x3f\x6c\x0e\x0f\x9b\x12\x63\x30\x69\x11\xda\x3d\xbd\xa2\x53\xb0\x52\x4e\x6a\x6e\x2d\x34\x0b\x8d\xe6\x8c\x86\xdf\x38\x7b\xa9\xf5\x06\xd8\x51\x0c\x4a\xd6\x38\x1f\x03\x37\x16\xbf\xe5\x54\x62\xa1\xcb\x42\xdb\x42\x3f\x39\xa2\x74\x57\xe7\xb9\x8b\x14\x74\xe3\x18\xdc\xe5\x87\xbd\x3d\xfa\x86\xb8\x33\x1a\xde\xb3\x7f\x8c\xb6\xfe\x37\x9a\xe1\xfb\xf2\x57\x4a\x49\x2d\xaf\xff\x2d\x4e\xa1\x41\xe8\xb0\xc6\x0d\xaf\x0b\x13\x19\x33\x88\xe1\xf1\xa9\x52\x92\xf1\x55\x03\x03\xcd\x4d\xea\x1a\x43\xfa\xee\x38\xb5\x08\xef\xdd\xe7\x13\xa6\xa4\xce\x0d\x68\x6e\x78\x8a\x17\xf7\x26\x3f\x74\x08\x8d\xef\xfd\x2c\x86\x82\x94\x8f\xf6\x7e\x7b\xae\xb9\x9e\xc3\xec\x75\x72\xd5\xb5\x1e\xb8\x7c\x79\x9d\x5e\x7b\xa0\x88\x4d\x8d\x51\x25\xf2\xbc\x9e\x36\x26\x8d\x8f\x90\xc6\x90\x71\x4a\x19\xd5\x45\x7d\x20\x8c\xcd\x79\x60\x3c\x15\xb2\x20\x8a\x09\x7e\x1a\x77\x7a\x53\x4b\xf8\xd5\xf1\xc6\x1c\x68\x68\x33\xa2\xc3\xa0\x6f\xdc\x71\xcc\x89\xb7\x18\x6c\xf6\xbe\x4a\x56\x10\xb9\xf9\x82\x9b\x78\x3f\x1b\xb7\xe9\x58\xae\x1d\x1f\x07\xcd\x2e\x6c\x63\x51\x76\x98\xb9\x3d\x2b\x74\x1d\x2b\xd7\xae\x90\xf5\x14\x9e\x5e\xf2\x51\x4f\x19\xb4\xed\xd3\x56\x8e\x4c\x83\xb4\x3d\xb5\xce\x7d\x16\x12\xd9\x8a\x7f\xc1\x4d\x35\xf6\x6e\x58\xde\xeb\x61\xda\x79\x38\x52\x1f\x4e\x75\x2e\xdc\x6f\x8a\x67\x91\x3b\xbc\xd3\x75\x68\xe7\x3d\xe4\x63\xd4\xf7\xc3\xea\x01\xec\x96\xba\x0b\x73\x72\xba\xde\x85\x6c\x17\xdc\xcb\x43\xe8\x4e\x01\xa6\x17\x1d\xc0\x97\xdf\x8b\xf0\x2e\xc8\xfb\x56\xda\x79\x1f\xd5\xe8\x0c\x4a\x51\xa9\x52\x70\x04\x89\xa9\x44\x4e\x19\x5f\x81\x12\x40\x5e\x05\xb3\x5d\x93\x66\x48\xd7\x7a\x35\x17\xa2\xec\x1b\xa3\xfe\xfd\x89\xe9\x0f\x61\x36\xe8\x1f\x87\xcd\x8a\x1b\xf2\xfc\x3f\x00\xbb\x1a\x30\x36\xf4\x5e\x0b\xfd\x89\x28\x77\xb5\x31\x5d\x87\x7f\xf0\x6f\x65\x42\xd4\xb4\xbb\x75\x36\xba\xcd\xd8\xd5\x9b\xb0\x2b\xb6\xfe\x81\x33\xb6\x4c\x7f\xc2\x1c\x0f\x9a\xb6\x9b\xa7\x9a\x1e\x75\xdc\x6d\x8e\x76\x1d\x52\x85\xb7\xfa\x3d\x84\x7d\x1c\xdc\x74\x9c\x0b\x66\xa9\xd9\xa9\x35\x3a\x0d\x58\xf2\xe6\xf8\xb0\x65\x66\xa0\xec\xb8\x42\xb2\xe4\x6d\x5a\x23\xf5\xaf\x6b\xfe\x9d\x40\xff\x2c\xe8\x25\x8e\xe5\xe7\x9e\xd7\x8b\x4d\x4f\x6d\xee\x50\x9e\x9d\x4a\xea\x9f\xc7\xea\x3d\x09\xb7\x67\xa9\x77\xbb\x1b\x6c\x89\xec\xef\x95\xe3\x79\x14\x81\x7b\x40\xdb\xde\x47\xf2\xdc\x34\x39\x65\x17\xdd\xd3\xd9\x01\xe9\x7b\x4e\x76\xfc\x2c\xec\xdb\xdb\xf1\xe7\xb9\x37\x62\xe5\x7b\x9d\x79\xee\x4f\x2f\xdd\xea\x8f\x80\xb4\xe6\x14\x18\x67\xea\xc3\x47\x68\x4e\xfd\x18\xf8\xee\x17\xc1\x56\xb4\xdf\x69\x34\xe3\x6e\x3f\xde\x1e\xc2\xda\x97\x1d\x58\xc2\xa9\xf5\x68\xfb\x2e\x1d\x04\xa3\xb1\xfd\x86\x74\x93\xff\x02\x00\x00\xff\xff\x1c\x78\xd4\x5e\x12\x0f\x00\x00") +var _templateMigrateSchemaTmpl = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xac\x57\x49\x6f\xdb\x46\x14\x3e\x93\xbf\xe2\x81\x50\x8b\xc4\x90\x48\xdb\xb7\x12\xd0\xc1\x70\x1c\xc0\x48\xe1\x06\xb5\x73\x32\x8c\x62\x3c\x7c\x14\x07\x22\x67\xe8\xe1\xd0\xb5\xca\xf2\xbf\x17\xb3\x70\xd3\x62\x29\x4d\x74\xd1\x2c\x6f\xfd\xde\x36\x6c\x9a\xe8\xcc\xbf\x16\xe5\x46\xb2\x55\xa6\xe0\xf2\xfc\xe2\xb7\x45\x29\xb1\x42\xae\xe0\x33\xa1\xf8\x2c\xc4\x1a\x6e\x39\x0d\xe1\x2a\xcf\xc1\x10\x55\xa0\xef\xe5\x2b\x26\xa1\xff\x90\xb1\x0a\x2a\x51\x4b\x8a\x40\x45\x82\xc0\x2a\xc8\x19\x45\x5e\x61\x02\x35\x4f\x50\x82\xca\x10\xae\x4a\x42\x33\x84\xcb\xf0\xbc\xbb\x85\x54\xd4\x3c\xf1\x19\x37\xf7\xbf\xdf\x5e\xdf\xdc\xdd\xdf\x40\xca\x72\x04\x77\x26\x85\x50\x90\x30\x89\x54\x09\xb9\x01\x91\x82\x1a\x29\x53\x12\x31\xf4\xcf\xa2\xb6\xf5\xfd\xa6\x81\x04\x53\xc6\x11\x82\x8a\x66\x58\x90\x00\xec\xf1\x02\xfe\x66\x2a\x03\x7c\x53\xc8\x13\x98\x41\xf0\x95\xd0\x35\x59\x61\x00\x41\xc1\x56\x92\x28\x0c\x60\xd1\xb6\xbe\xd7\x34\xa0\xb0\x28\x73\xa2\x10\x82\x0c\x49\x82\x32\x80\x50\x4b\x69\x1a\xd0\xbc\x5a\x1e\x2b\x4a\x21\x15\x7c\x30\xe4\x92\xf0\x15\xc2\xec\xaf\x39\xcc\x38\xc4\x4b\x98\x85\x77\x22\xc1\x4a\x13\x7a\x5e\xd0\x34\x30\x0b\xaf\x05\x4f\xd9\x2a\x74\x3a\xa1\x6d\x23\x7d\xcc\x47\x07\x81\x16\xb5\xe8\x15\x78\xc1\x8a\xa9\xac\x7e\x0e\xa9\x28\xa2\xd4\x81\xcf\x38\xad\x9f\x89\x12\x32\x42\xae\x22\xeb\x5f\x94\x32\xcc\x93\xe0\x14\x86\x84\x91\x1c\xa9\x8a\xaa\x97\xdc\x31\x07\xfe\x47\xdf\x7f\x25\xd2\x3a\xb2\x18\x7b\xa2\xac\x27\x0f\xe4\x39\xef\x5c\xd1\x14\xd1\x19\xa4\x8c\x27\xa0\x36\x25\x02\x37\x51\xb6\x21\x5a\x49\x52\x66\x7d\x64\x94\x66\x9b\x03\x4b\x01\xdf\x58\xa5\x2a\x30\xd1\xb1\x22\x66\x86\x2d\x5e\x02\xe3\x09\xbe\xf5\x68\x9d\x0f\x4a\x0e\x03\xda\x34\x46\xe6\x0b\xcc\x54\x78\x47\x0a\xd4\x18\x1a\x13\xed\x9d\x15\xbd\xd4\x6c\x66\x6f\xd1\x1c\xe2\xe6\x0c\xa0\x22\xaf\x0b\x5e\x69\xd1\x25\xa9\x28\xc9\x7b\x71\xff\x42\x29\x19\x57\x29\x04\xbf\x54\xd7\x96\x2a\xb0\x8c\x51\x04\x5a\x41\xc7\xda\xb6\x90\x89\x3c\xa9\x8c\xef\xdd\x61\x2a\x6c\x8a\x9b\x98\x3b\x89\x6d\x1b\x58\x34\x42\xa3\x7d\x22\x61\x09\x8f\x4f\x67\x36\x12\xa1\xd5\xd6\xf8\xde\x04\x02\x6a\xdc\x57\xee\xd6\xc5\xc1\xf3\x1a\xd0\xb2\x63\xab\x88\xf6\x8a\xe6\xf0\xb0\x29\x31\x06\x93\x12\xa1\xbd\xd3\x27\x3a\xfd\x2a\xe5\xa8\xe6\x56\x42\xb3\xd0\x48\xce\x68\xf8\x8d\xb3\x97\x5a\x5f\x80\x5d\xc5\xa0\x64\x8d\xf3\x31\x68\x63\xf2\x5b\x4e\x25\x16\xba\x25\xb4\x2d\xf4\x9b\x23\x4c\x77\x75\x9e\xbb\x28\x41\xb7\x8e\xc1\x19\x3f\xdc\xed\xe1\x37\x45\x3b\xa3\xe1\x3d\xfb\xc7\x70\xeb\x7f\xc3\x19\xbe\x4f\x7f\xa5\x94\xd4\xf4\xfa\xdf\xe2\x14\x1a\x84\x0e\x73\xdc\xf0\xba\x30\x51\x31\x8b\x18\x1e\x9f\x2a\x25\x19\x5f\x35\x30\x94\xb8\x49\x5b\x23\x48\xdb\x8e\x53\x89\xf0\x9e\x3d\x9f\x30\x25\x75\x6e\x40\x73\xcb\x53\xbc\xb8\x37\xb9\xa1\x43\x68\x7c\xef\x77\x31\x14\xa4\x7c\xb4\xf6\xed\x31\x73\x3d\x87\xd9\xeb\xc4\xd4\xb5\x5e\xb8\x7c\x79\x9d\x9a\x3d\x94\x87\x4d\x8d\x51\x17\xf2\xbc\xbe\x64\x4c\x0a\x1f\x29\x18\x53\x88\xd3\x72\x51\x5d\xd4\x87\x62\xb1\xf9\x0e\x8c\xa7\x42\x16\x44\x31\xc1\x4f\xab\x9b\x5e\xd4\x12\x7e\x75\x35\x63\x14\x9a\x92\x19\x95\xc3\xc0\x6f\xdc\x71\x95\x13\x6f\x55\xaf\xb9\xfb\x2a\x59\x41\xe4\xe6\x0b\x6e\xe2\xfd\x95\xb8\xdd\x8d\xca\xb5\xab\xc7\x81\xb3\x0b\xdb\x98\x94\xcd\x0f\x56\x6e\x5f\x15\xba\x87\x95\x6b\xd7\xc4\xfa\x12\x9e\x1a\xf9\xa8\xb7\x0c\xda\xf6\x69\x2b\x47\xa6\x41\xda\xde\x5a\xe7\x3e\x0b\x89\x6c\xc5\xbf\xe0\xa6\x1a\x7b\x37\x1c\xef\xf5\x30\xed\x3c\x1c\xb1\x0f\x5a\x9d\x0b\xf7\x9b\xe2\x59\xe4\x0e\xef\x74\x1d\xda\x7d\x0f\xf9\x18\xf5\xfd\xb0\x7a\x00\x3b\x9a\xe9\x85\xd1\x9c\xae\x77\x21\xdb\x05\xf7\xf2\x10\xba\x53\x80\xe9\x45\x07\xf0\xe5\xf7\x22\xbc\x0b\xf2\xbe\x93\x76\xde\x47\x35\x3a\x83\x52\x54\xaa\x14\x1c\x41\x62\x2a\x91\x53\xc6\x57\xa0\x04\x90\x57\xc1\xec\xc4\xa4\x19\xd2\xb5\x3e\xcd\x85\x28\xfb\xa1\xa8\x7f\x7f\x62\xfa\x43\x98\x0d\xfc\xc7\x61\xb3\xe4\xa6\x78\xfe\x1f\x80\x5d\x0f\x18\x0b\x7a\x6f\x7c\xfe\x44\x94\xbb\xde\x98\xae\xc3\x3f\xf8\xb7\x32\x21\x6a\x3a\xdd\x3a\x19\xdd\x65\xec\xfa\x4d\xd8\x35\x5b\xff\x80\x8e\x2d\xd1\x9f\x30\xc7\x83\xa2\xed\xe5\xa9\xa2\x47\x13\x77\xbb\x46\xbb\x09\xa9\xc2\x5b\xfd\x16\xc2\x3e\x0e\x6e\x3b\xce\x05\x73\xd4\xec\xf4\x1a\x9d\x06\x2c\x79\x73\xf5\xb0\x25\x66\x28\xd9\x71\x87\x64\xc9\xdb\xb4\x47\xea\x5f\x37\xfc\x3b\x82\xfe\x59\xd0\x53\x1c\xcb\xcf\x5d\xbb\x5c\x7a\x6a\x71\x87\xf2\xec\xd4\xa2\xfe\x79\x55\xbd\x27\xe1\xf6\x1c\xf5\x6e\x77\x8b\x2d\x92\xfd\xb3\x72\xbc\x8f\x22\x70\x8f\x67\x3b\xfb\x48\x9e\x9b\x21\xa7\xec\xa1\x7b\x36\x3b\x20\x7d\xcf\xd1\x8e\x9f\x84\xfd\x78\x3b\xfe\x34\xf7\x46\x55\xf9\xde\x64\x9e\xfb\x53\xa3\x5b\xfd\x01\x90\xd6\x9c\x02\xe3\x4c\x7d\xf8\x08\xcd\xa9\x1f\x02\xdf\xfd\x22\xd8\x8a\xf6\x3b\x83\x66\x3c\xed\xc7\xd7\x43\x58\xfb\xb6\x03\x4b\x38\xb5\x1f\x6d\xdb\xd2\x41\x30\x5a\xdb\xef\x47\xb7\xf9\x2f\x00\x00\xff\xff\x81\x9a\xd1\xb1\x0e\x0f\x00\x00") func templateMigrateSchemaTmplBytes() ([]byte, error) { return bindataRead( @@ -1021,7 +1021,7 @@ func templateMigrateSchemaTmpl() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "template/migrate/schema.tmpl", size: 3858, mode: os.FileMode(420), modTime: time.Unix(1, 0)} + info := bindataFileInfo{name: "template/migrate/schema.tmpl", size: 3854, mode: os.FileMode(420), modTime: time.Unix(1, 0)} a := &asset{bytes: bytes, info: info} return a, nil } diff --git a/entc/gen/template/migrate/schema.tmpl b/entc/gen/template/migrate/schema.tmpl index fdb45ddd0..8621b0502 100644 --- a/entc/gen/template/migrate/schema.tmpl +++ b/entc/gen/template/migrate/schema.tmpl @@ -27,7 +27,7 @@ var ( {{- $columns := pascal $t.Name | printf "%sColumns" }} // {{ $columns }} holds the columns for the "{{ $t.Name }}" table. {{ $columns }} = []*schema.Column{ - {{- range $_, $c := $t.Columns }} + {{- range $c := $t.Columns }} { Name: "{{ $c.Name }}", Type: field.{{ $c.Type.ConstName }}, {{- if $c.Unique }} Unique: true,{{ end }} {{- if $c.Increment }} Increment: true,{{ end }} diff --git a/entc/gen/type.go b/entc/gen/type.go index f87762865..0c54af55d 100644 --- a/entc/gen/type.go +++ b/entc/gen/type.go @@ -79,6 +79,7 @@ type ( // Edge of a graph between two types. Edge struct { + def *load.Edge // Name holds the name of the edge. Name string // Type holds a reference to the type this edge is directed to. @@ -448,8 +449,11 @@ func (t *Type) AddIndex(idx *load.Index) error { } // resolveFKs makes sure all edge-fks are created for the types. -func (t *Type) resolveFKs() { +func (t *Type) resolveFKs() error { for _, e := range t.Edges { + if err := e.setStorageKey(); err != nil { + return fmt.Errorf("%q edge: %v", e.Name, err) + } if e.IsInverse() || e.M2M() { continue } @@ -474,6 +478,7 @@ func (t *Type) resolveFKs() { e.Type.addFK(fk) } } + return nil } // AddForeignKey adds a foreign-key for the type if it doesn't exist. @@ -958,6 +963,32 @@ func (e Edge) MutationReset() string { return name } +// setStorageKey sets the storage-key option in the schema or fail. +func (e *Edge) setStorageKey() error { + key := e.def.StorageKey + if key == nil { + return nil + } + switch { + case key.Table != "" && !e.M2M(): + return fmt.Errorf("StorageKey.Table is allowed only for M2M edges (got %s)", e.Rel.Type) + case len(key.Columns) == 1 && e.M2M(): + return fmt.Errorf("%s edge have 2 columns. Use edge.Columns(to, from) instead", e.Rel.Type) + case len(key.Columns) > 1 && !e.M2M(): + return fmt.Errorf("%s edge does not have 2 columns. Use edge.Column(%s) instead", e.Rel.Type, key.Columns[0]) + } + if key.Table != "" { + e.Rel.Table = key.Table + } + if len(key.Columns) > 0 { + e.Rel.Columns[0] = key.Columns[0] + } + if len(key.Columns) > 1 { + e.Rel.Columns[1] = key.Columns[1] + } + return nil +} + // Column returns the first element from the columns slice. func (r Relation) Column() string { if len(r.Columns) == 0 { diff --git a/entc/integration/gremlin/ent/fieldtype.go b/entc/integration/gremlin/ent/fieldtype.go index 3de885d7e..fd589987e 100644 --- a/entc/integration/gremlin/ent/fieldtype.go +++ b/entc/integration/gremlin/ent/fieldtype.go @@ -106,6 +106,12 @@ type FieldType struct { SchemaInt8 schema.Int8 `json:"schema_int8,omitempty"` // SchemaInt64 holds the value of the "schema_int64" field. SchemaInt64 schema.Int64 `json:"schema_int64,omitempty"` + // SchemaFloat holds the value of the "schema_float" field. + SchemaFloat schema.Float64 `json:"schema_float,omitempty"` + // SchemaFloat32 holds the value of the "schema_float32" field. + SchemaFloat32 schema.Float32 `json:"schema_float32,omitempty"` + // NullFloat holds the value of the "null_float" field. + NullFloat sql.NullFloat64 `json:"null_float,omitempty"` } // FromResponse scans the gremlin response data into FieldType. @@ -157,6 +163,9 @@ func (ft *FieldType) FromResponse(res *gremlin.Response) error { SchemaInt schema.Int `json:"schema_int,omitempty"` SchemaInt8 schema.Int8 `json:"schema_int8,omitempty"` SchemaInt64 schema.Int64 `json:"schema_int64,omitempty"` + SchemaFloat schema.Float64 `json:"schema_float,omitempty"` + SchemaFloat32 schema.Float32 `json:"schema_float32,omitempty"` + NullFloat sql.NullFloat64 `json:"null_float,omitempty"` } if err := vmap.Decode(&scanft); err != nil { return err @@ -203,6 +212,9 @@ func (ft *FieldType) FromResponse(res *gremlin.Response) error { ft.SchemaInt = scanft.SchemaInt ft.SchemaInt8 = scanft.SchemaInt8 ft.SchemaInt64 = scanft.SchemaInt64 + ft.SchemaFloat = scanft.SchemaFloat + ft.SchemaFloat32 = scanft.SchemaFloat32 + ft.NullFloat = scanft.NullFloat return nil } @@ -329,6 +341,12 @@ func (ft *FieldType) String() string { builder.WriteString(fmt.Sprintf("%v", ft.SchemaInt8)) builder.WriteString(", schema_int64=") builder.WriteString(fmt.Sprintf("%v", ft.SchemaInt64)) + builder.WriteString(", schema_float=") + builder.WriteString(fmt.Sprintf("%v", ft.SchemaFloat)) + builder.WriteString(", schema_float32=") + builder.WriteString(fmt.Sprintf("%v", ft.SchemaFloat32)) + builder.WriteString(", null_float=") + builder.WriteString(fmt.Sprintf("%v", ft.NullFloat)) builder.WriteByte(')') return builder.String() } @@ -385,6 +403,9 @@ func (ft *FieldTypes) FromResponse(res *gremlin.Response) error { SchemaInt schema.Int `json:"schema_int,omitempty"` SchemaInt8 schema.Int8 `json:"schema_int8,omitempty"` SchemaInt64 schema.Int64 `json:"schema_int64,omitempty"` + SchemaFloat schema.Float64 `json:"schema_float,omitempty"` + SchemaFloat32 schema.Float32 `json:"schema_float32,omitempty"` + NullFloat sql.NullFloat64 `json:"null_float,omitempty"` } if err := vmap.Decode(&scanft); err != nil { return err @@ -433,6 +454,9 @@ func (ft *FieldTypes) FromResponse(res *gremlin.Response) error { SchemaInt: v.SchemaInt, SchemaInt8: v.SchemaInt8, SchemaInt64: v.SchemaInt64, + SchemaFloat: v.SchemaFloat, + SchemaFloat32: v.SchemaFloat32, + NullFloat: v.NullFloat, }) } return nil diff --git a/entc/integration/gremlin/ent/fieldtype/fieldtype.go b/entc/integration/gremlin/ent/fieldtype/fieldtype.go index 434d0027c..0682f8067 100644 --- a/entc/integration/gremlin/ent/fieldtype/fieldtype.go +++ b/entc/integration/gremlin/ent/fieldtype/fieldtype.go @@ -97,6 +97,12 @@ const ( FieldSchemaInt8 = "schema_int8" // FieldSchemaInt64 holds the string denoting the schema_int64 field in the database. FieldSchemaInt64 = "schema_int64" + // FieldSchemaFloat holds the string denoting the schema_float field in the database. + FieldSchemaFloat = "schema_float" + // FieldSchemaFloat32 holds the string denoting the schema_float32 field in the database. + FieldSchemaFloat32 = "schema_float32" + // FieldNullFloat holds the string denoting the null_float field in the database. + FieldNullFloat = "null_float" ) var ( diff --git a/entc/integration/gremlin/ent/fieldtype/where.go b/entc/integration/gremlin/ent/fieldtype/where.go index 00e56f0f5..29fac2d87 100644 --- a/entc/integration/gremlin/ent/fieldtype/where.go +++ b/entc/integration/gremlin/ent/fieldtype/where.go @@ -377,6 +377,22 @@ func SchemaInt64(v schema.Int64) predicate.FieldType { }) } +// SchemaFloat applies equality check predicate on the "schema_float" field. It's identical to SchemaFloatEQ. +func SchemaFloat(v schema.Float64) predicate.FieldType { + vc := float64(v) + return predicate.FieldType(func(t *dsl.Traversal) { + t.Has(Label, FieldSchemaFloat, p.EQ(vc)) + }) +} + +// SchemaFloat32 applies equality check predicate on the "schema_float32" field. It's identical to SchemaFloat32EQ. +func SchemaFloat32(v schema.Float32) predicate.FieldType { + vc := float32(v) + return predicate.FieldType(func(t *dsl.Traversal) { + t.Has(Label, FieldSchemaFloat32, p.EQ(vc)) + }) +} + // IntEQ applies the EQ predicate on the "int" field. func IntEQ(v int) predicate.FieldType { return predicate.FieldType(func(t *dsl.Traversal) { @@ -3479,6 +3495,188 @@ func SchemaInt64NotNil() predicate.FieldType { }) } +// SchemaFloatEQ applies the EQ predicate on the "schema_float" field. +func SchemaFloatEQ(v schema.Float64) predicate.FieldType { + vc := float64(v) + return predicate.FieldType(func(t *dsl.Traversal) { + t.Has(Label, FieldSchemaFloat, p.EQ(vc)) + }) +} + +// SchemaFloatNEQ applies the NEQ predicate on the "schema_float" field. +func SchemaFloatNEQ(v schema.Float64) predicate.FieldType { + vc := float64(v) + return predicate.FieldType(func(t *dsl.Traversal) { + t.Has(Label, FieldSchemaFloat, p.NEQ(vc)) + }) +} + +// SchemaFloatIn applies the In predicate on the "schema_float" field. +func SchemaFloatIn(vs ...schema.Float64) predicate.FieldType { + v := make([]interface{}, len(vs)) + for i := range v { + v[i] = float64(vs[i]) + } + return predicate.FieldType(func(t *dsl.Traversal) { + t.Has(Label, FieldSchemaFloat, p.Within(v...)) + }) +} + +// SchemaFloatNotIn applies the NotIn predicate on the "schema_float" field. +func SchemaFloatNotIn(vs ...schema.Float64) predicate.FieldType { + v := make([]interface{}, len(vs)) + for i := range v { + v[i] = float64(vs[i]) + } + return predicate.FieldType(func(t *dsl.Traversal) { + t.Has(Label, FieldSchemaFloat, p.Without(v...)) + }) +} + +// SchemaFloatGT applies the GT predicate on the "schema_float" field. +func SchemaFloatGT(v schema.Float64) predicate.FieldType { + vc := float64(v) + return predicate.FieldType(func(t *dsl.Traversal) { + t.Has(Label, FieldSchemaFloat, p.GT(vc)) + }) +} + +// SchemaFloatGTE applies the GTE predicate on the "schema_float" field. +func SchemaFloatGTE(v schema.Float64) predicate.FieldType { + vc := float64(v) + return predicate.FieldType(func(t *dsl.Traversal) { + t.Has(Label, FieldSchemaFloat, p.GTE(vc)) + }) +} + +// SchemaFloatLT applies the LT predicate on the "schema_float" field. +func SchemaFloatLT(v schema.Float64) predicate.FieldType { + vc := float64(v) + return predicate.FieldType(func(t *dsl.Traversal) { + t.Has(Label, FieldSchemaFloat, p.LT(vc)) + }) +} + +// SchemaFloatLTE applies the LTE predicate on the "schema_float" field. +func SchemaFloatLTE(v schema.Float64) predicate.FieldType { + vc := float64(v) + return predicate.FieldType(func(t *dsl.Traversal) { + t.Has(Label, FieldSchemaFloat, p.LTE(vc)) + }) +} + +// SchemaFloatIsNil applies the IsNil predicate on the "schema_float" field. +func SchemaFloatIsNil() predicate.FieldType { + return predicate.FieldType(func(t *dsl.Traversal) { + t.HasLabel(Label).HasNot(FieldSchemaFloat) + }) +} + +// SchemaFloatNotNil applies the NotNil predicate on the "schema_float" field. +func SchemaFloatNotNil() predicate.FieldType { + return predicate.FieldType(func(t *dsl.Traversal) { + t.HasLabel(Label).Has(FieldSchemaFloat) + }) +} + +// SchemaFloat32EQ applies the EQ predicate on the "schema_float32" field. +func SchemaFloat32EQ(v schema.Float32) predicate.FieldType { + vc := float32(v) + return predicate.FieldType(func(t *dsl.Traversal) { + t.Has(Label, FieldSchemaFloat32, p.EQ(vc)) + }) +} + +// SchemaFloat32NEQ applies the NEQ predicate on the "schema_float32" field. +func SchemaFloat32NEQ(v schema.Float32) predicate.FieldType { + vc := float32(v) + return predicate.FieldType(func(t *dsl.Traversal) { + t.Has(Label, FieldSchemaFloat32, p.NEQ(vc)) + }) +} + +// SchemaFloat32In applies the In predicate on the "schema_float32" field. +func SchemaFloat32In(vs ...schema.Float32) predicate.FieldType { + v := make([]interface{}, len(vs)) + for i := range v { + v[i] = float32(vs[i]) + } + return predicate.FieldType(func(t *dsl.Traversal) { + t.Has(Label, FieldSchemaFloat32, p.Within(v...)) + }) +} + +// SchemaFloat32NotIn applies the NotIn predicate on the "schema_float32" field. +func SchemaFloat32NotIn(vs ...schema.Float32) predicate.FieldType { + v := make([]interface{}, len(vs)) + for i := range v { + v[i] = float32(vs[i]) + } + return predicate.FieldType(func(t *dsl.Traversal) { + t.Has(Label, FieldSchemaFloat32, p.Without(v...)) + }) +} + +// SchemaFloat32GT applies the GT predicate on the "schema_float32" field. +func SchemaFloat32GT(v schema.Float32) predicate.FieldType { + vc := float32(v) + return predicate.FieldType(func(t *dsl.Traversal) { + t.Has(Label, FieldSchemaFloat32, p.GT(vc)) + }) +} + +// SchemaFloat32GTE applies the GTE predicate on the "schema_float32" field. +func SchemaFloat32GTE(v schema.Float32) predicate.FieldType { + vc := float32(v) + return predicate.FieldType(func(t *dsl.Traversal) { + t.Has(Label, FieldSchemaFloat32, p.GTE(vc)) + }) +} + +// SchemaFloat32LT applies the LT predicate on the "schema_float32" field. +func SchemaFloat32LT(v schema.Float32) predicate.FieldType { + vc := float32(v) + return predicate.FieldType(func(t *dsl.Traversal) { + t.Has(Label, FieldSchemaFloat32, p.LT(vc)) + }) +} + +// SchemaFloat32LTE applies the LTE predicate on the "schema_float32" field. +func SchemaFloat32LTE(v schema.Float32) predicate.FieldType { + vc := float32(v) + return predicate.FieldType(func(t *dsl.Traversal) { + t.Has(Label, FieldSchemaFloat32, p.LTE(vc)) + }) +} + +// SchemaFloat32IsNil applies the IsNil predicate on the "schema_float32" field. +func SchemaFloat32IsNil() predicate.FieldType { + return predicate.FieldType(func(t *dsl.Traversal) { + t.HasLabel(Label).HasNot(FieldSchemaFloat32) + }) +} + +// SchemaFloat32NotNil applies the NotNil predicate on the "schema_float32" field. +func SchemaFloat32NotNil() predicate.FieldType { + return predicate.FieldType(func(t *dsl.Traversal) { + t.HasLabel(Label).Has(FieldSchemaFloat32) + }) +} + +// NullFloatIsNil applies the IsNil predicate on the "null_float" field. +func NullFloatIsNil() predicate.FieldType { + return predicate.FieldType(func(t *dsl.Traversal) { + t.HasLabel(Label).HasNot(FieldNullFloat) + }) +} + +// NullFloatNotNil applies the NotNil predicate on the "null_float" field. +func NullFloatNotNil() predicate.FieldType { + return predicate.FieldType(func(t *dsl.Traversal) { + t.HasLabel(Label).Has(FieldNullFloat) + }) +} + // And groups list of predicates with the AND operator between them. func And(predicates ...predicate.FieldType) predicate.FieldType { return predicate.FieldType(func(tr *dsl.Traversal) { diff --git a/entc/integration/gremlin/ent/fieldtype_create.go b/entc/integration/gremlin/ent/fieldtype_create.go index c122f3d41..4bebeaf61 100644 --- a/entc/integration/gremlin/ent/fieldtype_create.go +++ b/entc/integration/gremlin/ent/fieldtype_create.go @@ -499,6 +499,40 @@ func (ftc *FieldTypeCreate) SetNillableSchemaInt64(s *schema.Int64) *FieldTypeCr return ftc } +// SetSchemaFloat sets the schema_float field. +func (ftc *FieldTypeCreate) SetSchemaFloat(s schema.Float64) *FieldTypeCreate { + ftc.mutation.SetSchemaFloat(s) + return ftc +} + +// SetNillableSchemaFloat sets the schema_float field if the given value is not nil. +func (ftc *FieldTypeCreate) SetNillableSchemaFloat(s *schema.Float64) *FieldTypeCreate { + if s != nil { + ftc.SetSchemaFloat(*s) + } + return ftc +} + +// SetSchemaFloat32 sets the schema_float32 field. +func (ftc *FieldTypeCreate) SetSchemaFloat32(s schema.Float32) *FieldTypeCreate { + ftc.mutation.SetSchemaFloat32(s) + return ftc +} + +// SetNillableSchemaFloat32 sets the schema_float32 field if the given value is not nil. +func (ftc *FieldTypeCreate) SetNillableSchemaFloat32(s *schema.Float32) *FieldTypeCreate { + if s != nil { + ftc.SetSchemaFloat32(*s) + } + return ftc +} + +// SetNullFloat sets the null_float field. +func (ftc *FieldTypeCreate) SetNullFloat(sf sql.NullFloat64) *FieldTypeCreate { + ftc.mutation.SetNullFloat(sf) + return ftc +} + // Mutation returns the FieldTypeMutation object of the builder. func (ftc *FieldTypeCreate) Mutation() *FieldTypeMutation { return ftc.mutation @@ -708,5 +742,14 @@ func (ftc *FieldTypeCreate) gremlin() *dsl.Traversal { if value, ok := ftc.mutation.SchemaInt64(); ok { v.Property(dsl.Single, fieldtype.FieldSchemaInt64, value) } + if value, ok := ftc.mutation.SchemaFloat(); ok { + v.Property(dsl.Single, fieldtype.FieldSchemaFloat, value) + } + if value, ok := ftc.mutation.SchemaFloat32(); ok { + v.Property(dsl.Single, fieldtype.FieldSchemaFloat32, value) + } + if value, ok := ftc.mutation.NullFloat(); ok { + v.Property(dsl.Single, fieldtype.FieldNullFloat, value) + } return v.ValueMap(true) } diff --git a/entc/integration/gremlin/ent/fieldtype_update.go b/entc/integration/gremlin/ent/fieldtype_update.go index d10b5296d..1a866ed81 100644 --- a/entc/integration/gremlin/ent/fieldtype_update.go +++ b/entc/integration/gremlin/ent/fieldtype_update.go @@ -913,6 +913,73 @@ func (ftu *FieldTypeUpdate) ClearSchemaInt64() *FieldTypeUpdate { return ftu } +// SetSchemaFloat sets the schema_float field. +func (ftu *FieldTypeUpdate) SetSchemaFloat(s schema.Float64) *FieldTypeUpdate { + ftu.mutation.ResetSchemaFloat() + ftu.mutation.SetSchemaFloat(s) + return ftu +} + +// SetNillableSchemaFloat sets the schema_float field if the given value is not nil. +func (ftu *FieldTypeUpdate) SetNillableSchemaFloat(s *schema.Float64) *FieldTypeUpdate { + if s != nil { + ftu.SetSchemaFloat(*s) + } + return ftu +} + +// AddSchemaFloat adds s to schema_float. +func (ftu *FieldTypeUpdate) AddSchemaFloat(s schema.Float64) *FieldTypeUpdate { + ftu.mutation.AddSchemaFloat(s) + return ftu +} + +// ClearSchemaFloat clears the value of schema_float. +func (ftu *FieldTypeUpdate) ClearSchemaFloat() *FieldTypeUpdate { + ftu.mutation.ClearSchemaFloat() + return ftu +} + +// SetSchemaFloat32 sets the schema_float32 field. +func (ftu *FieldTypeUpdate) SetSchemaFloat32(s schema.Float32) *FieldTypeUpdate { + ftu.mutation.ResetSchemaFloat32() + ftu.mutation.SetSchemaFloat32(s) + return ftu +} + +// SetNillableSchemaFloat32 sets the schema_float32 field if the given value is not nil. +func (ftu *FieldTypeUpdate) SetNillableSchemaFloat32(s *schema.Float32) *FieldTypeUpdate { + if s != nil { + ftu.SetSchemaFloat32(*s) + } + return ftu +} + +// AddSchemaFloat32 adds s to schema_float32. +func (ftu *FieldTypeUpdate) AddSchemaFloat32(s schema.Float32) *FieldTypeUpdate { + ftu.mutation.AddSchemaFloat32(s) + return ftu +} + +// ClearSchemaFloat32 clears the value of schema_float32. +func (ftu *FieldTypeUpdate) ClearSchemaFloat32() *FieldTypeUpdate { + ftu.mutation.ClearSchemaFloat32() + return ftu +} + +// SetNullFloat sets the null_float field. +func (ftu *FieldTypeUpdate) SetNullFloat(sf sql.NullFloat64) *FieldTypeUpdate { + ftu.mutation.ResetNullFloat() + ftu.mutation.SetNullFloat(sf) + return ftu +} + +// ClearNullFloat clears the value of null_float. +func (ftu *FieldTypeUpdate) ClearNullFloat() *FieldTypeUpdate { + ftu.mutation.ClearNullFloat() + return ftu +} + // Mutation returns the FieldTypeMutation object of the builder. func (ftu *FieldTypeUpdate) Mutation() *FieldTypeMutation { return ftu.mutation @@ -1203,6 +1270,21 @@ func (ftu *FieldTypeUpdate) gremlin() *dsl.Traversal { if value, ok := ftu.mutation.AddedSchemaInt64(); ok { v.Property(dsl.Single, fieldtype.FieldSchemaInt64, __.Union(__.Values(fieldtype.FieldSchemaInt64), __.Constant(value)).Sum()) } + if value, ok := ftu.mutation.SchemaFloat(); ok { + v.Property(dsl.Single, fieldtype.FieldSchemaFloat, value) + } + if value, ok := ftu.mutation.AddedSchemaFloat(); ok { + v.Property(dsl.Single, fieldtype.FieldSchemaFloat, __.Union(__.Values(fieldtype.FieldSchemaFloat), __.Constant(value)).Sum()) + } + if value, ok := ftu.mutation.SchemaFloat32(); ok { + v.Property(dsl.Single, fieldtype.FieldSchemaFloat32, value) + } + if value, ok := ftu.mutation.AddedSchemaFloat32(); ok { + v.Property(dsl.Single, fieldtype.FieldSchemaFloat32, __.Union(__.Values(fieldtype.FieldSchemaFloat32), __.Constant(value)).Sum()) + } + if value, ok := ftu.mutation.NullFloat(); ok { + v.Property(dsl.Single, fieldtype.FieldNullFloat, value) + } var properties []interface{} if ftu.mutation.OptionalIntCleared() { properties = append(properties, fieldtype.FieldOptionalInt) @@ -1312,6 +1394,15 @@ func (ftu *FieldTypeUpdate) gremlin() *dsl.Traversal { if ftu.mutation.SchemaInt64Cleared() { properties = append(properties, fieldtype.FieldSchemaInt64) } + if ftu.mutation.SchemaFloatCleared() { + properties = append(properties, fieldtype.FieldSchemaFloat) + } + if ftu.mutation.SchemaFloat32Cleared() { + properties = append(properties, fieldtype.FieldSchemaFloat32) + } + if ftu.mutation.NullFloatCleared() { + properties = append(properties, fieldtype.FieldNullFloat) + } if len(properties) > 0 { v.SideEffect(__.Properties(properties...).Drop()) } @@ -2203,6 +2294,73 @@ func (ftuo *FieldTypeUpdateOne) ClearSchemaInt64() *FieldTypeUpdateOne { return ftuo } +// SetSchemaFloat sets the schema_float field. +func (ftuo *FieldTypeUpdateOne) SetSchemaFloat(s schema.Float64) *FieldTypeUpdateOne { + ftuo.mutation.ResetSchemaFloat() + ftuo.mutation.SetSchemaFloat(s) + return ftuo +} + +// SetNillableSchemaFloat sets the schema_float field if the given value is not nil. +func (ftuo *FieldTypeUpdateOne) SetNillableSchemaFloat(s *schema.Float64) *FieldTypeUpdateOne { + if s != nil { + ftuo.SetSchemaFloat(*s) + } + return ftuo +} + +// AddSchemaFloat adds s to schema_float. +func (ftuo *FieldTypeUpdateOne) AddSchemaFloat(s schema.Float64) *FieldTypeUpdateOne { + ftuo.mutation.AddSchemaFloat(s) + return ftuo +} + +// ClearSchemaFloat clears the value of schema_float. +func (ftuo *FieldTypeUpdateOne) ClearSchemaFloat() *FieldTypeUpdateOne { + ftuo.mutation.ClearSchemaFloat() + return ftuo +} + +// SetSchemaFloat32 sets the schema_float32 field. +func (ftuo *FieldTypeUpdateOne) SetSchemaFloat32(s schema.Float32) *FieldTypeUpdateOne { + ftuo.mutation.ResetSchemaFloat32() + ftuo.mutation.SetSchemaFloat32(s) + return ftuo +} + +// SetNillableSchemaFloat32 sets the schema_float32 field if the given value is not nil. +func (ftuo *FieldTypeUpdateOne) SetNillableSchemaFloat32(s *schema.Float32) *FieldTypeUpdateOne { + if s != nil { + ftuo.SetSchemaFloat32(*s) + } + return ftuo +} + +// AddSchemaFloat32 adds s to schema_float32. +func (ftuo *FieldTypeUpdateOne) AddSchemaFloat32(s schema.Float32) *FieldTypeUpdateOne { + ftuo.mutation.AddSchemaFloat32(s) + return ftuo +} + +// ClearSchemaFloat32 clears the value of schema_float32. +func (ftuo *FieldTypeUpdateOne) ClearSchemaFloat32() *FieldTypeUpdateOne { + ftuo.mutation.ClearSchemaFloat32() + return ftuo +} + +// SetNullFloat sets the null_float field. +func (ftuo *FieldTypeUpdateOne) SetNullFloat(sf sql.NullFloat64) *FieldTypeUpdateOne { + ftuo.mutation.ResetNullFloat() + ftuo.mutation.SetNullFloat(sf) + return ftuo +} + +// ClearNullFloat clears the value of null_float. +func (ftuo *FieldTypeUpdateOne) ClearNullFloat() *FieldTypeUpdateOne { + ftuo.mutation.ClearNullFloat() + return ftuo +} + // Mutation returns the FieldTypeMutation object of the builder. func (ftuo *FieldTypeUpdateOne) Mutation() *FieldTypeMutation { return ftuo.mutation @@ -2498,6 +2656,21 @@ func (ftuo *FieldTypeUpdateOne) gremlin(id string) *dsl.Traversal { if value, ok := ftuo.mutation.AddedSchemaInt64(); ok { v.Property(dsl.Single, fieldtype.FieldSchemaInt64, __.Union(__.Values(fieldtype.FieldSchemaInt64), __.Constant(value)).Sum()) } + if value, ok := ftuo.mutation.SchemaFloat(); ok { + v.Property(dsl.Single, fieldtype.FieldSchemaFloat, value) + } + if value, ok := ftuo.mutation.AddedSchemaFloat(); ok { + v.Property(dsl.Single, fieldtype.FieldSchemaFloat, __.Union(__.Values(fieldtype.FieldSchemaFloat), __.Constant(value)).Sum()) + } + if value, ok := ftuo.mutation.SchemaFloat32(); ok { + v.Property(dsl.Single, fieldtype.FieldSchemaFloat32, value) + } + if value, ok := ftuo.mutation.AddedSchemaFloat32(); ok { + v.Property(dsl.Single, fieldtype.FieldSchemaFloat32, __.Union(__.Values(fieldtype.FieldSchemaFloat32), __.Constant(value)).Sum()) + } + if value, ok := ftuo.mutation.NullFloat(); ok { + v.Property(dsl.Single, fieldtype.FieldNullFloat, value) + } var properties []interface{} if ftuo.mutation.OptionalIntCleared() { properties = append(properties, fieldtype.FieldOptionalInt) @@ -2607,6 +2780,15 @@ func (ftuo *FieldTypeUpdateOne) gremlin(id string) *dsl.Traversal { if ftuo.mutation.SchemaInt64Cleared() { properties = append(properties, fieldtype.FieldSchemaInt64) } + if ftuo.mutation.SchemaFloatCleared() { + properties = append(properties, fieldtype.FieldSchemaFloat) + } + if ftuo.mutation.SchemaFloat32Cleared() { + properties = append(properties, fieldtype.FieldSchemaFloat32) + } + if ftuo.mutation.NullFloatCleared() { + properties = append(properties, fieldtype.FieldNullFloat) + } if len(properties) > 0 { v.SideEffect(__.Properties(properties...).Drop()) } diff --git a/entc/integration/gremlin/ent/mutation.go b/entc/integration/gremlin/ent/mutation.go index d9411bd3f..e8dcd0a45 100644 --- a/entc/integration/gremlin/ent/mutation.go +++ b/entc/integration/gremlin/ent/mutation.go @@ -1271,6 +1271,11 @@ type FieldTypeMutation struct { addschema_int8 *schema.Int8 schema_int64 *schema.Int64 addschema_int64 *schema.Int64 + schema_float *schema.Float64 + addschema_float *schema.Float64 + schema_float32 *schema.Float32 + addschema_float32 *schema.Float32 + null_float *sql.NullFloat64 clearedFields map[string]struct{} done bool oldValue func(context.Context) (*FieldType, error) @@ -3902,6 +3907,198 @@ func (m *FieldTypeMutation) ResetSchemaInt64() { delete(m.clearedFields, fieldtype.FieldSchemaInt64) } +// SetSchemaFloat sets the schema_float field. +func (m *FieldTypeMutation) SetSchemaFloat(s schema.Float64) { + m.schema_float = &s + m.addschema_float = nil +} + +// SchemaFloat returns the schema_float value in the mutation. +func (m *FieldTypeMutation) SchemaFloat() (r schema.Float64, exists bool) { + v := m.schema_float + if v == nil { + return + } + return *v, true +} + +// OldSchemaFloat returns the old schema_float value of the FieldType. +// If the FieldType object wasn't provided to the builder, the object is fetched +// from the database. +// An error is returned if the mutation operation is not UpdateOne, or database query fails. +func (m *FieldTypeMutation) OldSchemaFloat(ctx context.Context) (v schema.Float64, err error) { + if !m.op.Is(OpUpdateOne) { + return v, fmt.Errorf("OldSchemaFloat is allowed only on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, fmt.Errorf("OldSchemaFloat requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldSchemaFloat: %w", err) + } + return oldValue.SchemaFloat, nil +} + +// AddSchemaFloat adds s to schema_float. +func (m *FieldTypeMutation) AddSchemaFloat(s schema.Float64) { + if m.addschema_float != nil { + *m.addschema_float += s + } else { + m.addschema_float = &s + } +} + +// AddedSchemaFloat returns the value that was added to the schema_float field in this mutation. +func (m *FieldTypeMutation) AddedSchemaFloat() (r schema.Float64, exists bool) { + v := m.addschema_float + if v == nil { + return + } + return *v, true +} + +// ClearSchemaFloat clears the value of schema_float. +func (m *FieldTypeMutation) ClearSchemaFloat() { + m.schema_float = nil + m.addschema_float = nil + m.clearedFields[fieldtype.FieldSchemaFloat] = struct{}{} +} + +// SchemaFloatCleared returns if the field schema_float was cleared in this mutation. +func (m *FieldTypeMutation) SchemaFloatCleared() bool { + _, ok := m.clearedFields[fieldtype.FieldSchemaFloat] + return ok +} + +// ResetSchemaFloat reset all changes of the "schema_float" field. +func (m *FieldTypeMutation) ResetSchemaFloat() { + m.schema_float = nil + m.addschema_float = nil + delete(m.clearedFields, fieldtype.FieldSchemaFloat) +} + +// SetSchemaFloat32 sets the schema_float32 field. +func (m *FieldTypeMutation) SetSchemaFloat32(s schema.Float32) { + m.schema_float32 = &s + m.addschema_float32 = nil +} + +// SchemaFloat32 returns the schema_float32 value in the mutation. +func (m *FieldTypeMutation) SchemaFloat32() (r schema.Float32, exists bool) { + v := m.schema_float32 + if v == nil { + return + } + return *v, true +} + +// OldSchemaFloat32 returns the old schema_float32 value of the FieldType. +// If the FieldType object wasn't provided to the builder, the object is fetched +// from the database. +// An error is returned if the mutation operation is not UpdateOne, or database query fails. +func (m *FieldTypeMutation) OldSchemaFloat32(ctx context.Context) (v schema.Float32, err error) { + if !m.op.Is(OpUpdateOne) { + return v, fmt.Errorf("OldSchemaFloat32 is allowed only on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, fmt.Errorf("OldSchemaFloat32 requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldSchemaFloat32: %w", err) + } + return oldValue.SchemaFloat32, nil +} + +// AddSchemaFloat32 adds s to schema_float32. +func (m *FieldTypeMutation) AddSchemaFloat32(s schema.Float32) { + if m.addschema_float32 != nil { + *m.addschema_float32 += s + } else { + m.addschema_float32 = &s + } +} + +// AddedSchemaFloat32 returns the value that was added to the schema_float32 field in this mutation. +func (m *FieldTypeMutation) AddedSchemaFloat32() (r schema.Float32, exists bool) { + v := m.addschema_float32 + if v == nil { + return + } + return *v, true +} + +// ClearSchemaFloat32 clears the value of schema_float32. +func (m *FieldTypeMutation) ClearSchemaFloat32() { + m.schema_float32 = nil + m.addschema_float32 = nil + m.clearedFields[fieldtype.FieldSchemaFloat32] = struct{}{} +} + +// SchemaFloat32Cleared returns if the field schema_float32 was cleared in this mutation. +func (m *FieldTypeMutation) SchemaFloat32Cleared() bool { + _, ok := m.clearedFields[fieldtype.FieldSchemaFloat32] + return ok +} + +// ResetSchemaFloat32 reset all changes of the "schema_float32" field. +func (m *FieldTypeMutation) ResetSchemaFloat32() { + m.schema_float32 = nil + m.addschema_float32 = nil + delete(m.clearedFields, fieldtype.FieldSchemaFloat32) +} + +// SetNullFloat sets the null_float field. +func (m *FieldTypeMutation) SetNullFloat(sf sql.NullFloat64) { + m.null_float = &sf +} + +// NullFloat returns the null_float value in the mutation. +func (m *FieldTypeMutation) NullFloat() (r sql.NullFloat64, exists bool) { + v := m.null_float + if v == nil { + return + } + return *v, true +} + +// OldNullFloat returns the old null_float value of the FieldType. +// If the FieldType object wasn't provided to the builder, the object is fetched +// from the database. +// An error is returned if the mutation operation is not UpdateOne, or database query fails. +func (m *FieldTypeMutation) OldNullFloat(ctx context.Context) (v sql.NullFloat64, err error) { + if !m.op.Is(OpUpdateOne) { + return v, fmt.Errorf("OldNullFloat is allowed only on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, fmt.Errorf("OldNullFloat requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldNullFloat: %w", err) + } + return oldValue.NullFloat, nil +} + +// ClearNullFloat clears the value of null_float. +func (m *FieldTypeMutation) ClearNullFloat() { + m.null_float = nil + m.clearedFields[fieldtype.FieldNullFloat] = struct{}{} +} + +// NullFloatCleared returns if the field null_float was cleared in this mutation. +func (m *FieldTypeMutation) NullFloatCleared() bool { + _, ok := m.clearedFields[fieldtype.FieldNullFloat] + return ok +} + +// ResetNullFloat reset all changes of the "null_float" field. +func (m *FieldTypeMutation) ResetNullFloat() { + m.null_float = nil + delete(m.clearedFields, fieldtype.FieldNullFloat) +} + // Op returns the operation name. func (m *FieldTypeMutation) Op() Op { return m.op @@ -3916,7 +4113,7 @@ func (m *FieldTypeMutation) Type() string { // this mutation. Note that, in order to get all numeric // fields that were in/decremented, call AddedFields(). func (m *FieldTypeMutation) Fields() []string { - fields := make([]string, 0, 41) + fields := make([]string, 0, 44) if m.int != nil { fields = append(fields, fieldtype.FieldInt) } @@ -4040,6 +4237,15 @@ func (m *FieldTypeMutation) Fields() []string { if m.schema_int64 != nil { fields = append(fields, fieldtype.FieldSchemaInt64) } + if m.schema_float != nil { + fields = append(fields, fieldtype.FieldSchemaFloat) + } + if m.schema_float32 != nil { + fields = append(fields, fieldtype.FieldSchemaFloat32) + } + if m.null_float != nil { + fields = append(fields, fieldtype.FieldNullFloat) + } return fields } @@ -4130,6 +4336,12 @@ func (m *FieldTypeMutation) Field(name string) (ent.Value, bool) { return m.SchemaInt8() case fieldtype.FieldSchemaInt64: return m.SchemaInt64() + case fieldtype.FieldSchemaFloat: + return m.SchemaFloat() + case fieldtype.FieldSchemaFloat32: + return m.SchemaFloat32() + case fieldtype.FieldNullFloat: + return m.NullFloat() } return nil, false } @@ -4221,6 +4433,12 @@ func (m *FieldTypeMutation) OldField(ctx context.Context, name string) (ent.Valu return m.OldSchemaInt8(ctx) case fieldtype.FieldSchemaInt64: return m.OldSchemaInt64(ctx) + case fieldtype.FieldSchemaFloat: + return m.OldSchemaFloat(ctx) + case fieldtype.FieldSchemaFloat32: + return m.OldSchemaFloat32(ctx) + case fieldtype.FieldNullFloat: + return m.OldNullFloat(ctx) } return nil, fmt.Errorf("unknown FieldType field %s", name) } @@ -4517,6 +4735,27 @@ func (m *FieldTypeMutation) SetField(name string, value ent.Value) error { } m.SetSchemaInt64(v) return nil + case fieldtype.FieldSchemaFloat: + v, ok := value.(schema.Float64) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetSchemaFloat(v) + return nil + case fieldtype.FieldSchemaFloat32: + v, ok := value.(schema.Float32) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetSchemaFloat32(v) + return nil + case fieldtype.FieldNullFloat: + v, ok := value.(sql.NullFloat64) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetNullFloat(v) + return nil } return fmt.Errorf("unknown FieldType field %s", name) } @@ -4606,6 +4845,12 @@ func (m *FieldTypeMutation) AddedFields() []string { if m.addschema_int64 != nil { fields = append(fields, fieldtype.FieldSchemaInt64) } + if m.addschema_float != nil { + fields = append(fields, fieldtype.FieldSchemaFloat) + } + if m.addschema_float32 != nil { + fields = append(fields, fieldtype.FieldSchemaFloat32) + } return fields } @@ -4668,6 +4913,10 @@ func (m *FieldTypeMutation) AddedField(name string) (ent.Value, bool) { return m.AddedSchemaInt8() case fieldtype.FieldSchemaInt64: return m.AddedSchemaInt64() + case fieldtype.FieldSchemaFloat: + return m.AddedSchemaFloat() + case fieldtype.FieldSchemaFloat32: + return m.AddedSchemaFloat32() } return nil, false } @@ -4866,6 +5115,20 @@ func (m *FieldTypeMutation) AddField(name string, value ent.Value) error { } m.AddSchemaInt64(v) return nil + case fieldtype.FieldSchemaFloat: + v, ok := value.(schema.Float64) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.AddSchemaFloat(v) + return nil + case fieldtype.FieldSchemaFloat32: + v, ok := value.(schema.Float32) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.AddSchemaFloat32(v) + return nil } return fmt.Errorf("unknown FieldType numeric field %s", name) } @@ -4982,6 +5245,15 @@ func (m *FieldTypeMutation) ClearedFields() []string { if m.FieldCleared(fieldtype.FieldSchemaInt64) { fields = append(fields, fieldtype.FieldSchemaInt64) } + if m.FieldCleared(fieldtype.FieldSchemaFloat) { + fields = append(fields, fieldtype.FieldSchemaFloat) + } + if m.FieldCleared(fieldtype.FieldSchemaFloat32) { + fields = append(fields, fieldtype.FieldSchemaFloat32) + } + if m.FieldCleared(fieldtype.FieldNullFloat) { + fields = append(fields, fieldtype.FieldNullFloat) + } return fields } @@ -5104,6 +5376,15 @@ func (m *FieldTypeMutation) ClearField(name string) error { case fieldtype.FieldSchemaInt64: m.ClearSchemaInt64() return nil + case fieldtype.FieldSchemaFloat: + m.ClearSchemaFloat() + return nil + case fieldtype.FieldSchemaFloat32: + m.ClearSchemaFloat32() + return nil + case fieldtype.FieldNullFloat: + m.ClearNullFloat() + return nil } return fmt.Errorf("unknown FieldType nullable field %s", name) } @@ -5236,6 +5517,15 @@ func (m *FieldTypeMutation) ResetField(name string) error { case fieldtype.FieldSchemaInt64: m.ResetSchemaInt64() return nil + case fieldtype.FieldSchemaFloat: + m.ResetSchemaFloat() + return nil + case fieldtype.FieldSchemaFloat32: + m.ResetSchemaFloat32() + return nil + case fieldtype.FieldNullFloat: + m.ResetNullFloat() + return nil } return fmt.Errorf("unknown FieldType field %s", name) } diff --git a/entc/integration/migrate/entv2/client.go b/entc/integration/migrate/entv2/client.go index 449bde927..411be50a2 100644 --- a/entc/integration/migrate/entv2/client.go +++ b/entc/integration/migrate/entv2/client.go @@ -515,6 +515,22 @@ func (c *UserClient) QueryPets(u *User) *PetQuery { return query } +// QueryFriends queries the friends edge of a User. +func (c *UserClient) QueryFriends(u *User) *UserQuery { + query := &UserQuery{config: c.config} + query.path = func(ctx context.Context) (fromV *sql.Selector, _ error) { + id := u.ID + step := sqlgraph.NewStep( + sqlgraph.From(user.Table, user.FieldID, id), + sqlgraph.To(user.Table, user.FieldID), + sqlgraph.Edge(sqlgraph.M2M, false, user.FriendsTable, user.FriendsPrimaryKey...), + ) + fromV = sqlgraph.Neighbors(u.driver.Dialect(), step) + return fromV, nil + } + return query +} + // Hooks returns the client hooks. func (c *UserClient) Hooks() []Hook { return c.hooks.User diff --git a/entc/integration/migrate/entv2/migrate/schema.go b/entc/integration/migrate/entv2/migrate/schema.go index 2ce35522f..5ec3cd7c4 100644 --- a/entc/integration/migrate/entv2/migrate/schema.go +++ b/entc/integration/migrate/entv2/migrate/schema.go @@ -66,7 +66,7 @@ var ( {Name: "renamed", Type: field.TypeString, Nullable: true}, {Name: "blob", Type: field.TypeBytes, Nullable: true, Size: 1000}, {Name: "state", Type: field.TypeEnum, Nullable: true, Enums: []string{"logged_in", "logged_out", "online"}}, - {Name: "user_pets", Type: field.TypeInt, Nullable: true}, + {Name: "owner_id", Type: field.TypeInt, Nullable: true}, } // UsersTable holds the schema information for the "users" table. UsersTable = &schema.Table{ @@ -90,16 +90,46 @@ var ( }, }, } + // FriendsColumns holds the columns for the "friends" table. + FriendsColumns = []*schema.Column{ + {Name: "user", Type: field.TypeInt}, + {Name: "friend", Type: field.TypeInt}, + } + // FriendsTable holds the schema information for the "friends" table. + FriendsTable = &schema.Table{ + Name: "friends", + Columns: FriendsColumns, + PrimaryKey: []*schema.Column{FriendsColumns[0], FriendsColumns[1]}, + ForeignKeys: []*schema.ForeignKey{ + { + Symbol: "friends_user", + Columns: []*schema.Column{FriendsColumns[0]}, + + RefColumns: []*schema.Column{UsersColumns[0]}, + OnDelete: schema.Cascade, + }, + { + Symbol: "friends_friend", + Columns: []*schema.Column{FriendsColumns[1]}, + + RefColumns: []*schema.Column{UsersColumns[0]}, + OnDelete: schema.Cascade, + }, + }, + } // Tables holds all the tables in the schema. Tables = []*schema.Table{ CarsTable, GroupsTable, PetsTable, UsersTable, + FriendsTable, } ) func init() { CarsTable.ForeignKeys[0].RefTable = UsersTable UsersTable.ForeignKeys[0].RefTable = PetsTable + FriendsTable.ForeignKeys[0].RefTable = UsersTable + FriendsTable.ForeignKeys[1].RefTable = UsersTable } diff --git a/entc/integration/migrate/entv2/mutation.go b/entc/integration/migrate/entv2/mutation.go index 6779e2a48..85fecc5ae 100644 --- a/entc/integration/migrate/entv2/mutation.go +++ b/entc/integration/migrate/entv2/mutation.go @@ -795,26 +795,28 @@ func (m *PetMutation) ResetEdge(name string) error { // nodes in the graph. type UserMutation struct { config - op Op - typ string - id *int - age *int - addage *int - name *string - nickname *string - phone *string - buffer *[]byte - title *string - new_name *string - blob *[]byte - state *user.State - clearedFields map[string]struct{} - car map[int]struct{} - removedcar map[int]struct{} - pets *int - clearedpets bool - done bool - oldValue func(context.Context) (*User, error) + op Op + typ string + id *int + age *int + addage *int + name *string + nickname *string + phone *string + buffer *[]byte + title *string + new_name *string + blob *[]byte + state *user.State + clearedFields map[string]struct{} + car map[int]struct{} + removedcar map[int]struct{} + pets *int + clearedpets bool + friends map[int]struct{} + removedfriends map[int]struct{} + done bool + oldValue func(context.Context) (*User, error) } var _ ent.Mutation = (*UserMutation)(nil) @@ -1388,6 +1390,48 @@ func (m *UserMutation) ResetPets() { m.clearedpets = false } +// AddFriendIDs adds the friends edge to User by ids. +func (m *UserMutation) AddFriendIDs(ids ...int) { + if m.friends == nil { + m.friends = make(map[int]struct{}) + } + for i := range ids { + m.friends[ids[i]] = struct{}{} + } +} + +// RemoveFriendIDs removes the friends edge to User by ids. +func (m *UserMutation) RemoveFriendIDs(ids ...int) { + if m.removedfriends == nil { + m.removedfriends = make(map[int]struct{}) + } + for i := range ids { + m.removedfriends[ids[i]] = struct{}{} + } +} + +// RemovedFriends returns the removed ids of friends. +func (m *UserMutation) RemovedFriendsIDs() (ids []int) { + for id := range m.removedfriends { + ids = append(ids, id) + } + return +} + +// FriendsIDs returns the friends ids in the mutation. +func (m *UserMutation) FriendsIDs() (ids []int) { + for id := range m.friends { + ids = append(ids, id) + } + return +} + +// ResetFriends reset all changes of the "friends" edge. +func (m *UserMutation) ResetFriends() { + m.friends = nil + m.removedfriends = nil +} + // Op returns the operation name. func (m *UserMutation) Op() Op { return m.op @@ -1681,13 +1725,16 @@ func (m *UserMutation) ResetField(name string) error { // AddedEdges returns all edge names that were set/added in this // mutation. func (m *UserMutation) AddedEdges() []string { - edges := make([]string, 0, 2) + edges := make([]string, 0, 3) if m.car != nil { edges = append(edges, user.EdgeCar) } if m.pets != nil { edges = append(edges, user.EdgePets) } + if m.friends != nil { + edges = append(edges, user.EdgeFriends) + } return edges } @@ -1705,6 +1752,12 @@ func (m *UserMutation) AddedIDs(name string) []ent.Value { if id := m.pets; id != nil { return []ent.Value{*id} } + case user.EdgeFriends: + ids := make([]ent.Value, 0, len(m.friends)) + for id := range m.friends { + ids = append(ids, id) + } + return ids } return nil } @@ -1712,10 +1765,13 @@ func (m *UserMutation) AddedIDs(name string) []ent.Value { // RemovedEdges returns all edge names that were removed in this // mutation. func (m *UserMutation) RemovedEdges() []string { - edges := make([]string, 0, 2) + edges := make([]string, 0, 3) if m.removedcar != nil { edges = append(edges, user.EdgeCar) } + if m.removedfriends != nil { + edges = append(edges, user.EdgeFriends) + } return edges } @@ -1729,6 +1785,12 @@ func (m *UserMutation) RemovedIDs(name string) []ent.Value { ids = append(ids, id) } return ids + case user.EdgeFriends: + ids := make([]ent.Value, 0, len(m.removedfriends)) + for id := range m.removedfriends { + ids = append(ids, id) + } + return ids } return nil } @@ -1736,7 +1798,7 @@ func (m *UserMutation) RemovedIDs(name string) []ent.Value { // ClearedEdges returns all edge names that were cleared in this // mutation. func (m *UserMutation) ClearedEdges() []string { - edges := make([]string, 0, 2) + edges := make([]string, 0, 3) if m.clearedpets { edges = append(edges, user.EdgePets) } @@ -1775,6 +1837,9 @@ func (m *UserMutation) ResetEdge(name string) error { case user.EdgePets: m.ResetPets() return nil + case user.EdgeFriends: + m.ResetFriends() + return nil } return fmt.Errorf("unknown User edge %s", name) } diff --git a/entc/integration/migrate/entv2/schema/user.go b/entc/integration/migrate/entv2/schema/user.go index 33edd3cdf..738a2787f 100644 --- a/entc/integration/migrate/entv2/schema/user.go +++ b/entc/integration/migrate/entv2/schema/user.go @@ -59,9 +59,12 @@ func (User) Edges() []ent.Edge { // Edge(children<-M2O->parent) to be dropped. // Edge(spouse<-O2O->spouse) to be dropped. edge.To("car", Car.Type), - // A new edge was added. + // New edges to added. edge.To("pets", Pet.Type). + StorageKey(edge.Column("owner_id")). Unique(), + edge.To("friends", User.Type). + StorageKey(edge.Table("friends"), edge.Columns("user", "friend")), } } diff --git a/entc/integration/migrate/entv2/user.go b/entc/integration/migrate/entv2/user.go index 202562825..10a52f5ad 100644 --- a/entc/integration/migrate/entv2/user.go +++ b/entc/integration/migrate/entv2/user.go @@ -40,8 +40,8 @@ type User struct { State user.State `json:"state,omitempty"` // Edges holds the relations/edges for other nodes in the graph. // The values are being populated by the UserQuery when eager-loading is set. - Edges UserEdges `json:"edges"` - user_pets *int + Edges UserEdges `json:"edges"` + owner_id *int } // UserEdges holds the relations/edges for other nodes in the graph. @@ -50,9 +50,11 @@ type UserEdges struct { Car []*Car // Pets holds the value of the pets edge. Pets *Pet + // Friends holds the value of the friends edge. + Friends []*User // loadedTypes holds the information for reporting if a // type was loaded (or requested) in eager-loading or not. - loadedTypes [2]bool + loadedTypes [3]bool } // CarOrErr returns the Car value or an error if the edge @@ -78,6 +80,15 @@ func (e UserEdges) PetsOrErr() (*Pet, error) { return nil, &NotLoadedError{edge: "pets"} } +// FriendsOrErr returns the Friends value or an error if the edge +// was not loaded in eager-loading. +func (e UserEdges) FriendsOrErr() ([]*User, error) { + if e.loadedTypes[2] { + return e.Friends, nil + } + return nil, &NotLoadedError{edge: "friends"} +} + // scanValues returns the types for scanning values from sql.Rows. func (*User) scanValues() []interface{} { return []interface{}{ @@ -97,7 +108,7 @@ func (*User) scanValues() []interface{} { // fkValues returns the types for scanning foreign-keys values from sql.Rows. func (*User) fkValues() []interface{} { return []interface{}{ - &sql.NullInt64{}, // user_pets + &sql.NullInt64{}, // owner_id } } @@ -161,10 +172,10 @@ func (u *User) assignValues(values ...interface{}) error { values = values[9:] if len(values) == len(user.ForeignKeys) { if value, ok := values[0].(*sql.NullInt64); !ok { - return fmt.Errorf("unexpected type %T for edge-field user_pets", value) + return fmt.Errorf("unexpected type %T for edge-field owner_id", value) } else if value.Valid { - u.user_pets = new(int) - *u.user_pets = int(value.Int64) + u.owner_id = new(int) + *u.owner_id = int(value.Int64) } } return nil @@ -180,6 +191,11 @@ func (u *User) QueryPets() *PetQuery { return (&UserClient{config: u.config}).QueryPets(u) } +// QueryFriends queries the friends edge of the User. +func (u *User) QueryFriends() *UserQuery { + return (&UserClient{config: u.config}).QueryFriends(u) +} + // Update returns a builder for updating this User. // Note that, you need to call User.Unwrap() before calling this method, if this User // was returned from a transaction, and the transaction was committed or rolled back. diff --git a/entc/integration/migrate/entv2/user/user.go b/entc/integration/migrate/entv2/user/user.go index d3fe892da..bb01f73ac 100644 --- a/entc/integration/migrate/entv2/user/user.go +++ b/entc/integration/migrate/entv2/user/user.go @@ -38,6 +38,8 @@ const ( EdgeCar = "car" // EdgePets holds the string denoting the pets edge name in mutations. EdgePets = "pets" + // EdgeFriends holds the string denoting the friends edge name in mutations. + EdgeFriends = "friends" // Table holds the table name of the user in the database. Table = "users" @@ -54,7 +56,9 @@ const ( // It exists in this package in order to avoid circular dependency with the "pet" package. PetsInverseTable = "pets" // PetsColumn is the table column denoting the pets relation/edge. - PetsColumn = "user_pets" + PetsColumn = "owner_id" + // FriendsTable is the table the holds the friends relation/edge. The primary key declared below. + FriendsTable = "friends" ) // Columns holds all SQL columns for user fields. @@ -73,9 +77,15 @@ var Columns = []string{ // ForeignKeys holds the SQL foreign-keys that are owned by the User type. var ForeignKeys = []string{ - "user_pets", + "owner_id", } +var ( + // FriendsPrimaryKey and FriendsColumn2 are the table columns denoting the + // primary key for the friends relation (M2M). + FriendsPrimaryKey = []string{"user", "friend"} +) + var ( // DefaultPhone holds the default value on creation for the phone field. DefaultPhone string diff --git a/entc/integration/migrate/entv2/user/where.go b/entc/integration/migrate/entv2/user/where.go index 243670137..59e553617 100644 --- a/entc/integration/migrate/entv2/user/where.go +++ b/entc/integration/migrate/entv2/user/where.go @@ -1094,6 +1094,34 @@ func HasPetsWith(preds ...predicate.Pet) predicate.User { }) } +// HasFriends applies the HasEdge predicate on the "friends" edge. +func HasFriends() predicate.User { + return predicate.User(func(s *sql.Selector) { + step := sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.To(FriendsTable, FieldID), + sqlgraph.Edge(sqlgraph.M2M, false, FriendsTable, FriendsPrimaryKey...), + ) + sqlgraph.HasNeighbors(s, step) + }) +} + +// HasFriendsWith applies the HasEdge predicate on the "friends" edge with a given conditions (other predicates). +func HasFriendsWith(preds ...predicate.User) predicate.User { + return predicate.User(func(s *sql.Selector) { + step := sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.To(Table, FieldID), + sqlgraph.Edge(sqlgraph.M2M, false, FriendsTable, FriendsPrimaryKey...), + ) + sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) { + for _, p := range preds { + p(s) + } + }) + }) +} + // And groups list of predicates with the AND operator between them. func And(predicates ...predicate.User) predicate.User { return predicate.User(func(s *sql.Selector) { diff --git a/entc/integration/migrate/entv2/user_create.go b/entc/integration/migrate/entv2/user_create.go index 29119bd38..62b843aa3 100644 --- a/entc/integration/migrate/entv2/user_create.go +++ b/entc/integration/migrate/entv2/user_create.go @@ -151,6 +151,21 @@ func (uc *UserCreate) SetPets(p *Pet) *UserCreate { return uc.SetPetsID(p.ID) } +// AddFriendIDs adds the friends edge to User by ids. +func (uc *UserCreate) AddFriendIDs(ids ...int) *UserCreate { + uc.mutation.AddFriendIDs(ids...) + return uc +} + +// AddFriends adds the friends edges to User. +func (uc *UserCreate) AddFriends(u ...*User) *UserCreate { + ids := make([]int, len(u)) + for i := range u { + ids[i] = u[i].ID + } + return uc.AddFriendIDs(ids...) +} + // Mutation returns the UserMutation object of the builder. func (uc *UserCreate) Mutation() *UserMutation { return uc.mutation @@ -341,6 +356,25 @@ func (uc *UserCreate) sqlSave(ctx context.Context) (*User, error) { } _spec.Edges = append(_spec.Edges, edge) } + if nodes := uc.mutation.FriendsIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: false, + Table: user.FriendsTable, + Columns: user.FriendsPrimaryKey, + Bidi: true, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: user.FieldID, + }, + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges = append(_spec.Edges, edge) + } if err := sqlgraph.CreateNode(ctx, uc.driver, _spec); err != nil { if cerr, ok := isSQLConstraintError(err); ok { err = cerr diff --git a/entc/integration/migrate/entv2/user_query.go b/entc/integration/migrate/entv2/user_query.go index 008250d04..4acc1e868 100644 --- a/entc/integration/migrate/entv2/user_query.go +++ b/entc/integration/migrate/entv2/user_query.go @@ -31,9 +31,10 @@ type UserQuery struct { unique []string predicates []predicate.User // eager-loading edges. - withCar *CarQuery - withPets *PetQuery - withFKs bool + withCar *CarQuery + withPets *PetQuery + withFriends *UserQuery + withFKs bool // intermediate query (i.e. traversal path). sql *sql.Selector path func(context.Context) (*sql.Selector, error) @@ -99,6 +100,24 @@ func (uq *UserQuery) QueryPets() *PetQuery { return query } +// QueryFriends chains the current query on the friends edge. +func (uq *UserQuery) QueryFriends() *UserQuery { + query := &UserQuery{config: uq.config} + query.path = func(ctx context.Context) (fromU *sql.Selector, err error) { + if err := uq.prepareQuery(ctx); err != nil { + return nil, err + } + step := sqlgraph.NewStep( + sqlgraph.From(user.Table, user.FieldID, uq.sqlQuery()), + sqlgraph.To(user.Table, user.FieldID), + sqlgraph.Edge(sqlgraph.M2M, false, user.FriendsTable, user.FriendsPrimaryKey...), + ) + fromU = sqlgraph.SetNeighbors(uq.driver.Dialect(), step) + return fromU, nil + } + return query +} + // First returns the first User entity in the query. Returns *NotFoundError when no user was found. func (uq *UserQuery) First(ctx context.Context) (*User, error) { us, err := uq.Limit(1).All(ctx) @@ -300,6 +319,17 @@ func (uq *UserQuery) WithPets(opts ...func(*PetQuery)) *UserQuery { return uq } +// WithFriends tells the query-builder to eager-loads the nodes that are connected to +// the "friends" edge. The optional arguments used to configure the query builder of the edge. +func (uq *UserQuery) WithFriends(opts ...func(*UserQuery)) *UserQuery { + query := &UserQuery{config: uq.config} + for _, opt := range opts { + opt(query) + } + uq.withFriends = query + return uq +} + // GroupBy used to group vertices by one or more fields/columns. // It is often used with aggregate functions, like: count, max, mean, min, sum. // @@ -367,9 +397,10 @@ func (uq *UserQuery) sqlAll(ctx context.Context) ([]*User, error) { nodes = []*User{} withFKs = uq.withFKs _spec = uq.querySpec() - loadedTypes = [2]bool{ + loadedTypes = [3]bool{ uq.withCar != nil, uq.withPets != nil, + uq.withFriends != nil, } ) if uq.withPets != nil { @@ -434,7 +465,7 @@ func (uq *UserQuery) sqlAll(ctx context.Context) ([]*User, error) { ids := make([]int, 0, len(nodes)) nodeids := make(map[int][]*User) for i := range nodes { - if fk := nodes[i].user_pets; fk != nil { + if fk := nodes[i].owner_id; fk != nil { ids = append(ids, *fk) nodeids[*fk] = append(nodeids[*fk], nodes[i]) } @@ -447,7 +478,7 @@ func (uq *UserQuery) sqlAll(ctx context.Context) ([]*User, error) { for _, n := range neighbors { nodes, ok := nodeids[n.ID] if !ok { - return nil, fmt.Errorf(`unexpected foreign-key "user_pets" returned %v`, n.ID) + return nil, fmt.Errorf(`unexpected foreign-key "owner_id" returned %v`, n.ID) } for i := range nodes { nodes[i].Edges.Pets = n @@ -455,6 +486,69 @@ func (uq *UserQuery) sqlAll(ctx context.Context) ([]*User, error) { } } + if query := uq.withFriends; query != nil { + fks := make([]driver.Value, 0, len(nodes)) + ids := make(map[int]*User, len(nodes)) + for _, node := range nodes { + ids[node.ID] = node + fks = append(fks, node.ID) + } + var ( + edgeids []int + edges = make(map[int][]*User) + ) + _spec := &sqlgraph.EdgeQuerySpec{ + Edge: &sqlgraph.EdgeSpec{ + Inverse: false, + Table: user.FriendsTable, + Columns: user.FriendsPrimaryKey, + }, + Predicate: func(s *sql.Selector) { + s.Where(sql.InValues(user.FriendsPrimaryKey[0], fks...)) + }, + + ScanValues: func() [2]interface{} { + return [2]interface{}{&sql.NullInt64{}, &sql.NullInt64{}} + }, + Assign: func(out, in interface{}) error { + eout, ok := out.(*sql.NullInt64) + if !ok || eout == nil { + return fmt.Errorf("unexpected id value for edge-out") + } + ein, ok := in.(*sql.NullInt64) + if !ok || ein == nil { + return fmt.Errorf("unexpected id value for edge-in") + } + outValue := int(eout.Int64) + inValue := int(ein.Int64) + node, ok := ids[outValue] + if !ok { + return fmt.Errorf("unexpected node id in edges: %v", outValue) + } + edgeids = append(edgeids, inValue) + edges[inValue] = append(edges[inValue], node) + return nil + }, + } + if err := sqlgraph.QueryEdges(ctx, uq.driver, _spec); err != nil { + return nil, fmt.Errorf(`query edges "friends": %v`, err) + } + query.Where(user.IDIn(edgeids...)) + neighbors, err := query.All(ctx) + if err != nil { + return nil, err + } + for _, n := range neighbors { + nodes, ok := edges[n.ID] + if !ok { + return nil, fmt.Errorf(`unexpected "friends" node returned %v`, n.ID) + } + for i := range nodes { + nodes[i].Edges.Friends = append(nodes[i].Edges.Friends, n) + } + } + } + return nodes, nil } diff --git a/entc/integration/migrate/entv2/user_update.go b/entc/integration/migrate/entv2/user_update.go index ea7a7cafa..6c0c32a99 100644 --- a/entc/integration/migrate/entv2/user_update.go +++ b/entc/integration/migrate/entv2/user_update.go @@ -184,6 +184,21 @@ func (uu *UserUpdate) SetPets(p *Pet) *UserUpdate { return uu.SetPetsID(p.ID) } +// AddFriendIDs adds the friends edge to User by ids. +func (uu *UserUpdate) AddFriendIDs(ids ...int) *UserUpdate { + uu.mutation.AddFriendIDs(ids...) + return uu +} + +// AddFriends adds the friends edges to User. +func (uu *UserUpdate) AddFriends(u ...*User) *UserUpdate { + ids := make([]int, len(u)) + for i := range u { + ids[i] = u[i].ID + } + return uu.AddFriendIDs(ids...) +} + // Mutation returns the UserMutation object of the builder. func (uu *UserUpdate) Mutation() *UserMutation { return uu.mutation @@ -210,6 +225,21 @@ func (uu *UserUpdate) ClearPets() *UserUpdate { return uu } +// RemoveFriendIDs removes the friends edge to User by ids. +func (uu *UserUpdate) RemoveFriendIDs(ids ...int) *UserUpdate { + uu.mutation.RemoveFriendIDs(ids...) + return uu +} + +// RemoveFriends removes friends edges to User. +func (uu *UserUpdate) RemoveFriends(u ...*User) *UserUpdate { + ids := make([]int, len(u)) + for i := range u { + ids[i] = u[i].ID + } + return uu.RemoveFriendIDs(ids...) +} + // Save executes the query and returns the number of rows/vertices matched by this operation. func (uu *UserUpdate) Save(ctx context.Context) (int, error) { if v, ok := uu.mutation.State(); ok { @@ -452,6 +482,44 @@ func (uu *UserUpdate) sqlSave(ctx context.Context) (n int, err error) { } _spec.Edges.Add = append(_spec.Edges.Add, edge) } + if nodes := uu.mutation.RemovedFriendsIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: false, + Table: user.FriendsTable, + Columns: user.FriendsPrimaryKey, + Bidi: true, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: user.FieldID, + }, + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := uu.mutation.FriendsIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: false, + Table: user.FriendsTable, + Columns: user.FriendsPrimaryKey, + Bidi: true, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: user.FieldID, + }, + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Add = append(_spec.Edges.Add, edge) + } if n, err = sqlgraph.UpdateNodes(ctx, uu.driver, _spec); err != nil { if _, ok := err.(*sqlgraph.NotFoundError); ok { err = &NotFoundError{user.Label} @@ -621,6 +689,21 @@ func (uuo *UserUpdateOne) SetPets(p *Pet) *UserUpdateOne { return uuo.SetPetsID(p.ID) } +// AddFriendIDs adds the friends edge to User by ids. +func (uuo *UserUpdateOne) AddFriendIDs(ids ...int) *UserUpdateOne { + uuo.mutation.AddFriendIDs(ids...) + return uuo +} + +// AddFriends adds the friends edges to User. +func (uuo *UserUpdateOne) AddFriends(u ...*User) *UserUpdateOne { + ids := make([]int, len(u)) + for i := range u { + ids[i] = u[i].ID + } + return uuo.AddFriendIDs(ids...) +} + // Mutation returns the UserMutation object of the builder. func (uuo *UserUpdateOne) Mutation() *UserMutation { return uuo.mutation @@ -647,6 +730,21 @@ func (uuo *UserUpdateOne) ClearPets() *UserUpdateOne { return uuo } +// RemoveFriendIDs removes the friends edge to User by ids. +func (uuo *UserUpdateOne) RemoveFriendIDs(ids ...int) *UserUpdateOne { + uuo.mutation.RemoveFriendIDs(ids...) + return uuo +} + +// RemoveFriends removes friends edges to User. +func (uuo *UserUpdateOne) RemoveFriends(u ...*User) *UserUpdateOne { + ids := make([]int, len(u)) + for i := range u { + ids[i] = u[i].ID + } + return uuo.RemoveFriendIDs(ids...) +} + // Save executes the query and returns the updated entity. func (uuo *UserUpdateOne) Save(ctx context.Context) (*User, error) { if v, ok := uuo.mutation.State(); ok { @@ -887,6 +985,44 @@ func (uuo *UserUpdateOne) sqlSave(ctx context.Context) (u *User, err error) { } _spec.Edges.Add = append(_spec.Edges.Add, edge) } + if nodes := uuo.mutation.RemovedFriendsIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: false, + Table: user.FriendsTable, + Columns: user.FriendsPrimaryKey, + Bidi: true, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: user.FieldID, + }, + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := uuo.mutation.FriendsIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: false, + Table: user.FriendsTable, + Columns: user.FriendsPrimaryKey, + Bidi: true, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: user.FieldID, + }, + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Add = append(_spec.Edges.Add, edge) + } u = &User{config: uuo.config} _spec.Assign = u.assignValues _spec.ScanValues = u.scanValues() diff --git a/entc/load/internal/bindata.go b/entc/load/internal/bindata.go index 4fbe149e3..ea126453f 100644 --- a/entc/load/internal/bindata.go +++ b/entc/load/internal/bindata.go @@ -98,7 +98,7 @@ func templateMainTmpl() (*asset, error) { return a, nil } -var _schemaGo = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xb4\x5a\x5f\x6f\xe3\x46\x0e\x7f\xb6\x3e\x05\x37\x40\x03\x7b\xe1\xca\xbd\xa2\x28\xee\xbc\xe7\x03\x8a\x76\x8b\xe6\x7a\x4d\x17\xdd\xdd\xbe\x2c\x16\x5b\x45\xa2\xec\xd9\x48\x23\x77\x66\x9c\x4d\x9a\xe6\xbb\x1f\x48\xce\x48\x23\x59\x76\xf6\x5f\xfc\x12\x89\x43\x0e\xc9\xdf\x70\x48\xce\x28\x8b\x05\x7c\xdf\x6c\x6f\x8c\x5a\x6f\x1c\x7c\xfd\xd5\x3f\xfe\xf5\xe5\xd6\xa0\x45\xed\xe0\xc7\x2c\xc7\x8b\xa6\xb9\x84\x33\x9d\xa7\xf0\x5d\x55\x01\x33\x59\xa0\x71\x73\x85\x45\x9a\x2c\x16\xf0\x62\xa3\x2c\xd8\x66\x67\x72\x84\xbc\x29\x10\x94\x85\x4a\xe5\xa8\x2d\x16\xb0\xd3\x05\x1a\x70\x1b\x84\xef\xb6\x59\xbe\x41\xf8\x3a\xfd\x2a\x8c\x42\xd9\xec\x74\x41\x53\x28\xcd\x2c\xff\x3b\xfb\xfe\xe9\xf9\xf3\xa7\x50\xaa\x0a\x03\xcd\x34\x8d\x83\x42\x19\xcc\x5d\x63\x6e\xa0\x29\xc1\x45\xfa\x9c\x41\x4c\x93\x64\x9b\xe5\x97\xd9\x1a\xa1\x6a\xb2\x22\x49\x54\xbd\x6d\x8c\x83\x69\x32\x39\x41\x9d\x37\x85\xd2\xeb\xc5\x5b\xdb\xe8\x93\x64\x72\x52\xd6\x8e\xfe\x18\x2c\x2b\xcc\xdd\x49\x92\x4c\x4e\xd6\xca\x6d\x76\x17\x69\xde\xd4\x8b\xd2\x3b\xac\x74\xbe\xbb\xc8\x5c\x63\x16\xa8\x99\xff\x3e\x9e\x85\xcd\x37\x58\x67\x0b\x2c\xd6\xf8\x21\xfc\xa5\xc2\xaa\xf8\x10\x01\xa5\x0b\xbc\x3e\x49\x66\x09\xc1\xf6\x9c\x69\x60\xd0\x2f\x98\x85\x4c\x03\x6a\x97\xfa\x01\xb7\xc9\x1c\xbc\xcb\x2c\xe3\x82\x05\x94\xa6\xa9\x21\x83\xbc\xa9\xb7\x95\xa2\xc5\xb1\x68\xc0\x63\x97\x26\xee\x66\x8b\x61\x4a\xeb\xcc\x2e\x77\x70\x9b\x4c\xce\xb3\x1a\x01\x80\x28\x4a\xaf\x81\x7f\x7f\x10\x9a\xcb\x13\x9d\xd5\x38\x6f\x6a\xe5\xb0\xde\xba\x9b\x93\x3f\x92\xc9\xf7\x8d\x2e\xd5\x1a\xd8\x86\xf0\xec\x99\x73\x7e\xed\xb3\x3f\x2d\xd6\x68\x01\xe0\xd5\xeb\xc7\xf4\x18\xcf\x4d\x40\xda\x3e\xf7\x8f\x84\x95\x65\x6e\x7e\x8c\xb8\x19\xc6\x01\xfb\x19\x21\x85\x96\xd8\xf9\x31\x62\x57\x32\xd4\xe7\xff\xa9\x69\x2e\xbd\x31\xcf\x1a\xab\x9c\x6a\x74\xe0\xdf\xd0\x50\x9f\xfb\x59\x53\xa9\xfc\x06\xe0\xa2\x69\x2a\x80\x1e\x2c\x5b\x1e\xea\xb1\xdf\xf1\x72\xb5\xd3\x16\x68\x73\xa3\x2e\xd0\x42\x06\x6c\x3a\x6c\xc3\x90\x8f\x7a\x59\x6d\xbf\x26\xad\x5c\xb7\x2a\xad\x47\x00\x4a\x3b\x80\xc5\x02\x04\x13\x76\x2d\xcc\x22\x73\x57\xca\xba\x34\x99\xfc\xa2\xae\xb1\x38\xd3\x24\xc2\x46\x2f\x16\x70\xa6\x0b\x95\x67\x0e\x2d\xa8\x32\x12\xa0\x88\xa9\x89\xfb\x4b\xa5\x45\x50\xe9\x33\x3f\xaf\xe8\x62\x52\x5f\x57\xcd\x24\xd1\x25\xee\x8a\x41\xfb\xc1\x29\xf4\x8f\x88\x4d\x11\xdc\x0f\x4d\xf9\xc5\x01\x7a\x4f\x98\x9e\xe9\xb2\xe9\xd8\x1e\xb3\xd7\xe9\x8b\x9b\x2d\xfa\x01\x2f\x48\x4a\xfb\x82\x2f\xb2\x58\xc1\x41\x8d\x2e\x1b\x04\xfa\x73\xf5\x57\x64\xe9\x63\xa5\xdd\xb7\xdf\x8c\xc8\x59\xf5\xd7\x40\xe1\x53\xbd\xab\x6d\xcb\xf6\xea\xf5\x50\x65\xd8\x2d\xc4\xd6\x97\x7c\xa9\xd5\x9f\xbb\x56\x69\x1c\xa6\x3d\xc9\x1d\xb3\xf5\x45\xcf\x55\x55\x65\x17\x15\xde\x23\xaa\x3d\x5b\x5f\xf8\xd7\x2d\x85\x6a\x56\xdd\x23\xdc\x78\xb6\xbe\xf0\x0f\x58\x66\xbb\xca\xdd\x67\x74\x21\x6c\xa3\xb2\xbf\x67\x15\xb9\xad\xb4\x43\x43\x99\xf4\xf6\x6e\x54\xf6\xcd\x15\xf1\x0d\x20\xdb\x16\x99\xc3\x60\xc3\x61\xc8\x98\xed\xcd\xa8\x11\x67\x75\xbd\x73\x2d\x76\x07\xa7\x50\x81\xad\x2f\xfd\x7b\x56\xa9\x82\x32\x3e\x2f\x39\x6f\xb6\x31\xe9\xab\x96\x6d\x10\x65\xae\x31\xd9\x1a\x7f\xc6\x1b\x38\x16\x9d\x56\xd8\xde\x5c\xe2\xcd\x30\xa7\xf9\x3c\xc3\xbf\xc7\xfd\xd7\x38\xbf\x09\x7d\xa0\x1c\x35\x91\xaf\xee\xf1\xdc\x06\xb6\x81\x34\xe7\x3b\xda\x82\xc4\x5b\x67\xdb\x57\x62\x7e\x08\xf8\x20\xcd\x6c\x6f\xf6\x36\xa6\x24\x1c\xae\x21\xfb\xf9\x86\xc9\x1f\x91\x6e\x58\x6e\x24\xdb\xf4\x4d\xda\xcf\x2e\xc1\x8b\x01\xe3\x91\x6c\x32\x60\x1c\x66\x8f\xdf\xb0\x14\xe5\x7d\x3e\x83\xe5\x9b\x7d\xed\xbf\x61\xe9\xd7\x4f\x4a\x6a\xc7\x7c\x20\x3f\xf8\xa5\x3a\x92\x0f\xce\xf4\x15\x1a\x8b\x43\x56\x25\xe4\xa1\xfa\x3f\x77\xca\x60\x31\xe0\x35\x9e\x3c\xb2\x6a\x52\x59\xf6\x97\x4d\xe8\x1f\xb1\x6e\x22\xd8\x2d\x5c\x94\x09\xdb\xb0\x3c\xe2\x6d\x68\x4a\xe2\x7c\x7b\x7f\x53\x32\xc2\x3d\xd6\x94\x44\x5b\xb4\xdd\x9f\xf7\x6c\x4b\x41\xe9\x1c\xdf\xf1\x7a\xe6\x06\xb9\x60\x67\x3a\x20\x42\x46\x09\x2c\xfc\x24\xbd\xc5\xd6\x35\x26\x4d\xca\x9d\xce\x83\xe4\x14\x0b\x78\x4c\x1c\xe9\x0f\x2d\xc7\xcc\x07\xc9\x6d\x32\xd1\x08\xcb\x15\x9c\xd2\xeb\x6d\x32\xa1\xd0\x5c\x0a\x06\x58\xa4\x2f\xb2\xf5\x9c\x68\x37\x5b\x5c\xb6\x34\x8a\xe6\x64\xc2\xbb\xa2\x25\xd2\x0b\x11\x05\xf1\xa5\x10\xe5\x85\xc8\x3e\x8e\x96\x4c\xf6\x2f\x44\x0f\x31\xb3\x24\x7a\x78\x91\x81\xd2\xcf\xcf\x03\xa5\x9f\xff\x2e\x99\xa8\x12\x0c\x96\x64\xb2\x8c\x3c\xe1\xd7\x47\x2b\xd0\xaa\x22\x77\x26\x1a\x89\x0c\xab\xd6\x7d\x83\xe5\x8c\x45\x0d\xba\x9d\xd1\xa0\xb1\x43\x56\x1a\x8b\x7d\x68\xa5\x1d\x62\x6c\xe5\x71\x0c\x5c\x16\x9e\x96\x45\xe8\x23\x62\x78\xa7\xd2\xa9\xce\x01\x8d\xa1\xf7\x5b\xb6\x1c\x8d\x21\xcb\xcb\x22\x7d\x6a\xcc\x74\xf6\x84\x09\x91\xed\xc1\x42\x55\xcd\xa1\xac\x1d\x71\x35\xa6\x9c\x4a\x40\xc1\x17\x7f\x2e\xe1\x8b\xab\x93\x39\xc9\x33\x20\x24\x2e\xae\x59\x46\xe4\x94\x75\xde\xf6\x16\x87\x7f\x65\xb7\x42\xd4\xe8\xf4\x47\x88\x32\xef\xad\x7c\x18\xf1\xcb\xcf\xad\xc8\x32\x1e\x60\x4a\x7f\xbd\xc3\x50\xb7\xe8\xa1\x99\x58\x76\x36\x84\xbe\x21\x99\xb4\xdd\x42\x37\x1a\x28\x34\xea\x4b\xf1\xb2\x9b\x37\x14\x67\x41\x8b\x75\xc7\x45\x7b\xc9\xba\x7b\x65\xbc\xe3\x6c\x6b\xf3\xb2\xf5\xb9\x2d\xc3\xc9\x24\xda\x9a\x4b\x3f\xdc\x51\x68\xbc\x2b\xce\x3c\x5e\xa1\x9e\x96\x45\xda\x51\x67\x3c\x49\x28\x6f\xad\x8e\x96\xc2\xc3\x6d\x99\x6b\x75\xb4\x94\x36\xb0\x6d\xc9\x8b\x01\xab\xfb\x23\xa2\x56\xd6\x52\x12\xe1\xbc\xa7\x48\xa8\x6c\x0c\x84\x38\x39\x99\xd3\x5c\xb4\xe4\xb3\x76\x6e\x6a\x44\x97\x2b\xe0\x0e\x94\xec\xa7\xce\x74\xf6\x44\xe8\x8f\x56\xf0\x15\xab\xb3\x25\xd3\x61\x05\xa7\x34\xc0\xc2\x94\xa9\xe5\x90\xe0\x1b\x1f\xe0\x0e\x0a\xf2\x4c\xc3\x05\x02\x1f\xb4\xb1\x00\xd7\x30\xcf\x1a\x35\x9a\x8c\xf7\x09\x49\xfe\xd8\x18\xc0\xeb\xac\xde\x56\x38\x07\xdd\x38\x3a\xf7\xec\x74\xce\xdd\x45\xa5\x2e\x11\x9c\xaa\x31\x3d\x6f\xde\xa5\x6c\xe5\x9b\x79\xd8\x23\x94\x1a\xd3\x5f\x32\x63\x37\x59\x35\xed\xd6\xdf\xef\x99\x08\x21\x5b\xa6\xbd\x06\x70\x15\x45\x4b\xbc\xed\x6d\x39\x27\x99\x6e\xef\x4b\xb5\xd8\xdf\xfb\x72\xb8\xe1\xbd\x2f\x8f\x63\x7b\x9f\x85\xa7\xaa\xb8\xa6\x9e\xbe\xc0\xeb\x7e\x6e\x95\xa9\x6f\x5b\xdd\xa7\x4c\x20\x6b\xb9\xc6\xf8\xb0\x56\xc5\x35\xb7\x28\xbc\x93\xa4\x9c\x2c\xdb\x01\x79\x1f\xee\x31\x1a\xe9\x76\x58\x1c\xb8\x34\xd2\x0b\xdb\x3b\xef\xa9\xc7\xd0\x1f\xef\x65\xb5\x78\xa5\xa2\xeb\x82\xb6\x67\xa6\xa7\x06\x32\xf8\xef\xf3\x5f\xcf\x49\x98\x8b\xb0\x5f\xe8\x02\x65\xa1\x99\x85\x26\xf0\xc2\xcd\xc5\x5b\xcc\x9d\xff\xe3\x11\xea\x29\x9d\xda\xa0\x9b\x6a\xbb\xd7\x34\x83\xe9\x05\xbc\x7a\x7d\x71\xe3\x24\x8f\x45\x89\xd2\x72\x2e\x13\x59\xc2\x4c\xee\x13\x96\xe1\x68\x2c\xaf\xd3\x59\x5c\x84\x94\x96\x8b\xa2\xa9\xbf\xde\xe1\x2a\xf5\x6b\xe9\x35\xcf\x66\xbc\x17\x58\xe4\x2e\x4e\xc4\x36\xa5\x35\xe7\x33\x6d\x60\x7d\xef\x9c\xec\x9d\x6a\x93\xb2\x1d\xe6\xe4\xa1\x1a\x59\xd1\xcf\xaf\x47\x7a\x93\x56\x57\x56\x22\x07\x55\x50\xd4\x1a\xf2\x39\x74\x51\x92\xa1\x3d\x4a\x9a\x4c\xa6\xd7\xc8\xad\x87\x95\x8d\x28\xc1\x0c\x2b\xc8\xb6\x5b\xd4\xc5\xd4\x13\xe6\x5d\x23\x12\xed\x92\xe9\x6c\xe6\x61\xf2\x57\x32\xb1\x03\xfe\x06\xe7\x21\x5d\xa0\xad\xdb\x3a\xe1\x6d\xf0\x6e\x84\xfb\xa3\xc8\x91\xb3\x60\x64\xbc\xf5\x47\xbd\x19\x2c\x3a\xdf\x2d\x3d\x7c\x6c\xc9\xa5\xd4\xe7\xd7\xe3\x05\x7b\xc9\xd8\xce\x7c\x66\x79\xa9\xeb\x5e\x6e\x91\x04\x61\xa5\x0c\xa8\x2b\xd4\x70\xb1\x2b\x4b\x34\xc0\x29\xc5\x67\xd7\x70\xbf\xc5\x69\x62\x30\xc3\xf4\x62\x57\xfa\x9c\x40\x1d\x94\x10\xe7\x87\x32\x43\x0f\x06\xb6\xb0\x9d\x8e\x26\x9a\x83\x3d\x0e\x04\x1a\x13\x07\x44\xd9\x85\x83\xf5\xd9\x97\x45\xa2\xb6\x2d\xf5\x05\xd0\x8e\xb4\x6e\xfb\x53\xd3\xdc\x51\xf9\x89\xab\x4f\x9b\x75\xf8\xc9\xfa\x2b\x34\xd7\x78\x74\x7c\x53\x1f\xa7\x4b\x0f\xd8\xd4\x82\x87\x65\x06\xc3\xd4\x35\xcc\xaf\x0c\x1b\xd9\xc6\xb3\xf7\xf6\x57\x2f\xe3\x1d\xd9\x5d\x31\x44\x6a\x0e\x75\xb4\x65\xc4\x64\x6e\xb8\xe9\x84\xca\x9d\xc5\x78\x0e\xae\xaf\xdb\xfc\x9b\x4c\x26\xfe\x6c\x14\x5b\xe3\x13\x63\x7d\x3d\xeb\xe0\x1e\x41\xb6\xdf\xfe\x90\xf6\x36\x6e\x75\x14\xb5\x64\x2f\x1b\xfc\xb6\xb7\xa6\x65\xb7\xa2\x13\x6a\x05\xbc\xfe\xae\x8d\xef\xef\x66\x62\x1b\x31\xe5\x43\x6d\x61\x63\xa8\x45\x69\xaf\x54\x56\x70\x1a\x9e\x65\x46\x4e\x27\xbe\x23\x78\x3b\x67\x92\xbf\xb0\x65\xa2\x33\x52\xeb\x27\xd1\x6d\xec\x12\xd4\xbc\x9b\x3c\x04\x6b\x94\xae\x7c\xf3\x00\xb6\x0c\x80\x1c\x2a\x12\x9f\x1b\xf4\x43\xc5\xe1\xa3\xaa\x03\xcf\x7a\xac\x3e\x3c\x80\xf5\x07\xeb\xc2\xa7\x14\x06\x56\x20\xdf\x12\x62\x37\xa4\x38\x7c\xf6\xb8\xef\xec\x67\x95\xc1\x7a\xf9\xcc\x11\xd9\xfe\x93\x18\xf4\x19\xe3\x71\x36\xcc\x7a\xfd\x94\xe7\x03\x55\x72\x9e\x9c\x55\x3e\x22\xe7\xf5\xfa\xa8\x83\x49\xef\x70\x9e\xf9\xe0\xb4\x37\x9e\x45\xde\x2f\x89\x1c\x5e\xd6\xb6\x46\x1c\x4c\x0f\x01\x5b\xe6\xb9\x6f\x97\xef\x61\x3e\x8a\x5d\xdc\x8e\x1c\x84\xee\x50\xa0\x7e\x20\x70\x63\x61\xf8\xbe\x51\xd8\x06\xa1\x04\x56\x1b\x80\x65\x56\xc9\xcd\xd1\xdd\x7b\xbb\xdc\x6b\x8d\x0e\xfa\xec\x3f\xdd\xc5\x4e\xf7\x7b\xaa\xf7\xf0\xda\xa6\xfe\xdb\xe0\x0a\x64\x3a\xcf\x3b\x6e\x66\x09\x72\x45\x34\x83\xae\xab\xe8\xec\x51\x25\x3c\x6a\x0f\xb6\xf0\xf7\xdf\xf4\x76\xa6\xcb\x26\x3d\xdf\xd5\x68\x54\x3e\x9d\x0d\xfa\x19\xb6\x40\xcf\xa1\xb9\x94\x56\x25\x3e\x13\xa7\xd3\xb2\x6a\x32\xf7\xed\x37\xe2\xc5\xa3\xe6\x32\x16\x8e\xf3\xcb\x4e\xe3\xf5\x16\x73\x87\xc5\xe0\xb0\xcf\xf7\x0c\xed\x15\xc3\x52\xee\x18\xe2\x2b\x06\xfb\x4e\xb9\x7c\x03\x4e\xb4\xb3\xa9\x54\xff\x9f\x90\xa6\x3c\xb3\x08\x0e\xfe\xb3\x82\xf8\x83\x9b\xfb\x27\x9c\x9e\x82\x83\x7f\x0f\xc8\xdf\x7e\xb3\xa4\x4c\x36\x3c\xd5\xcb\xc5\x85\x9e\x8d\x4f\xf7\x52\x8d\xcf\xf7\x52\x1d\x9c\x70\xd7\xcd\x38\x96\xb0\xba\x8c\x01\xef\x4c\xb6\xb5\xf1\xd7\x59\x4f\xcf\x74\x21\x7d\x50\x20\xd4\xe8\x36\x4d\x01\xef\x94\xdb\x80\xc1\xbc\xb9\x92\xe6\x17\xb5\xdd\x19\x04\xdd\xc0\x36\xd3\x2a\xb7\xa0\x34\xf8\x4e\x55\xe9\xb5\x4f\x73\x51\x86\x2a\x8b\xe8\x2b\x16\x78\xe2\x0c\x5e\xbd\xee\x3e\xa2\xde\xcd\x60\xea\x93\x51\x44\x1e\x9e\xa4\x0b\xa4\xf6\x9b\xa6\xf7\xf1\xa2\x4a\xb8\xe2\x7d\x29\xc6\x51\x1f\x7b\xd5\x4b\x4e\x7c\xb9\xd2\x0b\x89\x2f\x5e\x04\xef\xc4\xf8\xf6\x0e\x72\x0e\x57\xdc\xe2\x94\x21\x31\x71\x14\x72\xfe\xa7\x4e\x2f\x44\x57\x91\x06\x07\xe6\x03\x74\xa5\x21\xd8\x03\x57\xc8\x9f\x0a\x65\x7c\x06\x8e\xd1\x14\x7a\x00\x93\x2f\xc1\x09\x4b\xe9\x54\x3a\xe2\x43\x20\xd9\xf3\xaf\x07\xa6\x00\x89\xbe\x41\x1a\xc5\x31\x16\xde\x87\x32\x74\x26\x7b\x60\x86\x81\x4f\x85\xb3\x7f\x22\x8f\x01\x0d\x23\x01\x52\xb9\xfb\x22\x4c\x55\xfb\x7f\x18\x2d\xfd\x01\x61\x0d\x9e\x8e\x00\xab\xda\xbe\xed\x18\xb4\xad\x23\x43\x70\xe5\xa4\xb6\x07\xad\x90\x3f\x15\xd8\x63\x27\xb8\xa9\xb4\x7b\x82\xdf\x2f\xdd\x29\xee\x41\xf0\x13\x77\x46\xd0\x13\x23\x8e\x63\x27\x5e\xec\x21\x27\xc5\x7e\x0f\x39\x21\x7f\x2a\x72\xbd\x5e\x26\x0a\x48\xa1\x87\x70\xa4\x37\x8e\x46\x69\x42\x3a\xe2\x03\x42\x29\xfe\x8d\x40\xb9\xf1\xcd\xcf\x31\x28\xbd\xf9\x43\x28\x7d\x6b\xb1\x87\xa5\xa7\x7f\x2a\x98\x47\xbb\xa4\xa9\x6f\x67\x88\xfc\x2c\x6a\x94\x1e\x04\x3c\xef\xd0\x08\x7a\xdb\xd0\x5d\x1d\x83\xcf\x3b\xd2\xe1\xc7\x2e\xb6\x77\x13\x0e\xe2\xdb\x89\x59\xef\x8d\x8f\x0d\x8d\x01\x97\xfe\xac\x74\x31\x9d\xc1\x6a\xd5\x8e\x3f\x73\xdc\x96\x4d\x1c\xac\xc0\xa5\x4f\x2b\xac\xa7\xbd\xbe\xc1\x25\x77\xc9\xff\x03\x00\x00\xff\xff\xdd\xdc\x23\x9c\x4f\x29\x00\x00") +var _schemaGo = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xb4\x5a\x5f\x6f\xdc\x36\x12\x7f\x5e\x7d\x8a\x89\x81\x1a\x52\xb0\xd5\xf6\x8a\xa2\xb8\xdb\xdc\x1e\x50\xb4\x29\xea\xeb\xd5\x0d\x9a\xa4\x2f\x41\x90\xca\xd2\x68\x97\xb1\x44\x6e\x49\xae\x63\xd7\xf5\x77\x3f\x70\x86\x94\x28\xad\x76\x9d\x7f\xf6\x4b\xa4\xe1\x0c\x67\xe6\xc7\xe1\xf0\x27\x6e\x16\x0b\xf8\x5e\x6d\x6f\xb4\x58\x6f\x2c\x7c\xfd\xd5\x3f\xfe\xf5\xe5\x56\xa3\x41\x69\xe1\xc7\xa2\xc4\x0b\xa5\x2e\xe1\x4c\x96\x39\x7c\xd7\x34\x40\x4a\x06\xdc\xb8\xbe\xc2\x2a\x4f\x16\x0b\x78\xb1\x11\x06\x8c\xda\xe9\x12\xa1\x54\x15\x82\x30\xd0\x88\x12\xa5\xc1\x0a\x76\xb2\x42\x0d\x76\x83\xf0\xdd\xb6\x28\x37\x08\x5f\xe7\x5f\x85\x51\xa8\xd5\x4e\x56\x6e\x0a\x21\x49\xe5\x7f\x67\xdf\x3f\x3d\x7f\xfe\x14\x6a\xd1\x60\x90\x69\xa5\x2c\x54\x42\x63\x69\x95\xbe\x01\x55\x83\x8d\xfc\x59\x8d\x98\x27\xc9\xb6\x28\x2f\x8b\x35\x42\xa3\x8a\x2a\x49\x44\xbb\x55\xda\x42\x9a\xcc\x4e\x50\x96\xaa\x12\x72\xbd\x78\x6b\x94\x3c\x49\x66\x27\x75\x6b\xdd\x3f\x1a\xeb\x06\x4b\x7b\x92\x24\xb3\x93\xb5\xb0\x9b\xdd\x45\x5e\xaa\x76\x51\xfb\x84\x85\x2c\x77\x17\x85\x55\x7a\x81\x92\xf4\xef\xd3\x59\x98\x72\x83\x6d\xb1\xc0\x6a\x8d\x1f\xa2\x5f\x0b\x6c\xaa\x0f\x31\x10\xb2\xc2\xeb\x93\x24\x4b\x1c\x6c\xcf\x49\x06\x1a\xfd\x82\x19\x28\x24\xa0\xb4\xb9\x1f\xb0\x9b\xc2\xc2\xbb\xc2\x10\x2e\x58\x41\xad\x55\x0b\x05\x94\xaa\xdd\x36\xc2\x2d\x8e\x41\x0d\x1e\xbb\x3c\xb1\x37\x5b\x0c\x53\x1a\xab\x77\xa5\x85\xdb\x64\x76\x5e\xb4\x08\x00\x4e\x22\xe4\x1a\xe8\xef\x0f\x87\xe6\xf2\x44\x16\x2d\xce\x55\x2b\x2c\xb6\x5b\x7b\x73\xf2\x47\x32\xfb\x5e\xc9\x5a\xac\x81\x62\x08\xcf\x5e\xb9\xa4\xd7\xa1\xfa\xd3\x6a\x8d\x06\x00\x5e\xbd\x7e\xec\x1e\xe3\xb9\x1d\x90\x66\xa8\xfd\xa3\xc3\xca\x90\x36\x3d\x46\xda\x04\xe3\x48\xfd\xcc\x21\x85\xc6\xa9\xd3\x63\xa4\x2e\x78\x68\xa8\xff\x93\x52\x97\x3e\x98\x67\xca\x08\x2b\x94\x0c\xfa\x1b\x37\x34\xd4\x7e\xa6\x1a\x51\xde\x00\x5c\x28\xd5\x00\x0c\x60\xd9\xd2\xd0\x40\xfd\x8e\x96\xab\x9b\xb6\x42\x53\x6a\x71\x81\x06\x0a\xa0\xd0\x61\x1b\x86\x7c\xd5\xf3\x6a\xfb\x35\xe9\xec\xfa\x55\xe9\x32\x02\x10\xd2\x02\x2c\x16\xc0\x98\x50\x6a\x61\x16\x9e\xbb\x11\xc6\xe6\xc9\xec\x17\x71\x8d\xd5\x99\x74\x26\x14\xf4\x62\x01\x67\xb2\x12\x65\x61\xd1\x80\xa8\x23\x03\x57\x31\xad\xd3\xfe\x52\x48\x36\x14\xf2\xcc\xcf\xcb\xbe\x48\x34\xf4\xd5\x92\x88\x7d\x71\xba\x1c\xd0\x7e\x71\xb2\xfc\x23\x6a\x93\x0d\xf7\x4b\x93\xff\xe2\x02\xbd\xa7\x4c\xcf\x64\xad\x7a\xb5\xc7\x94\x75\xfe\xe2\x66\x8b\x7e\xc0\x1b\x3a\xa7\x43\xc3\x17\x45\xec\xe0\xa0\x47\x5b\x8c\x0a\xfd\xb9\xf8\x2b\x8a\xf4\xb1\x90\xf6\xdb\x6f\x26\xec\x8c\xf8\x6b\xe4\xf0\xa9\xdc\xb5\xa6\x53\x7b\xf5\x7a\xec\x32\xec\x16\xa7\x36\xb4\x7c\x29\xc5\x9f\xbb\xce\x69\x5c\xa6\x03\xcb\x1d\xa9\x0d\x4d\xcf\x45\xd3\x14\x17\x0d\xde\x63\x2a\xbd\xda\xd0\xf8\xd7\xad\x2b\xd5\xa2\xb9\xc7\x58\x79\xb5\xa1\xf1\x0f\x58\x17\xbb\xc6\xde\x17\x74\xc5\x6a\x93\xb6\xbf\x17\x8d\x4b\x5b\x48\x8b\xda\x75\xd2\xdb\xbb\x49\xdb\x37\x57\x4e\x6f\x04\xd9\xb6\x2a\x2c\x86\x18\x0e\x43\x46\x6a\x6f\x26\x83\x38\x6b\xdb\x9d\xed\xb0\x3b\x38\x85\x08\x6a\x43\xeb\xdf\x8b\x46\x54\xae\xe3\xd3\x92\xd3\x66\x9b\xb2\xbe\xea\xd4\x46\x55\x66\x95\x2e\xd6\xf8\x33\xde\xc0\xb1\xea\x34\xac\xf6\xe6\x12\x6f\xc6\x3d\xcd\xf7\x19\xfa\x7b\x3c\x7c\x8d\xfb\x1b\xcb\x47\xce\x51\x3a\xf1\xd5\x3d\x99\x9b\xa0\x36\xb2\xa6\x7e\xe7\xb6\xa0\xd3\x6d\x8b\xed\x2b\x0e\x3f\x14\x7c\xb0\x26\xb5\x37\x7b\x1b\x93\x1b\x0e\x9d\x21\xfb\xfd\x86\xc4\x1f\xd1\x6e\xc8\x6e\xb2\xdb\xec\x41\x7b\xb0\xd3\x84\x8c\x8e\x18\x1d\xed\x32\x07\x8d\xc6\x1d\xe6\x37\xac\xa7\x4e\xea\xd8\x46\x63\xfd\x66\x3f\xc2\xdf\xb0\x0e\x7a\xfd\x21\xbc\x67\x78\xb0\xb7\xec\x2d\xf4\x91\xbe\x72\x26\xaf\x50\x1b\x3c\x66\x26\x58\x65\x1c\xe2\x9f\x3b\xa1\xb1\x3a\x62\xa7\xbd\xca\xc1\x0d\xf1\xd8\x11\x8a\x3c\x12\xdc\xb3\x19\xb8\xa2\xf8\xd4\xdb\x2f\x29\x96\x7f\x44\x4d\xb1\x61\x5f\x54\x53\x48\x1e\x41\x30\x10\xa6\xf8\x2c\xb8\x9f\x30\x4d\x68\x4f\x11\xa6\x08\x9c\xae\x84\xde\x0b\xa5\x73\x7c\x47\x95\x53\x6a\x24\x32\x51\xc8\x80\x88\x0b\x8a\x61\xa1\x27\xe6\x3d\x5b\xab\x74\x9e\xd4\x3b\x59\x06\xcb\x14\x2b\xbf\x40\x3f\x74\x1a\x99\x2f\xc7\xdb\x64\x26\x11\x96\x2b\x38\x75\xaf\xb7\xc9\xcc\x6d\x8f\x65\x58\x7e\xac\xf2\x17\xc5\x7a\xee\xa4\x37\x5b\x5c\x46\x52\xb7\xab\x92\x19\xed\xda\x48\xec\x5e\x9d\x98\x71\x5f\x06\x31\xbf\xba\x01\x5f\xa3\x4b\x3f\xe0\x5f\xdd\x48\xa8\xc2\x25\x8f\x84\x57\x1e\xaa\x3b\x3f\x34\x54\x07\x3f\x3d\xa6\x4b\x37\xd2\xbf\xce\x93\xd9\x5d\x32\x13\x35\x68\xac\x5d\x76\x6c\xf6\x84\x5e\x1f\xad\x40\x8a\xc6\x65\x3e\x93\xe8\xc4\xb0\xea\x90\xd2\x58\x67\x2c\x8f\x96\x6b\x05\xac\x17\xc9\x68\x7a\x8d\x76\xa7\x25\x48\xec\x17\x8a\x39\xd4\xfe\x4a\x31\xf3\xa3\xa5\xe2\xc7\xa9\xb5\x22\xe3\xb4\xae\x02\x65\x8a\x57\x2b\x65\x52\x3e\x07\xd4\xda\xbd\xdf\x52\x76\xa8\xb5\xcb\xae\xae\xf2\xa7\x5a\xa7\xd9\x13\x12\x44\xf9\x85\x08\x45\x33\x87\xba\xb5\x4e\x4b\xe9\x3a\xe5\xfa\x84\x2f\xfe\x5c\xc2\x17\x57\x27\x73\x67\x4f\x88\x3a\xf3\x8c\x52\x33\x84\xda\x29\xf9\xbc\x1d\xad\x33\x40\x67\x40\x2b\x5a\xab\xe1\x88\x93\xcc\x47\x85\xc4\x23\xbe\x96\x88\x75\x2d\xe3\x01\x92\x8c\x0b\x87\x87\xfa\xda\x09\xbc\x69\xd9\xc7\x10\x28\x52\x32\xeb\x88\x51\x3f\x1a\x24\x6e\xd4\xb3\x8e\x65\x3f\x6f\xe0\x21\x8c\x16\xf9\x8e\xf9\xc9\x92\x7c\x0f\x18\x4b\xaf\xd9\xd1\x90\x65\x97\x73\xc7\x38\x46\x55\xc9\xc3\x83\xc2\x8c\x78\x08\x8d\x37\x28\xd3\xba\xca\x7b\x69\x46\x93\x84\x93\xbc\xf3\xd1\x49\x68\xb8\x3b\xd1\x3b\x1f\x9d\xa4\x2b\x7e\x53\xd3\x62\xc0\xea\xfe\x8a\x68\x85\x31\xae\x27\x51\x1b\x15\xce\xa8\x56\x1a\x42\x9d\x9c\xcc\xdd\x5c\x6e\xc9\xb3\x6e\x6e\xc7\xb9\x97\x2b\x20\xb2\xed\xe2\x77\x24\x3c\x7b\xc2\xf2\x47\x2b\xf8\x8a\xdc\x99\x9a\xe4\xb0\x82\x53\x37\x40\xc6\xae\xf1\xf3\xf7\x90\xe7\x78\x40\x64\x11\xca\x42\xc2\x05\x02\xdd\x29\x60\x05\x56\x91\xce\x1a\x25\xea\x82\xf6\x89\xb3\xfc\x51\x69\xc0\xeb\xa2\xdd\x36\x38\x07\xa9\xac\xfb\xc4\xdb\xc9\x92\x88\x54\x23\x2e\x11\xac\x68\x31\x3f\x57\xef\x72\x8a\xf2\xcd\x3c\xec\x11\xd7\x69\xf3\x5f\x0a\x6d\x36\x45\x93\xf6\xeb\xef\xf7\x4c\x84\x90\xa9\xf3\x01\xd7\x5d\x45\xd5\x12\x6f\x7b\x53\xcf\x9d\x4d\xbf\xf7\xf9\xf0\xd9\xdf\xfb\xfc\x1d\x47\x7b\x9f\x1f\xa7\xf6\x3e\x19\xa7\xa2\xba\x76\x9f\x2f\x15\x5e\x0f\x5b\x35\x4f\x7d\xdb\xf9\x3e\x25\x81\x8b\x96\x8e\x2c\x5f\xd6\xa2\xba\x26\x36\x46\x3b\x89\x4f\xa7\x65\x37\xc0\xef\xe3\x3d\xe6\x46\xfa\x1d\x16\x17\xae\x1b\x19\xf5\x53\xce\xd4\x63\xe8\x6f\x32\x78\xb5\x68\xa5\xa2\x9b\x91\xee\xf3\xc0\x3d\x29\x28\xe0\xbf\xcf\x7f\x3d\x77\xc6\x74\xa6\xfb\x85\xae\x90\x17\x9a\x54\xdc\x04\xde\x58\x5d\xbc\xc5\xd2\xfa\x7f\x3c\x42\x03\xa7\xa9\x09\xbe\x1d\x55\xf0\x9e\x32\x48\x2f\xe0\xd5\xeb\x8b\x1b\xcb\x7d\x2c\x6a\x94\x86\x7a\x19\xdb\x3a\xcc\xf8\xea\x64\x19\x6e\x01\xf8\x35\xcd\xe2\xf3\x4c\x48\xbe\x13\x4b\xfd\x4d\x16\x1d\x78\xbf\xd6\xde\x73\x96\xd1\x5e\x20\x93\xbb\xb8\x11\x9b\xdc\xad\x39\x7d\xbe\x07\xd5\xf7\xee\xc9\x3e\xa9\xae\x29\x9b\x71\x4f\x1e\xbb\xe1\x15\xfd\xfc\x7e\x98\xea\x74\xbe\x8a\x1a\xa9\xa8\x82\xa3\x2e\x90\xcf\xe1\xcb\x35\x19\xb7\x47\x9d\x27\x5d\xc8\x35\x12\x93\x31\xbc\x11\xb9\x98\x61\x05\xc5\x76\x8b\xb2\x4a\xbd\x60\xde\xf3\x9a\x68\x97\xa4\x59\xe6\x61\xf2\xb7\x4f\x71\x02\xfe\xb2\xea\x21\x53\x70\x5b\xb7\x4b\xc2\xc7\xe0\xd3\x08\x57\x65\x51\x22\x67\x21\xc8\x78\xeb\x4f\x66\x33\x5a\x74\xba\x46\x7b\xf8\xda\xe2\xfb\xb7\xcf\xef\xc7\x1b\x0e\x9a\xb1\xc9\x7c\x67\x79\x29\xdb\x41\x6f\xe1\x06\x61\xf8\x18\x10\x57\x28\xe1\x62\x57\xd7\xa8\x81\x5a\x8a\xef\xae\xe1\x2a\x8f\xda\xc4\x68\x86\xf4\x62\x57\xfb\x9e\xe0\x18\x14\x0b\xe7\x87\x3a\xc3\x00\x06\x8a\xb0\x9b\xce\x4d\x34\x07\x73\x1c\x08\xd4\x3a\x2e\x88\xba\x2f\x07\xe3\xbb\x2f\x99\x44\xb4\x2d\xf7\x07\xa0\x99\xa0\x6e\xfb\x53\xbb\xb9\xa3\xe3\x27\x3e\x7d\xba\xae\x43\x4f\xc6\xdf\x16\x5a\xe5\xd1\xf1\xdf\x08\x71\xbb\xf4\x80\xa5\x06\x3c\x2c\x19\x8c\x5b\xd7\xb8\xbf\x12\x6c\x2e\x36\x9a\x7d\xb0\xbf\x06\x1d\xef\xc8\xee\x8a\x21\x12\x73\x68\xa3\x2d\xc3\x21\x13\x29\x77\x1f\xda\xc4\x2c\xa6\x7b\x70\x7b\xdd\xf5\xdf\x64\x36\xf3\x9f\x5a\x71\x34\xbe\x31\xb6\xd7\x59\x0f\xf7\x04\xb2\x43\xfa\xe3\xbc\x77\x75\x2b\xa3\xaa\x75\xf1\x52\xc0\x6f\x07\x6b\x5a\xf7\x2b\x3a\x73\x54\xc0\xfb\xef\x69\xfc\x70\x37\x3b\xb5\x89\x50\x3e\x34\x16\x0a\xc6\x51\x94\xee\xf6\x68\x05\xa7\xe1\x99\x67\xa4\x76\xe2\x19\xc1\xdb\x39\x89\xfc\xdd\x34\x09\xad\xe6\xb3\x7e\x16\x5d\x3c\x2f\x41\xcc\xfb\xc9\x43\xb1\x46\xed\xca\x93\x07\x30\x75\x00\xe4\xd0\x21\xf1\xb9\x41\x3f\x74\x38\x7c\xd4\xe9\x40\xb3\x1e\x3b\x1f\x1e\x20\xfa\x83\xe7\xc2\xa7\x1c\x0c\xe4\x80\x7f\x36\x89\xd3\xe0\xc3\xe1\xb3\xd7\x7d\x1f\x3f\xb9\x0c\xd1\xf3\x2f\x3a\x51\xec\x3f\x71\x40\x9f\xb1\x1e\xb3\x71\xd7\x1b\xb6\x3c\x5f\xa8\xdc\xf3\xf8\x5b\xe5\x23\x7a\xde\x80\x47\x1d\x6c\x7a\x87\xfb\xcc\x07\xb7\xbd\xe9\x2e\xf2\x7e\x4d\xe4\xf0\xb2\x76\x67\xc4\xc1\xf6\x10\xb0\x25\x9d\xfb\x76\xf9\x1e\xe6\x93\xd8\xc5\x74\xe4\x20\x74\x87\x0a\xf5\x03\x81\x9b\x2a\xc3\xf7\xad\xc2\xae\x08\xb9\xb0\xba\x02\xac\x8b\x86\xaf\x9f\xee\xde\x3b\xe5\x01\x35\x3a\x98\xb3\xff\x95\x32\x4e\x7a\xc8\xa9\xde\x23\x6b\x93\xfb\x9f\x41\x57\xc0\xd3\x79\xdd\xe9\x30\x6b\xe0\x2b\xa2\x0c\x7a\x56\xd1\xc7\x23\x6a\x78\xd4\x7d\xd8\xc2\xdf\x7f\xbb\xb7\x33\x59\xab\xfc\x7c\xd7\xa2\x16\x65\x9a\x8d\xf8\x0c\x45\x20\xe7\xa0\x2e\x99\xaa\xc4\xdf\xc4\x79\x5a\x37\xaa\xb0\xdf\x7e\xc3\x59\x3c\x52\x97\xb1\x71\xdc\x5f\x76\x12\xaf\xb7\x58\x5a\xac\x46\x1f\xfb\x74\xcf\xd0\x5d\x31\x2c\xf9\x8e\x21\xbe\x62\x30\xef\x84\x2d\x37\x60\xd9\x3b\x85\xea\xce\xff\x27\xce\x53\x59\x18\x04\x0b\xff\x59\x41\xfc\xdb\xa2\xfd\x27\x9c\x9e\x82\x85\x7f\x8f\xc4\xdf\x7e\xb3\x74\x9d\x6c\xfc\x55\xcf\x17\x17\x32\x9b\x9e\xee\xa5\x98\x9e\xef\xa5\x38\x38\xe1\xae\x9f\x71\xaa\x61\xf5\x1d\x03\xde\xe9\x62\x6b\xe2\x1f\xa2\xbd\xbc\x90\x15\xf3\xa0\x20\x68\xd1\x6e\x54\x05\xef\x84\xdd\x80\xc6\x52\x5d\x31\xf9\x45\x69\x76\x1a\x41\x2a\xd8\x16\x52\x94\x06\x84\x04\xcf\x54\x85\x5c\xfb\x36\x17\x75\xa8\xba\x8a\x7e\xb0\x03\x2f\xcc\xe0\xd5\xeb\xfe\xf7\xe2\xbb\x0c\x52\xdf\x8c\x22\xf1\xf8\x4b\xba\x42\x47\xbf\xdd\xf4\xbe\x5e\x44\x0d\x57\xb4\x2f\x39\x38\xc7\x63\xaf\x06\xcd\x89\x2e\x57\x06\x25\xf1\xc5\x8b\x90\x1d\x07\xdf\xdd\x41\xce\xe1\x8a\x28\x4e\x1d\x1a\x13\x55\x21\xf5\x7f\xc7\xf4\x42\x75\x55\x79\x48\x60\x3e\x42\x97\x09\xc1\x1e\xb8\x2c\xfe\x54\x28\xe3\x6f\xe0\x18\x4d\x96\x07\x30\xe9\x4e\xdd\x61\xc9\x4c\xa5\x17\x3e\x04\x92\x83\xfc\x06\x60\x32\x90\xe8\x09\xd2\x24\x8e\xb1\xf1\x3e\x94\x81\x99\xec\x81\x19\x06\x3e\x15\xce\xe1\x17\x79\x0c\x68\x18\x09\x90\xf2\xdd\x97\xc3\x54\x74\xff\xe5\xa4\x93\x3f\x20\xac\x21\xd3\x09\x60\x45\xc7\xdb\x8e\x41\xdb\x25\x32\x06\x97\xbf\xd4\xf6\xa0\x65\xf1\xa7\x02\x7b\xec\x0b\x2e\x65\xba\xc7\xf8\xfd\xd2\x7f\xc5\x3d\x08\x7e\x9c\xce\x04\x7a\x1c\xc4\x71\xec\x38\x8b\x3d\xe4\xf8\xb0\xdf\x43\x8e\xc5\x9f\x8a\xdc\x80\xcb\x44\x05\xc9\xf2\x50\x8e\xee\x8d\xaa\x91\x49\x48\x2f\x7c\x40\x28\x39\xbf\x09\x28\x37\x9e\xfc\x1c\x83\xd2\x87\x3f\x86\xd2\x53\x8b\x3d\x2c\xbd\xfc\x53\xc1\x3c\xca\x92\x52\x4f\x67\x9c\xf8\x59\x44\x94\x1e\x04\x3c\x9f\xd0\x04\x7a\xdb\xc0\xae\x8e\xc1\xe7\x13\xe9\xf1\xa3\x14\xbb\xbb\x09\x0b\xf1\xed\x44\x36\x78\xa3\xcf\x06\xa5\xc1\xe6\x3f\x0b\x59\xa5\x19\xac\x56\xdd\xf8\x33\x4b\xb4\x6c\x66\x61\x05\x36\x7f\xda\x60\x9b\x0e\x78\x83\x4d\xee\x92\xff\x07\x00\x00\xff\xff\x43\x01\x91\xe2\x3a\x2a\x00\x00") func schemaGoBytes() ([]byte, error) { return bindataRead( @@ -113,7 +113,7 @@ func schemaGo() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "schema.go", size: 10575, mode: os.FileMode(420), modTime: time.Unix(1, 0)} + info := bindataFileInfo{name: "schema.go", size: 10810, mode: os.FileMode(420), modTime: time.Unix(1, 0)} a := &asset{bytes: bytes, info: info} return a, nil } diff --git a/entc/load/schema.go b/entc/load/schema.go index 1fbd237d0..0fd2b8bf1 100644 --- a/entc/load/schema.go +++ b/entc/load/schema.go @@ -56,14 +56,15 @@ type Field struct { // Edge represents an ent.Edge that was loaded from a complied user package. type Edge struct { - Name string `json:"name,omitempty"` - Type string `json:"type,omitempty"` - Tag string `json:"tag,omitempty"` - RefName string `json:"ref_name,omitempty"` - Ref *Edge `json:"ref,omitempty"` - Unique bool `json:"unique,omitempty"` - Inverse bool `json:"inverse,omitempty"` - Required bool `json:"required,omitempty"` + Name string `json:"name,omitempty"` + Type string `json:"type,omitempty"` + Tag string `json:"tag,omitempty"` + RefName string `json:"ref_name,omitempty"` + Ref *Edge `json:"ref,omitempty"` + Unique bool `json:"unique,omitempty"` + Inverse bool `json:"inverse,omitempty"` + Required bool `json:"required,omitempty"` + StorageKey *edge.StorageKey `json:"storage_key,omitempty"` } // Index represents an ent.Index that was loaded from a complied user package. @@ -77,16 +78,18 @@ type Index struct { // NewEdge creates an loaded edge from edge descriptor. func NewEdge(ed *edge.Descriptor) *Edge { ne := &Edge{ - Tag: ed.Tag, - Type: ed.Type, - Name: ed.Name, - Unique: ed.Unique, - Inverse: ed.Inverse, - Required: ed.Required, - RefName: ed.RefName, + Tag: ed.Tag, + Type: ed.Type, + Name: ed.Name, + Unique: ed.Unique, + Inverse: ed.Inverse, + Required: ed.Required, + RefName: ed.RefName, + StorageKey: ed.StorageKey, } if ref := ed.Ref; ref != nil { ne.Ref = NewEdge(ref) + ne.StorageKey = ne.Ref.StorageKey } return ne } diff --git a/entc/load/schema_test.go b/entc/load/schema_test.go index 87411c090..9c8b34d4a 100644 --- a/entc/load/schema_test.go +++ b/entc/load/schema_test.go @@ -50,6 +50,7 @@ func (User) Edges() []ent.Edge { edge.To("groups", Group.Type), edge.To("parent", User.Type). Unique(). + StorageKey(edge.Column("user_parent_id")). From("children"), } } @@ -123,10 +124,12 @@ func TestMarshalSchema(t *testing.T) { require.Equal(t, "Group", schema.Edges[0].Type) require.False(t, schema.Edges[0].Inverse) require.Equal(t, "children", schema.Edges[1].Name) + require.Equal(t, "user_parent_id", schema.Edges[1].StorageKey.Columns[0]) require.Equal(t, "User", schema.Edges[1].Type) require.True(t, schema.Edges[1].Inverse) require.Equal(t, "parent", schema.Edges[1].Ref.Name) require.True(t, schema.Edges[1].Ref.Unique) + require.Equal(t, "user_parent_id", schema.Edges[1].Ref.StorageKey.Columns[0]) require.Equal(t, []string{"name", "address"}, schema.Indexes[0].Fields) require.True(t, schema.Indexes[0].Unique) diff --git a/schema/edge/edge.go b/schema/edge/edge.go index 56985e03c..63e4b24df 100644 --- a/schema/edge/edge.go +++ b/schema/edge/edge.go @@ -10,14 +10,15 @@ import ( // A Descriptor for edge configuration. type Descriptor struct { - Tag string // struct tag. - Type string // edge type. - Name string // edge name. - RefName string // ref name; inverse only. - Ref *Descriptor // edge reference; to/from of the same type. - Unique bool // unique edge. - Inverse bool // inverse edge. - Required bool // required on creation. + Tag string // struct tag. + Type string // edge type. + Name string // edge name. + RefName string // ref name; inverse only. + Ref *Descriptor // edge reference; to/from of the same type. + Unique bool // unique edge. + Inverse bool // inverse edge. + Required bool // required on creation. + StorageKey *StorageKey // optional storage-key configuration. } // To defines an association edge between two vertices. @@ -72,6 +73,21 @@ func (b *assocBuilder) Comment(string) *assocBuilder { return b } +// StorageKey sets the storage key of the edge. +// +// edge.To("groups"). +// StorageKey(edge.Table("user_groups"), edge.Columns("user_id", "group_id")) +// +func (b *assocBuilder) StorageKey(opts ...StorageOption) *assocBuilder { + if b.desc.StorageKey == nil { + b.desc.StorageKey = &StorageKey{} + } + for i := range opts { + opts[i](b.desc.StorageKey) + } + return b +} + // Descriptor implements the ent.Descriptor interface. func (b *assocBuilder) Descriptor() *Descriptor { return b.desc @@ -117,3 +133,37 @@ func (b *inverseBuilder) Comment(string) *inverseBuilder { func (b *inverseBuilder) Descriptor() *Descriptor { return b.desc } + +// StorageKey holds the configuration for edge storage-key. +type StorageKey struct { + Table string // Table or label. + Columns []string // Foreign-key columns. +} + +// StorageOption allows for setting the storage configuration using functional options. +type StorageOption func(*StorageKey) + +// The Table option sets the table name of M2M edges. +func Table(name string) StorageOption { + return func(key *StorageKey) { + key.Table = name + } +} + +// The Column option sets the foreign-key column name for O2O, O2M and M2O +// edges. Note that, for M2M edges (2 columns), use the edge.Columns option. +func Column(name string) StorageOption { + return func(key *StorageKey) { + key.Columns = []string{name} + } +} + +// The Columns option sets the foreign-key column names for M2M edges. +// The 1st column defines the name of the "To" edge, and the 2nd defines +// the name of the "From" edge (inverse edge). +// Note that, for O2O, O2M and M2O edges, use the edge.Column option. +func Columns(to, from string) StorageOption { + return func(key *StorageKey) { + key.Columns = []string{to, from} + } +} diff --git a/schema/edge/edge_test.go b/schema/edge/edge_test.go index b2d27c59f..44ff9cf53 100644 --- a/schema/edge/edge_test.go +++ b/schema/edge/edge_test.go @@ -76,9 +76,11 @@ func TestEdge(t *testing.T) { from = edge.To("following", User.Type). StructTag("following"). + StorageKey(edge.Table("user_followers"), edge.Columns("following_id", "followers_id")). From("followers"). StructTag("followers"). Descriptor() assert.Equal("followers", from.Tag) assert.Equal("following", from.Ref.Tag) + assert.Equal(edge.StorageKey{Table: "user_followers", Columns: []string{"following_id", "followers_id"}}, *from.Ref.StorageKey) }