From 7fde9b76429bdad6bf683261d3f5ffbcd1262284 Mon Sep 17 00:00:00 2001 From: Ariel Mashraki Date: Wed, 18 Dec 2019 19:25:46 +0200 Subject: [PATCH 1/2] entc/gen: move sql-update-one to sqlgraph --- dialect/sql/sqlgraph/graph.go | 19 +- dialect/sql/sqlgraph/graph_test.go | 5 +- entc/gen/func.go | 6 + entc/gen/internal/bindata.go | 8 +- entc/gen/template/dialect/sql/create.tmpl | 2 +- entc/gen/template/dialect/sql/update.tmpl | 446 ++-- entc/integration/config/ent/user_update.go | 109 +- entc/integration/customid/customid_test.go | 1 - entc/integration/customid/ent/blob_update.go | 156 +- entc/integration/customid/ent/group_update.go | 234 ++- entc/integration/customid/ent/user_update.go | 234 ++- entc/integration/ent/card_update.go | 309 +-- entc/integration/ent/comment_update.go | 242 ++- entc/integration/ent/fieldtype_update.go | 825 +++++--- entc/integration/ent/file_update.go | 464 ++-- entc/integration/ent/filetype_update.go | 318 ++- entc/integration/ent/group_update.go | 843 ++++---- entc/integration/ent/groupinfo_update.go | 350 +-- entc/integration/ent/item_update.go | 110 +- entc/integration/ent/node_update.go | 411 ++-- entc/integration/ent/pet_update.go | 382 ++-- entc/integration/ent/user_update.go | 1869 +++++++++-------- entc/integration/idtype/ent/user_update.go | 518 +++-- entc/integration/integration_test.go | 7 +- entc/integration/json/ent/user_update.go | 381 ++-- entc/integration/migrate/entv1/user_update.go | 323 +-- .../integration/migrate/entv2/group_update.go | 109 +- entc/integration/migrate/entv2/pet_update.go | 109 +- entc/integration/migrate/entv2/user_update.go | 361 ++-- entc/integration/template/ent/group_update.go | 161 +- entc/integration/template/ent/pet_update.go | 312 +-- entc/integration/template/ent/user_update.go | 408 ++-- entc/integration/type_test.go | 42 +- examples/edgeindex/ent/city_update.go | 278 ++- examples/edgeindex/ent/street_update.go | 256 +-- examples/entcpkg/ent/user_update.go | 109 +- examples/m2m2types/ent/group_update.go | 281 ++- examples/m2m2types/ent/user_update.go | 321 +-- examples/m2mbidi/ent/user_update.go | 334 +-- examples/m2mrecur/ent/user_update.go | 410 ++-- examples/o2m2types/ent/pet_update.go | 256 +-- examples/o2m2types/ent/user_update.go | 310 +-- examples/o2mrecur/ent/node_update.go | 385 ++-- examples/o2o2types/ent/card_update.go | 279 +-- examples/o2o2types/ent/user_update.go | 292 +-- examples/o2obidi/ent/user_update.go | 316 ++- examples/o2orecur/ent/node_update.go | 379 ++-- examples/start/ent/car_update.go | 279 +-- examples/start/ent/group_update.go | 281 ++- examples/start/ent/user_update.go | 427 ++-- examples/traversal/ent/group_update.go | 368 ++-- examples/traversal/ent/pet_update.go | 382 ++-- examples/traversal/ent/user_update.go | 676 +++--- 53 files changed, 8834 insertions(+), 7859 deletions(-) diff --git a/dialect/sql/sqlgraph/graph.go b/dialect/sql/sqlgraph/graph.go index e1f2a2c1b..2a9c3b9e7 100644 --- a/dialect/sql/sqlgraph/graph.go +++ b/dialect/sql/sqlgraph/graph.go @@ -630,15 +630,28 @@ func (u *updater) setExternalEdges(ctx context.Context, ids []driver.Value, addE // setTableColumns sets the table columns and foreign_keys used in insert. func (u *updater) setTableColumns(update *sql.UpdateBuilder, addEdges, clearEdges map[Rel][]*EdgeSpec) error { + // Avoid multiple assignments to same column. + setEdges := make(map[string]bool) + for _, e := range addEdges[M2O] { + setEdges[e.Columns[0]] = true + } + for _, e := range addEdges[O2O] { + if e.Inverse || e.Bidi { + setEdges[e.Columns[0]] = true + } + } for _, fi := range u.Fields.Clear { update.SetNull(fi.Column) } for _, e := range clearEdges[M2O] { - update.SetNull(e.Columns[0]) + if col := e.Columns[0]; !setEdges[col] { + update.SetNull(col) + } } for _, e := range clearEdges[O2O] { - if e.Inverse || e.Bidi { - update.SetNull(e.Columns[0]) + col := e.Columns[0] + if (e.Inverse || e.Bidi) && !setEdges[col] { + update.SetNull(col) } } err := setTableColumns(u.Fields.Set, addEdges, func(column string, value driver.Value) { diff --git a/dialect/sql/sqlgraph/graph_test.go b/dialect/sql/sqlgraph/graph_test.go index f1e237f14..50eb99363 100644 --- a/dialect/sql/sqlgraph/graph_test.go +++ b/dialect/sql/sqlgraph/graph_test.go @@ -885,8 +885,9 @@ func TestUpdateNode(t *testing.T) { }, prepare: func(mock sqlmock.Sqlmock) { mock.ExpectBegin() - // Clear the "partner" and "spouse 2" from 1's column, and set "spouse 3". - mock.ExpectExec(escape("UPDATE `users` SET `partner_id` = NULL, `spouse_id` = NULL, `spouse_id` = ? WHERE `id` = ?")). + // Clear the "partner" from 1's column, and set "spouse 3". + // "spouse 2" is implicitly removed when setting a different foreign-key. + mock.ExpectExec(escape("UPDATE `users` SET `partner_id` = NULL, `spouse_id` = ? WHERE `id` = ?")). WithArgs(3, 1). WillReturnResult(sqlmock.NewResult(1, 1)) // Clear the "partner_id" column from previous 1's partner. diff --git a/entc/gen/func.go b/entc/gen/func.go index 575c82983..5d6ed8414 100644 --- a/entc/gen/func.go +++ b/entc/gen/func.go @@ -46,6 +46,7 @@ var ( "upper": strings.ToUpper, "hasField": hasField, "indirect": indirect, + "hasPrefix": strings.HasPrefix, "hasSuffix": strings.HasSuffix, "trimPackage": trimPackage, "xtemplate": xtemplate, @@ -193,6 +194,11 @@ func extend(v interface{}, kv ...interface{}) (interface{}, error) { return &typeScope{Type: v, Scope: scope}, nil case *Graph: return &graphScope{Graph: v, Scope: scope}, nil + case *typeScope: + for k := range v.Scope { + scope[k] = v.Scope[k] + } + return &typeScope{Type: v.Type, Scope: scope}, nil default: return nil, fmt.Errorf("invalid type for extend: %T", v) } diff --git a/entc/gen/internal/bindata.go b/entc/gen/internal/bindata.go index bbabad6fe..d9618fb70 100644 --- a/entc/gen/internal/bindata.go +++ b/entc/gen/internal/bindata.go @@ -581,7 +581,7 @@ func templateDialectSqlByTmpl() (*asset, error) { return a, nil } -var _templateDialectSqlCreateTmpl = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x8c\x56\x5b\x6f\xe2\x46\x14\x7e\xb6\x7f\xc5\xe9\x0a\x55\x36\x72\x4c\x36\xaa\x2a\x95\x88\x4a\x59\x48\x24\xd4\xdd\x68\x1b\x92\xbe\x54\xd5\x6a\xf0\x1c\xc3\x88\xc9\x8c\x33\x33\x46\x1b\xa1\xf9\xef\xd5\x5c\x70\x0c\x24\xbb\x79\x81\xe1\xdc\xcf\x77\x6e\xec\x76\xa3\x61\x3a\x95\xcd\xb3\x62\xab\xb5\x81\x8b\xf3\x8f\x7f\x9c\x35\x0a\x35\x0a\x03\x37\xa4\xc2\xa5\x94\x1b\x98\x8b\xaa\x84\x2b\xce\xc1\x0b\x69\x70\x7c\xb5\x45\x5a\xa6\xf7\x6b\xa6\x41\xcb\x56\x55\x08\x95\xa4\x08\x4c\x03\x67\x15\x0a\x8d\x14\x5a\x41\x51\x81\x59\x23\x5c\x35\xa4\x5a\x23\x5c\x94\xe7\x7b\x2e\xd4\xb2\x15\x34\x65\xc2\xf3\x3f\xcf\xa7\xd7\xb7\x8b\x6b\xa8\x19\x47\x88\x34\x25\xa5\x01\xca\x14\x56\x46\xaa\x67\x90\x35\x98\x9e\x33\xa3\x10\xcb\x74\x38\xb2\x36\x4d\x77\x3b\xa0\x58\x33\x81\xf0\x81\x32\xc2\xb1\x32\x23\xfd\xc4\x47\x95\x42\x62\xf0\x03\x58\xeb\x24\x06\xcb\x96\x71\x17\xcf\x78\x02\x0d\xd1\x15\xe1\x30\x28\x17\x95\x6c\xb0\xfc\x14\x39\x51\x50\x61\x85\x6c\x1b\x24\xbb\x77\xa7\xee\x1c\xd6\xad\xa8\x20\x3b\x90\xb5\x16\x86\x7d\x2f\xd6\xe6\xa0\x9f\xf8\x82\x6c\x31\xab\xcc\x77\xa8\xa4\x30\xf8\xdd\x94\xd3\xf0\x9d\x43\xe6\xc5\xcb\x5b\xf2\x88\x60\x6d\x01\xa8\x94\x54\x39\xec\xd2\x64\x4b\x14\x64\x69\x92\x78\xfe\x5d\xcf\xc1\x04\x7e\xed\xeb\xec\x2a\x29\x6a\xb6\x1a\xc3\x51\x20\x65\xa0\xdb\x34\x49\x74\x83\x95\x53\xd3\x4f\x7c\xa5\x48\xb3\x2e\xa7\x1e\x93\x45\x83\xd5\x2e\x4d\x92\xe4\x9e\x2c\x39\x06\x03\xe5\x57\x52\x6d\xc8\xca\x19\x2e\x3d\xb9\x70\x02\xf3\xd9\xb8\xa7\x7d\xc3\x90\xd3\x4e\x39\xb9\x7f\x6e\x70\x0c\xb5\x23\x96\xde\xc4\x7c\x56\x3a\x9a\x4b\x52\x9b\x7d\x66\x5e\x74\x2a\x79\xfb\x28\x4e\x3d\xed\xd5\xbc\x06\x11\x66\xaf\xe0\x3f\x6d\x9a\xe4\x69\xb2\xdb\x9d\x01\xab\x83\xd8\x83\x46\x35\xf3\xa5\xa6\xae\x10\x49\xc2\x6a\xd8\x12\xde\xa2\xab\xd5\x31\x0c\x7b\xdb\xb1\xbc\x3e\x78\xb0\xf6\x32\x6a\xfc\x32\x01\xc1\x38\xf8\x54\x8e\xa1\x2e\xe7\x33\x98\xc0\xd0\x0b\x3a\xbe\xc3\xd1\x99\xfa\xc7\x6b\xf6\x38\x36\xc4\x87\x22\xc4\xe3\xde\x8a\x88\x15\xc2\xe0\x5b\x01\x83\xda\x85\x35\x08\xb0\xe9\xf7\x05\x5c\xbf\x27\x5c\x1f\x4e\xb4\x3a\x01\xd2\x34\x28\x68\xd6\x23\x16\xef\xaf\x59\xfd\x56\xc5\x7c\xaa\xe3\x98\xe9\xcf\x8b\x58\x9f\x96\x30\x7f\x15\xd9\x20\xbc\x30\xaa\xad\xcc\x3e\x47\xf0\x58\xb0\x1a\x84\x34\x8e\x7b\xcb\x38\x77\x2d\x08\xd6\xba\x29\x09\xe8\xbe\x0f\x72\x0c\x90\x5f\xd3\x15\xbe\x20\x2e\x24\x45\xfd\x16\xe2\x78\x8a\x38\x47\x91\x79\x9d\x1c\xfe\x84\xf3\x80\x39\xd2\x95\xb7\xfd\x82\xac\xf3\xf1\x02\xec\x1d\xf2\x31\x74\xbc\x60\xf8\x0e\xb9\x87\xb7\x03\x75\x2e\xb6\xa8\x74\x9c\x38\x2c\xe7\x3a\x12\x3a\x81\x37\x06\x32\x88\x7b\xe6\x31\xcc\xb1\x2a\x7a\x1c\x21\x1c\x60\xf9\xe5\xe2\x8b\x5b\x0f\xaf\xda\xf8\xfa\x57\xcf\x80\xc3\x96\x7b\xef\xff\xfe\xa7\x8d\x62\x62\xb5\x7b\xc3\x75\x70\xd2\x53\x05\xdb\x15\x26\x84\xf1\x89\x51\xb6\xcf\x6b\x81\xbc\xbe\xc3\xba\x97\x95\x5a\xa1\x19\x1f\x61\x17\xa8\x01\xbd\x64\x3e\x73\x50\xfe\x60\xd9\x9c\xb6\x2e\x86\xd6\x7d\x7b\xe9\x1c\x76\x6c\x14\x3f\x45\x35\x1a\x39\x01\x36\x89\xdf\xb1\x9d\xdd\x47\x2d\x15\x6c\x0a\xf8\xe6\x4f\x83\x6f\xba\xd0\x5a\x21\x44\xd7\x8a\x03\x46\x7d\x07\x76\x76\xe1\xcc\x77\x61\xe0\x8e\x86\x30\x95\xae\xe4\x06\x02\xde\x67\x8c\x6a\x30\x6b\x62\x80\x28\x04\x6d\xa4\x42\x0a\x44\x03\x13\x66\x7f\x07\x29\x31\x64\x49\x34\xc2\x70\x74\x60\x8b\xd5\x40\x04\x85\xcc\xcf\x0c\xa3\xfd\xdd\x98\x7b\xc2\x5c\x2f\xbc\x0f\x88\x4a\xc9\xc6\x5f\x19\x17\x9e\x36\xaa\x92\x62\x5b\x5e\x19\xc9\xb2\x4d\x1e\xd8\xac\xf6\xec\xfe\xa2\x49\x92\x44\xa1\x69\x95\x70\x24\xaf\x1d\x91\xe9\xa2\xd8\x8f\x61\x9c\x90\x32\x14\xb5\xbc\xf5\xb0\x74\xbb\xe9\x84\x55\x40\xf0\x6a\xbb\x75\x16\x26\xf6\x70\x9b\x79\x5a\x01\x4e\x3b\x3f\x9d\xfc\x18\xaf\x4b\xe7\xf0\xbc\x39\x0f\xee\xe8\x16\x27\xf3\x4e\x95\x7b\x15\xe0\xac\xe7\x97\xc7\xe9\xb2\x1a\x2a\x54\xaa\x00\xb9\x71\x56\x99\x5e\xfc\xfd\xd9\x77\x85\x22\x4c\x98\x6b\x77\xa0\x33\x54\x2a\xbf\x74\x02\x61\x29\x28\x05\x13\xaf\x14\xc2\x3b\x45\xcb\xa6\xfd\x62\x9d\x1c\xb1\x4c\xaa\x40\xec\x8a\x15\x7f\x3d\x3c\xcc\x67\x79\x40\x36\x36\xce\x4c\xba\xf5\xb8\x66\x62\x55\xc0\x12\x2b\xd2\x6a\x74\xfd\xa1\x11\x2e\xc0\x3c\x37\xa8\xe1\xb1\xd5\x06\x96\x08\xba\x6d\x1a\xce\x90\xc2\xf2\xd9\x77\x50\xab\x51\x95\x5d\xfb\x78\x08\xc3\xd4\xa7\xc9\x0f\x83\x0b\x75\x65\x35\xbc\x7a\x1e\x27\x71\x33\x1e\x76\x41\x68\xff\x83\x7b\x59\x66\x4c\x98\xdf\x7f\x7b\xfd\x1c\xf8\x43\x1b\x37\xd7\x01\x0e\xd6\xee\x9b\xf4\x46\xaa\x47\x62\xe6\xc2\x64\x8c\x16\xf0\xf1\x3c\x7f\x59\x5b\xfd\x7f\x1d\x60\x6d\xc6\x68\xde\xad\xa5\x77\x25\x67\x8f\x12\xe8\xbf\x63\x2d\x8f\x43\x2e\x5c\x75\xd3\xf0\xb7\x33\x8a\xfe\x1f\x00\x00\xff\xff\x96\x8c\x77\x87\x45\x0b\x00\x00") +var _templateDialectSqlCreateTmpl = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x8c\x56\x5b\x6f\xe2\xb8\x17\x7f\x4e\x3e\xc5\xf9\x8f\xd0\x5f\x09\x4a\x43\xa7\x5a\xad\xb4\x54\xac\xd4\x81\x56\x42\x3b\x53\xcd\x96\x76\x5f\x56\xab\x91\x89\x4f\xc0\xc2\xb5\x53\xdb\x41\x53\x21\x7f\xf7\x95\x2f\xa4\x01\xda\x6e\x5f\xc0\x9c\xfb\xf9\x9d\x1b\xbb\xdd\x68\x98\x4e\x65\xf3\xac\xd8\x6a\x6d\xe0\xe2\xfc\xf3\x6f\x67\x8d\x42\x8d\xc2\xc0\x0d\xa9\x70\x29\xe5\x06\xe6\xa2\x2a\xe1\x8a\x73\xf0\x42\x1a\x1c\x5f\x6d\x91\x96\xe9\xfd\x9a\x69\xd0\xb2\x55\x15\x42\x25\x29\x02\xd3\xc0\x59\x85\x42\x23\x85\x56\x50\x54\x60\xd6\x08\x57\x0d\xa9\xd6\x08\x17\xe5\xf9\x9e\x0b\xb5\x6c\x05\x4d\x99\xf0\xfc\xaf\xf3\xe9\xf5\xed\xe2\x1a\x6a\xc6\x11\x22\x4d\x49\x69\x80\x32\x85\x95\x91\xea\x19\x64\x0d\xa6\xe7\xcc\x28\xc4\x32\x1d\x8e\xac\x4d\xd3\xdd\x0e\x28\xd6\x4c\x20\x7c\xa2\x8c\x70\xac\xcc\x48\x3f\xf1\x51\xa5\x90\x18\xfc\x04\xd6\x3a\x89\xc1\xb2\x65\xdc\xc5\x33\x9e\x40\x43\x74\x45\x38\x0c\xca\x45\x25\x1b\x2c\xbf\x44\x4e\x14\x54\x58\x21\xdb\x06\xc9\xee\xdd\xa9\x3b\x87\x75\x2b\x2a\xc8\x0e\x64\xad\x85\x61\xdf\x8b\xb5\x39\xe8\x27\xbe\x20\x5b\xcc\x2a\xf3\x13\x2a\x29\x0c\xfe\x34\xe5\x34\x7c\xe7\x90\x79\xf1\xf2\x96\x3c\x22\x58\x5b\x00\x2a\x25\x55\x0e\xbb\x34\xd9\x12\x05\x59\x9a\x24\x9e\x7f\xd7\x73\x30\x81\xff\xf7\x75\x76\x95\x14\x35\x5b\x8d\xe1\x28\x90\x32\xd0\x6d\x9a\x24\xba\xc1\xca\xa9\xe9\x27\xbe\x52\xa4\x59\x97\x53\x8f\xc9\xa2\xc1\x6a\x97\x26\x49\x72\x4f\x96\x1c\x83\x81\xf2\x3b\xa9\x36\x64\xe5\x0c\x97\x9e\x5c\x38\x81\xf9\x6c\xdc\xd3\xbe\x61\xc8\x69\xa7\x9c\xdc\x3f\x37\x38\x86\xda\x11\x4b\x6f\x62\x3e\x2b\x1d\xcd\x25\xa9\xcd\x3e\x33\x2f\x3a\x95\xbc\x7d\x14\xa7\x9e\xf6\x6a\x5e\x83\x08\xb3\x57\xf0\x9f\x36\x4d\xf2\x34\xd9\xed\xce\x80\xd5\x41\xec\x41\xa3\x9a\xf9\x52\x53\x57\x88\x24\x61\x35\x6c\x09\x6f\xd1\xd5\xea\x18\x86\xbd\xed\x58\x5e\x1f\x3c\x58\x7b\x19\x35\xfe\x37\x01\xc1\x38\xf8\x54\x8e\xa1\x2e\xe7\x33\x98\xc0\xd0\x0b\x3a\xbe\xc3\xd1\x99\xfa\xcb\x6b\xf6\x38\x36\xc4\x87\x22\xc4\xe3\xde\x8a\x88\x15\xc2\xe0\x47\x01\x83\xda\x85\x35\x08\xb0\xe9\x8f\x05\x5c\x7f\x24\x5c\x1f\x4e\xb4\x3a\x01\xd2\x34\x28\x68\xd6\x23\x16\x1f\xaf\x59\xfd\x56\xc5\x7c\xaa\xe3\x98\xe9\x7f\x17\xb1\x3e\x2d\x61\xfe\x2a\xb2\x41\x78\x61\x54\x5b\x99\x7d\x8e\xe0\xb1\x60\x35\x08\x69\x1c\xf7\x96\x71\xee\x5a\x10\xac\x75\x53\x12\xd0\xfd\x18\xe4\x18\x20\xbf\xa6\x2b\x7c\x41\x5c\x48\x8a\xfa\x2d\xc4\xf1\x14\x71\x8e\x22\xf3\x3a\x39\xfc\x0e\xe7\x01\x73\xa4\x2b\x6f\xfb\x05\x59\xe7\xe3\x05\xd8\x3b\xe4\x63\xe8\x78\xc1\xf0\x1d\x72\x0f\x6f\x07\xea\x5c\x6c\x51\xe9\x38\x71\x58\xce\x75\x24\x74\x02\x6f\x0c\x64\x10\xf7\xcc\x63\x98\x63\x55\xf4\x38\x42\x38\xc0\xf2\xdb\xc5\x37\xb7\x1e\x5e\xb5\xf1\xfd\x8f\x9e\x01\x87\x2d\xf7\xde\xff\xfe\x47\x1b\xc5\xc4\x6a\xf7\x86\xeb\xe0\xa4\xa7\x0a\xb6\x2b\x4c\x08\xe3\x0b\xa3\x6c\x9f\xd7\x02\x79\x7d\x87\x75\x2f\x2b\xb5\x42\x33\x3e\xc2\x2e\x50\x03\x7a\xc9\x7c\xe6\xa0\x7c\x67\xd9\x9c\xb6\x2e\x86\xd6\x7d\x7b\xe9\x1c\x76\x6c\x14\x3f\x45\x35\x1a\x39\x01\x36\x89\xdf\xb1\x9d\xdd\x47\x2d\x15\x6c\x0a\xf8\xe1\x4f\x83\x6f\xba\xd0\x5a\x21\x44\xd7\x8a\x03\x46\x7d\x07\x76\x76\xe1\xcc\x77\x61\xe0\x8e\x86\x30\x95\xae\xe4\x06\x02\xde\x67\x8c\x6a\x30\x6b\x62\x80\x28\x04\x6d\xa4\x42\x0a\x44\x03\x13\x66\x7f\x07\x29\x31\x64\x49\x34\xc2\x70\x74\x60\x8b\xd5\x40\x04\x85\xcc\xcf\x0c\xa3\xfd\xdd\x98\x7b\xc2\x5c\x2f\xbc\x0f\x88\x4a\xc9\xc6\x5f\x19\x17\x9e\x36\xaa\x92\x62\x5b\x5e\x19\xc9\xb2\x4d\x1e\xd8\xac\xf6\xec\xfe\xa2\x49\x92\x44\xa1\x69\x95\x70\x24\xaf\x1d\x91\xe9\xa2\xd8\x8f\x61\x9c\x90\x32\x14\xb5\xbc\xf5\xb0\x74\xbb\xe9\x84\x55\x40\xf0\x6a\xbb\x75\x16\x26\xf6\x70\x9b\x79\x5a\x01\x4e\x3b\x3f\x9d\xfc\x18\xaf\x4b\xe7\xf0\xbc\x39\x0f\xee\xe8\x16\x27\xf3\x4e\x95\x7b\x15\xe0\xac\xe7\x97\xc7\xe9\xb2\x1a\x2a\x54\xaa\x00\xb9\x71\x56\x99\x5e\xfc\xf9\xd5\x77\x85\x22\x4c\x98\x6b\x77\xa0\x33\x54\x2a\xbf\x74\x02\x61\x29\x28\x05\x13\xaf\x14\xc2\x3b\x45\xcb\xa6\xfd\x62\x9d\x1c\xb1\x4c\xaa\x40\xec\x8a\x15\x7f\x3d\x3c\xcc\x67\x79\x40\x36\x36\xce\x4c\xba\xf5\xb8\x66\x62\x55\xc0\x12\x2b\xd2\x6a\x74\xfd\xa1\x11\x2e\xc0\x3c\x37\xa8\xe1\xb1\xd5\x06\x96\x08\xba\x6d\x1a\xce\x90\xc2\xf2\xd9\x77\x50\xab\x51\x95\x5d\xfb\x78\x08\xc3\xd4\xa7\xc9\xfb\xd7\xd5\x21\xf2\xea\x69\x9c\xc4\xad\x78\xd8\x01\xa1\xf5\x0f\x6e\x65\x99\x31\x61\x7e\xfd\xe5\xf5\x53\xe0\x8f\x6c\xdc\x5a\x07\x18\x58\xbb\x6f\xd0\x1b\xa9\x1e\x89\x99\x0b\x93\x31\x5a\xc0\xe7\xf3\xfc\x65\x65\xf5\xff\x71\x80\xb5\x19\xa3\x79\xb7\x92\xd2\xe4\x5d\xd4\x43\xb8\xf6\x28\x81\xfe\x3b\xd6\xf1\x38\xe4\xc2\x55\x36\x0d\x7f\x39\xa3\xe8\xbf\x01\x00\x00\xff\xff\x27\x76\x47\x05\x41\x0b\x00\x00") func templateDialectSqlCreateTmplBytes() ([]byte, error) { return bindataRead( @@ -596,7 +596,7 @@ func templateDialectSqlCreateTmpl() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "template/dialect/sql/create.tmpl", size: 2885, mode: os.FileMode(420), modTime: time.Unix(1, 0)} + info := bindataFileInfo{name: "template/dialect/sql/create.tmpl", size: 2881, mode: os.FileMode(420), modTime: time.Unix(1, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -801,7 +801,7 @@ func templateDialectSqlSelectTmpl() (*asset, error) { return a, nil } -var _templateDialectSqlUpdateTmpl = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x5b\x5f\x73\xdb\xb8\x11\x7f\xa6\x3e\xc5\x9e\x46\xf1\x91\xae\x42\x3b\x79\xab\x53\x65\xc6\xb5\x9d\x19\xb5\x8d\x95\x8b\x92\xf6\xc1\xe7\xb9\x81\xc9\xa5\x85\x9a\x02\x15\x00\x92\xed\x6a\xf8\xdd\x3b\x00\x08\x12\xa4\x28\x45\xb2\x3c\x97\xb4\xb9\xcc\x24\x11\xf1\x6f\x17\xfb\xf7\xb7\x20\xb8\x5c\x1e\x1d\x76\xce\xb2\xd9\x23\xa7\xb7\x13\x09\xaf\x8f\x5f\xfd\xf9\xe5\x8c\xa3\x40\x26\xe1\x1d\x89\xf0\x26\xcb\xee\x60\xc8\xa2\x10\x4e\xd3\x14\xf4\x20\x01\xaa\x9f\x2f\x30\x0e\x3b\x9f\x26\x54\x80\xc8\xe6\x3c\x42\x88\xb2\x18\x81\x0a\x48\x69\x84\x4c\x60\x0c\x73\x16\x23\x07\x39\x41\x38\x9d\x91\x68\x82\xf0\x3a\x3c\xb6\xbd\x90\x64\x73\x16\x77\x28\xd3\xfd\xff\x18\x9e\x5d\x5c\x8e\x2f\x20\xa1\x29\x42\xd1\xc6\xb3\x4c\x42\x4c\x39\x46\x32\xe3\x8f\x90\x25\x20\x1d\x62\x92\x23\x86\x9d\xc3\xa3\x3c\xef\x74\x96\x4b\x88\x31\xa1\x0c\xa1\x1b\x53\x92\x62\x24\x8f\xc4\x97\xf4\x68\x3e\x8b\x89\xc4\x2e\xe4\xb9\x1a\xd1\x9b\xdd\xdd\xc2\xc9\x00\x7a\xe1\x38\xca\x66\x18\x7e\x20\xd1\x1d\xb9\x45\xdb\x7b\x33\xa7\xa9\xe2\xf6\x64\x00\x33\x22\x22\x92\x96\x03\xff\x5a\xf4\x14\x03\x39\x46\x48\x17\x66\x64\xf9\xbb\x9c\x5e\x0c\xca\x18\xaa\xfe\x09\x11\xe3\x79\x92\xd0\x87\x6a\x40\x77\xc4\x2c\x4b\x2f\xa1\xf7\x1f\xe4\x99\x1a\x78\x0c\x79\xbe\x5c\x02\x4d\xcc\x54\xfd\x60\x3a\x07\xd0\x65\x34\xed\x9a\x26\x64\x71\x39\x95\xa3\x54\x33\xbb\xac\xdb\x36\x57\xf5\xaa\xbd\x7e\xb4\x1c\xba\xf3\x3b\xc9\x9c\x45\xe0\xd7\x76\x93\xe7\x70\xe8\xca\x21\xcf\x03\x10\x5f\xd2\x31\x59\xa0\x1f\xc9\x07\x88\x32\x26\xf1\x41\x86\x67\xe6\xff\xc0\x4e\x97\x6a\x66\x8d\xbc\x5e\x26\xbc\x24\xd3\x82\x17\x4c\x85\xfa\x45\x99\x2c\x39\xe8\x03\x72\xae\xfe\x66\x3c\x80\x65\xc7\x5b\x10\x0e\x7e\xc7\xf3\x2c\xf1\x81\x22\x1d\x9e\x1b\x5d\x36\xf9\x0c\x63\xae\x7e\x95\xdd\x41\xd0\xf1\x3c\x81\xa9\xb6\x13\x18\x40\xb1\x48\x38\xc6\x72\xb6\xa3\xec\xb0\xc6\xeb\x59\x96\xce\xa7\x4c\x84\x61\x58\x31\xaa\x27\x0c\xcf\xd5\x4e\x85\x24\x4c\xba\xa2\x0b\xc2\x77\x3c\x9b\xfa\x96\xc4\x27\x72\x93\xe2\x0a\x05\xdd\xaa\xb8\x0a\x3a\x9e\x52\x55\x45\xae\xe3\x79\xcd\xc1\xc3\xf3\x95\xfd\xd1\x38\xf0\xed\x7e\x8a\x25\x0a\xd6\x3a\x9e\x97\x64\x1c\x7e\xeb\xc3\x4c\x9b\x1f\x61\xb7\x08\xcd\xe9\x33\x8e\x31\x8d\x88\x44\xa1\x44\xeb\x79\x33\x77\x31\x2f\x2f\x16\x34\x96\xe0\xf1\xec\x5e\xa8\xa5\x0e\x94\xc0\x3f\x66\xf7\x62\x99\x77\xbc\x2f\x73\xe4\x8f\x7d\x20\xfc\x56\xf7\xd9\xe9\xe1\x2f\xaa\xdd\x0f\x3a\x1e\x4d\xb4\x02\x07\x2b\xb4\x0b\xd5\x98\x81\x91\x7c\xe8\x83\xb3\x56\x1f\x14\xb5\xe0\x8d\x9e\xfb\xd3\x00\x18\x4d\x35\x87\x1c\xe5\x9c\x33\x28\x4d\xbe\xb0\x8f\x8e\xe2\x35\xc6\x04\xb9\x9e\x17\x9e\xa5\x99\x40\x5f\x0b\x04\x7a\xf2\x51\x4b\xa0\x4b\x99\x74\xec\x5f\xa9\xed\xb3\x40\x7e\xae\xa3\x41\x5c\x28\x53\x8d\x1d\x98\xce\x4f\x8f\x33\xac\xb9\x82\x36\x3d\x1a\x0b\xb8\xba\xb6\x43\x55\xab\x92\xb2\x26\x7a\x89\x0f\xd2\xd7\x36\x5a\x8c\x04\x77\xd8\xaa\x7a\x8d\x7e\x1d\xaf\x83\x01\x1c\xd4\x1c\x22\xca\x58\x42\x6f\x4f\x56\x44\x67\xda\xf5\x1a\x85\x78\x4f\x8c\x7c\xdd\xd5\xb4\xf9\x29\x35\xf9\xed\xa2\x6c\x17\x66\x32\x95\xe1\x85\x72\xb6\xc4\xef\xda\x48\x98\xe7\x27\x90\x10\x9a\x62\x0c\x22\x22\x8c\x51\x76\xab\x76\x0c\x94\xc9\x0c\x5c\x86\x4f\xe0\xc5\xa2\xab\x15\xa2\xcc\xc7\x2b\x36\xf9\x12\xd4\xbe\x09\x8b\x8d\x5c\x87\x62\x2c\xb9\x5a\xc2\x67\x99\x5c\xd1\x43\x50\xc8\xc6\xa3\x31\xb4\xec\x89\xc6\x7e\x60\x57\xd5\x86\x4e\x13\xc8\xb8\x5d\xf8\xf3\xe7\xe1\xb9\xfd\x3d\xd4\xde\xb8\x61\xa9\xe1\x79\x6d\x21\x77\x2c\x65\x45\x2c\xa8\x8f\xaf\x28\x17\x06\xd1\x9c\x5d\x29\x43\x1b\xc4\x38\x22\xcc\x3f\xa0\xf1\x33\xc9\x9e\x23\x89\x95\xdc\x68\xdc\x22\xe7\x1a\x5b\xca\x48\x07\x40\x66\x33\x64\xb1\x4f\x63\xd1\x07\x1a\x07\x1d\xeb\xcf\x35\x23\x14\xf7\x54\x46\x13\x60\x8a\xe9\x14\x99\x1a\x1d\xbc\xd1\x3c\x46\x44\x20\x30\x18\x0c\xe0\xf8\xa4\xb3\x86\xe3\x83\x0b\xce\x2f\x33\xf9\x4e\xe5\xe7\xa5\x62\x7f\x3c\xe3\x94\xc9\x82\x7f\x6b\x16\x70\x4f\xe5\xa4\x62\xbb\x25\x86\xe5\x15\xbd\xb7\xf0\x6a\x2d\xb9\x75\x02\x9a\x66\x1c\x41\x4e\x08\x03\xb5\xaf\x55\xd2\x0a\x22\x08\xd5\xb0\x89\x07\x27\xe0\x95\x1a\xa5\x49\x29\x14\x2d\x08\xa3\xbc\x36\xd6\x18\x4d\x57\x23\xa6\x02\x4c\x4a\xdc\x72\x82\x1c\x7f\x56\x78\x64\x8a\x72\xa2\x74\x28\x33\x30\x90\xa3\x0f\x42\x12\x2e\x81\x80\xe4\x84\x09\x12\x49\x9a\xb1\x10\x34\x58\xf1\x54\x50\x74\xbc\xbb\x25\x7a\x7e\x7a\x50\xa1\xb3\x0a\xb3\x5b\x86\x4a\x6b\x06\xe1\x3b\x8a\x69\x2c\xcc\x66\x6d\x66\xf5\x38\x0a\x9d\x54\x3f\xa2\x98\xa7\x52\xb5\x18\x5e\xdd\x8c\xf9\x59\xb7\xac\xc9\x67\x1d\x4f\xe5\x33\x4b\x45\x79\x7e\xe5\xeb\xda\x33\x83\xb6\xf8\xab\x3d\x28\x4e\x48\xa4\xf1\xd0\x94\xdc\xa1\x7f\x75\x4d\x99\x44\xae\xda\x96\x79\xbf\xd4\x85\xb6\x7a\x15\x77\x69\x95\xda\x94\xcd\x2f\x0b\x17\x56\xe3\xaf\xe8\xb5\xf2\xe4\x58\x5c\xd1\xeb\x32\x18\x55\xfb\x28\x7e\x85\xff\x52\xaa\xf1\xd5\x6e\x87\xac\x2d\xff\x37\xd3\xbb\x72\x25\xb5\x7c\x18\x86\x41\xb0\x1a\x01\x36\x13\x18\x32\x29\xb6\x25\x22\x6a\x14\xdc\x80\x63\xf6\xdb\xfb\xad\x0f\xbd\xc4\xa0\x54\x57\x8b\x56\xea\x19\x2f\x84\x9e\x84\xc3\xe9\x74\x2e\xb5\x62\xd4\x93\xd1\xdc\x39\x26\x64\x9e\x56\x21\x32\x81\x05\x49\xe7\xd8\x66\x6a\xea\x39\xb1\xd0\x56\x93\x82\x3c\x7f\x53\x8c\xaf\x05\xb5\xd2\xae\x92\x70\x28\xfe\x36\x1e\x5d\xda\xe5\x15\x5c\x4b\x4a\x5b\xfe\xb7\xc8\x58\xf8\x9e\x70\x31\x21\xa9\x7f\xa8\xd7\x09\x8a\x61\xab\x66\xec\xad\x8b\x96\xda\x96\xf5\x1f\x4b\xc3\x8a\x7c\x8c\xad\x50\xae\x97\xd4\x65\x7c\x33\x4f\x82\x8a\x6d\x37\x09\xec\xbc\x54\x6d\x13\x35\x85\x79\x6d\x89\xbf\x25\xf7\x17\xab\x8e\x25\x9f\x47\xd2\x0a\xd9\xa4\x2d\x9a\x40\xa1\xc8\x4b\x9a\xa6\x4a\x8f\x05\x72\x36\x44\x34\xe9\x56\xca\xe6\xdf\x4a\x27\x0a\xd1\x84\x97\xf3\x29\x72\x1a\x95\x9c\x6c\xd2\x3c\x89\xe3\x1d\x94\x5f\x0a\xed\x34\x8e\x77\x16\x5a\xbb\x94\x1c\xe6\x9d\xbd\xdb\x4e\xc5\xfb\x76\x72\x6c\xda\x93\xe7\x1d\x6e\x37\xf1\x4f\x83\x82\xcd\x72\x66\x6e\x2c\xc5\x59\x6a\x5b\x55\x36\xd6\x71\xb7\x58\x37\xbe\x6d\x97\x5c\x61\xae\x69\x79\x2b\x0d\x95\x45\x54\xad\xab\x4f\x46\xe0\xa3\x99\x4a\x45\x24\x75\x42\xc4\x0a\x0e\x4d\x91\xf0\x56\x0b\x69\x06\x84\x86\xed\x6f\x50\xea\xb6\xd2\x34\x09\x77\x8d\x00\x55\x2a\x33\x26\x6a\x66\x17\x58\x7e\x57\x1a\xae\x70\xdb\xbc\xda\x7d\x76\x22\xc6\xe5\x3c\x4d\xbf\xee\x00\x41\xe5\xa3\xab\x98\xb2\x44\x72\x09\xfc\x64\x57\xbe\x98\xce\xe4\x63\x51\x60\x34\xeb\x2e\x3b\xa6\x2c\xbb\x5c\x30\x2a\x1f\xc2\x8b\x07\x8c\x5a\x8a\xac\x03\x8e\x5b\x57\x06\x3c\x4b\xd3\x1b\x12\xdd\xf9\x05\x2a\x29\xa1\xa7\x8b\x9a\x34\xa8\xb8\x88\x6f\x51\xe8\xd2\xe9\xe8\x10\x90\x49\x0d\xc2\xb2\xb9\x84\x44\xe7\x29\x15\x79\x4d\x1b\xa0\x1e\x69\xc0\x8e\x56\x5a\x13\x7a\xd4\xd1\x54\x2d\xf7\xa1\xc9\x7d\x96\x98\x53\x61\x61\xf8\xfe\xf5\xfb\x0a\x92\x2b\xd4\xd0\xb4\x5c\x8e\xd3\x6c\x81\x3a\xba\x61\x43\xef\x01\xbc\xb5\x40\x4f\xaf\xd8\x23\xce\xa9\x4b\xef\x46\x3d\xbc\xaa\xca\x48\xd4\x80\x66\x81\xbc\x3c\x0f\x20\x50\x0e\xe8\xdd\x40\x39\xd3\xb1\x15\x54\x58\xa5\x06\x71\xfa\x3b\x33\x69\xac\x47\x61\x20\xa4\xf1\xfa\x02\x7f\xc3\x12\xae\x8b\x4a\x9c\xce\x52\x22\x5b\x0f\xc5\x8e\xa2\x4c\xed\x4f\xd2\xb8\xab\x84\xfe\xd2\x1a\x3c\xd6\xaa\x0c\xd4\x65\x06\x1a\x1c\x6d\x03\x4d\xc3\x48\x2d\x76\x3c\xc7\x14\x5b\xb0\xa3\x61\x52\x23\x48\xd7\x4d\x42\x43\x6e\x2b\x1c\x85\xe1\x87\xbf\x3b\x73\xaf\x8c\x3e\xf2\xfc\xba\x42\x54\xfb\x2e\x77\x63\x96\xc3\xc6\x7a\x8e\xe3\xed\xe5\x79\xdb\xbb\x5e\x23\xbd\x63\x38\xc6\x34\xf9\x88\x89\x75\x3c\xe5\x03\xda\xc9\x04\xa6\x09\x70\x4c\x90\x23\x8b\x50\x7b\x9b\x1e\xf0\x69\x74\x3e\x3a\x81\xb9\x40\x18\x7d\xb4\x07\xa9\xba\x08\x23\x37\xd9\x02\x6d\x0d\xd2\xd4\xe3\x9e\x6a\xdc\x5b\xf0\x0d\xb9\xef\x6d\x17\x4d\x45\xd6\x34\xb9\xa7\x2e\x77\xd1\x66\x7b\x72\xae\x1d\x32\x18\x35\x8f\x9e\x29\xb6\xfd\xe8\x51\x68\x4d\x05\xbb\xd9\x7c\x37\x65\x77\x0c\xcd\x11\xf1\xd3\x83\xd7\xca\xfc\xed\xc2\x16\x1a\x64\xbf\xba\x09\xd5\xda\xac\x2c\xbf\x97\xc0\xd5\x38\x3e\xd3\x11\x69\xf4\x7a\xa4\xea\xd6\xf7\xaf\x47\x65\xf0\x59\x87\x3a\x37\x5a\xd3\xf7\xaa\xf1\x9d\x14\xf5\x9d\xe8\x69\x7d\x82\x51\xda\x5a\x97\x60\x36\xe5\x8d\x27\xa9\xe1\xa9\x7a\x78\x3e\xd7\xab\x27\x86\xfd\xf2\xc2\x0e\x69\x61\x63\x56\x70\xca\x84\xb6\xd0\x6d\xb6\xd6\x28\xcd\x9c\x1c\xe0\x1c\xd0\xf5\x30\xfc\xcc\xe8\x97\x39\x3e\x45\xd1\x34\x69\x1e\x20\xeb\x73\xdc\xad\x2d\x6e\xdd\xb9\x6e\x44\xd8\xcf\x12\x52\xca\xee\x34\x0f\xaa\x5a\x80\x5f\xbb\x66\x57\xc5\x01\xef\xaf\x5d\x90\x19\xbc\x88\x41\x27\x87\x08\x05\xf8\x6f\xe1\x55\xd0\xed\x03\x0b\x5c\x2b\xfe\x6a\x8e\x6a\x95\xd5\xbe\xd9\xe9\x39\x03\x91\x76\x81\xed\xad\x57\x25\xc1\x72\x66\xe5\x04\x17\xbf\x6c\x7d\x00\x79\x75\x7c\x1d\x04\xe1\xb7\xb4\xfa\x67\x0d\x20\xbb\x89\xaf\xd8\xff\x7a\x09\xee\x9a\x74\x83\xf0\x94\xc5\x7e\x10\x0e\xc5\x4e\x61\xec\x1b\x2b\x80\x24\x09\x46\x12\xe3\xf2\xec\x96\xa3\xd0\xef\x7e\x4f\x8b\x8e\x06\x63\x7b\x13\xa4\x89\x7e\xfb\x66\xe9\x06\xf0\x97\x5d\x22\xdb\xd6\x74\x0f\xb4\x8c\x39\xa1\x4c\xea\xc0\xb3\x9c\x8a\xdb\x13\xa8\xbd\xc1\x5a\x0d\x34\xfe\x8b\x45\x00\x24\xe5\x48\xe2\x47\x88\x32\xc6\x34\x8b\x2a\xfe\x10\x88\x69\xa2\xc3\xa2\x2c\x02\x54\x35\xad\x6b\xd4\x9f\xd7\xf6\x59\x1d\xfb\x54\xc0\x5e\x15\x6c\xf6\x88\x40\x9f\x3c\xb9\xf0\xbc\x00\xe8\xc7\x8d\x97\x20\xf6\x1d\xbf\x1b\xd9\xaa\x37\x21\x7b\x46\xbd\x27\x87\x3d\xcb\x7e\x89\xcb\xcd\x73\x1f\xf4\x2e\x96\x34\xd6\x22\xc9\xfb\xd0\x86\x2d\xcc\x18\x54\x83\x68\xec\x5c\xa7\xd0\xa9\x48\x65\xa0\x97\x1c\x13\x88\x38\xea\x6b\x0b\xaa\x68\x35\xa7\x48\x94\xc1\x4d\x26\x27\x70\x4f\x1e\x85\x5b\xbc\x36\xcf\xc2\x9f\xff\x3c\xc7\xb9\x0f\x64\x43\xd4\x90\x09\xe4\xeb\xc2\xcd\xba\x10\x55\xdc\x30\xd9\xb5\x82\xdd\xa9\x80\xae\x59\xcd\xa2\x32\x8c\x42\x63\x85\xe6\xed\x36\xfe\xa9\x5b\xfd\xc5\xd5\xf1\x75\x1f\x16\x57\xaf\xae\xb7\xa8\xab\xbe\x15\x50\x5d\xf1\xa6\x91\xd5\xcf\xff\x41\xee\x7f\x72\xea\xdf\xef\xf5\xe3\xf7\x00\x7d\xdb\x94\x5b\x9d\x81\x7c\x25\x00\xea\x9b\x3f\x6a\xf7\x1f\x2c\xf7\xdf\x2a\x24\xce\xc2\x11\xf7\x83\x27\xa3\x87\xb5\xb0\xe8\xf7\x35\xad\x56\xcb\x52\xc0\x66\xd6\xd7\x62\xde\x15\xdd\x7c\x17\x16\xf6\x23\xa3\x9c\x8c\x21\x64\x49\x4b\x55\xf5\x62\xf1\x24\xa8\x73\x87\x8f\x62\xcb\x7d\x6c\x84\x44\x4e\xe9\x59\xa6\xf2\xcd\xae\x5e\xde\x69\xb1\x3e\x54\x5e\x34\x2b\x7d\x50\x83\x0a\x51\xe8\x58\x48\xae\x7c\x35\x3c\x95\x19\xf5\x77\x60\x5b\x95\x05\xd5\xe1\xb0\x78\x9e\x53\xdf\x96\x97\x98\x45\x90\xda\x8d\x33\x67\xb1\x96\x1b\x08\x75\x70\x53\xd0\xf9\x5f\xae\x51\x9f\x5c\x54\x59\xa2\xb5\xb0\xb3\xaa\x83\x6f\x28\x9b\x8d\xa2\xf9\xdd\x8a\xcf\xf5\x72\x72\xcc\xeb\x8f\x70\xfd\x43\x87\x6b\x6b\x09\x8d\xcb\x8f\xe5\xc5\x6f\xf9\x10\x9e\x65\xd3\x29\x95\xfe\x6e\xf7\xb9\xab\xbe\xfa\xf7\x0a\xcd\x0f\x15\x8c\xc7\xda\xb2\xd8\xf9\x70\x80\xd1\xb4\x63\x3e\xf9\xb0\x1f\x33\x6c\xfc\xfa\xc3\x85\x6e\xf6\xbe\x41\xcf\x04\xe1\x32\xa9\x94\x1d\xf6\x52\x16\x8d\x57\x6f\x31\xda\x70\x4b\xe3\x66\x0e\x5a\x9f\x80\x2c\xc6\x6b\x4d\x29\x46\x8e\x35\x5b\x11\xa5\x91\x96\x62\x3a\x3a\x84\xe2\x37\x15\x9a\xb9\x3b\x76\x9f\x31\x20\xd2\x7c\x0c\x33\xcb\x28\x93\x55\x61\xdc\x7c\xb3\x68\x77\xa3\xef\x67\x96\xdc\x2a\x3e\x95\xe9\x17\xec\x35\xaf\x63\x94\x1f\x99\xd8\x5f\xff\x0d\x00\x00\xff\xff\x5b\xd4\x2c\x15\x23\x34\x00\x00") +var _templateDialectSqlUpdateTmpl = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xc4\x58\xdd\x6f\xdb\xc8\x11\x7f\x96\xfe\x8a\x39\xc2\x31\x44\x43\xa6\x9d\xa0\x28\x50\x19\x2a\xe0\xb3\x13\x40\xed\x9d\x93\x5a\xf1\x3d\x5c\x60\x1c\xd6\xe4\x50\xda\x7a\xb5\xa4\x77\x97\x3e\xa7\x82\xfe\xf7\x62\xf6\x83\x5f\x92\x1c\xbb\xd7\xe0\x1e\xe2\x88\x9c\x9d\x9d\x99\xdf\x7c\x73\xbd\x3e\x39\x1a\x5e\x14\xe5\x57\xc5\x17\x4b\x03\xef\x4e\xdf\xfe\xed\xb8\x54\xa8\x51\x1a\xf8\xc0\x52\xbc\x2b\x8a\x7b\x98\xc9\x34\x81\x73\x21\xc0\x1e\xd2\x40\x74\xf5\x88\x59\x32\xfc\xbc\xe4\x1a\x74\x51\xa9\x14\x21\x2d\x32\x04\xae\x41\xf0\x14\xa5\xc6\x0c\x2a\x99\xa1\x02\xb3\x44\x38\x2f\x59\xba\x44\x78\x97\x9c\x06\x2a\xe4\x45\x25\xb3\x21\x97\x96\xfe\xd3\xec\xe2\xfd\xd5\xfc\x3d\xe4\x5c\x20\xf8\x77\xaa\x28\x0c\x64\x5c\x61\x6a\x0a\xf5\x15\x8a\x1c\x4c\x4b\x98\x51\x88\xc9\xf0\xe8\x64\xb3\x19\x0e\xd7\x6b\xc8\x30\xe7\x12\x21\xca\x38\x13\x98\x9a\x13\xfd\x20\x4e\xaa\x32\x63\x06\x23\xd8\x6c\xe8\xc4\x41\x79\xbf\x80\xc9\x14\x0e\x92\x79\x5a\x94\x98\x7c\x62\xe9\x3d\x5b\x60\xa0\xde\x55\x5c\x90\xb6\x93\x29\x94\x4c\xa7\x4c\xd4\x07\x7f\xf4\x14\x7f\x50\x61\x8a\xfc\xd1\x9d\xac\x7f\xd7\xec\xfe\x50\x21\x91\xe8\x4b\xa6\xe7\x55\x9e\xf3\xa7\xe6\x40\xf4\x51\x06\x95\x8e\xe1\xe0\x3f\xa8\x0a\x3a\x78\x0a\x9b\xcd\x7a\x0d\x3c\x77\xac\xf6\xc1\x11\xa7\x10\x49\x2e\x22\xf7\x0a\x65\x56\xb3\x2a\x34\xc4\x19\xc9\x68\x17\x2f\x51\xc9\xd6\xeb\xa0\x61\x9b\x7f\x98\x57\x32\x85\x51\xc7\x9a\xcd\x06\x8e\xda\x38\x6c\x36\x31\xe8\x07\x31\x67\x8f\x38\x4a\xcd\x13\xa4\x85\x34\xf8\x64\x92\x0b\xf7\x7f\x1c\xd8\x0d\x71\x76\xc4\xdb\x6b\x92\x2b\xb6\xf2\xba\xa0\xd0\xf4\x8b\x4b\x53\x6b\x30\x06\x54\x8a\xfe\x15\x2a\x86\xf5\x70\xa0\x4b\x4c\xc9\x98\x43\xfd\x20\x16\x8a\x95\xcb\xe4\xc6\xfa\x6e\x5e\x62\xba\x1e\x0e\x06\x57\x45\x86\x93\x16\x95\x9e\x03\x6d\xf0\x99\xdd\x09\x9c\x80\x95\xda\x38\x35\xb1\xaf\xc7\x74\xe0\xa2\x10\xd5\x4a\xea\xed\x23\x9e\x60\x0f\xcd\x2e\xdb\x02\x3e\x70\x14\x59\x2d\x61\x40\x80\x37\x06\xda\x57\x83\x5f\x98\xa8\xbc\xd8\x16\x88\x09\xcf\xc6\x35\x8b\x87\x9b\x1e\x3f\x7f\x2d\x71\x02\x39\x5d\x9b\x58\x35\x66\x97\x09\xbd\x23\x3c\xb5\xf1\x60\x39\x4e\xa7\xd5\xb6\xb6\x81\xcd\x72\x30\x69\x02\x83\xfd\x4b\x7f\x36\xc3\xa0\xa8\x2c\x4c\x4b\x59\x9e\x43\xa9\x09\xde\xbe\xae\xa5\xc2\x8c\xa7\xcc\xa0\x3e\x03\x81\x72\x54\xea\x18\xfe\x0e\xa7\x60\x8d\x26\x9f\x24\x9f\xc2\x09\x98\x02\x05\xcd\x48\xa3\xb0\xf9\x08\x47\xfa\x41\x24\x73\xff\x14\x3b\x96\x41\x5e\x28\xe0\x36\x31\x98\x5c\x20\x49\x75\xef\x07\xa5\xfe\xc2\x6f\x6b\xe6\xd8\xbe\xb4\xc0\xd0\x1f\xaf\x77\x40\x8b\x7e\x3b\xfe\x83\xdf\xc6\x70\x90\xbb\xa4\xb5\x1e\xd1\x1e\x4e\x6f\x66\xa1\x60\x64\x4d\xcd\x93\xd9\x6a\x55\x19\xf2\x78\x4c\x4f\x2e\x7a\x2e\x31\x67\x95\x30\xc1\x05\x3c\x87\x47\xf2\xd9\x2e\x24\xe8\x39\x0f\x99\x6e\x45\xc1\x66\x73\xe6\xcf\xff\x30\x05\xc9\x45\x30\xc5\xe2\xe2\xb4\x49\xe6\x36\xcb\x58\x59\xa2\xcc\x46\x3d\xc2\x78\x7f\x38\x6d\x87\x43\xbe\x2f\x18\xea\x38\x3b\xb2\xba\x84\x97\xcf\xc5\x48\xbe\x15\x21\x83\xc1\xa6\x05\x79\x1d\xcd\x5e\xe8\x55\xb5\x42\xc5\xd3\x3a\xb0\x9f\xc3\x89\x65\xd9\x2b\xa0\xea\x60\x75\x9e\x65\xbb\xb1\x3a\xcf\xb2\x67\xb1\x7a\x0d\x58\xbb\xd1\x7a\x35\x5c\x01\xaf\x16\x60\x4d\x2e\x6f\x3f\x39\x30\x3f\x96\x86\x17\x92\x89\x56\xbc\xf5\xe1\x4b\x05\x32\xb5\x13\xc0\x5d\xd1\x75\x41\xa7\x77\x63\x66\x49\xff\xaf\x08\xfb\x23\xc1\xd4\x4f\xdc\x3d\x49\x8c\x2e\x89\xdf\x67\x0b\xf4\x39\x1c\x70\xc3\xe4\x46\xf2\x87\x2a\xd4\xd5\x7d\xa0\xa1\x8d\x3b\x4c\xe6\x46\x55\xa9\xe9\xa1\x46\x77\xfd\xce\xcd\x12\xf0\xc9\x90\x02\x07\x10\x91\xa4\x88\xe4\x86\xa8\x5e\xaf\xc1\xe0\xaa\x14\x54\xcb\x3a\x53\x42\x86\x39\xda\xc3\x49\x38\xdb\x2b\xdd\x16\x77\xab\xf9\x4e\x8f\xb4\x28\x63\xa0\x9b\xe2\x50\xd7\xec\x3d\xae\xf9\x79\xd3\x64\x91\xe1\xce\x4a\xac\x70\x55\x3c\xee\xb6\xd1\x95\x66\xcb\xd9\xaa\xce\xcf\xda\x1c\x51\x7f\xd4\x11\x18\x55\x21\x44\xbf\xa2\x2a\x22\x3f\x4d\xfc\xd9\x68\x84\x7b\x9e\xc3\xc2\x81\xb0\x55\x60\x76\xa1\xf0\x87\x40\x78\x39\x06\x5d\x08\x5a\x76\x6e\xd7\xb4\xfa\x7d\x63\xfd\x8e\xcc\xe8\xcc\x12\xad\x39\x6a\x0a\x87\x9d\xe1\x29\x2d\x64\xce\x17\xdb\x43\x86\x7b\x4f\xcc\x56\xe8\x3c\x65\x92\xb2\x5b\xc3\x14\xbe\xdc\x72\x69\x50\xe5\x2c\xc5\xb5\xcf\x8f\x43\x37\x9e\xd9\x4e\x49\x03\xc4\x8d\x46\x75\x69\xe7\x65\xd2\x88\xfa\xf8\x55\x25\xc4\x4c\x9a\xbf\xfe\xa5\x19\xd7\xc2\xb4\x41\x24\xba\xbb\x3d\x40\xae\x5d\x25\x78\x41\xa3\xb6\xb2\x0f\xf2\xce\x2d\x0d\x73\x8d\x69\x6d\xc9\xb9\xd6\x7c\x21\xc3\xb0\x61\x8b\xb8\x86\x24\x49\x5a\x36\xc5\x6e\x6e\x74\xa6\xf1\x1c\x56\x63\x90\x24\x99\xe2\xc3\x31\xc4\x63\xfb\xd0\x85\x26\x3e\x83\x95\x6d\x4f\x3e\x7f\x14\x9a\x4a\x49\xc8\x57\x26\x79\x4f\xf7\xe5\xa3\x68\xc5\xf5\x8a\x99\x74\x09\xb2\x5a\xdd\xa1\xa2\x8d\x43\xa7\x4c\xba\xd6\xa6\x27\xf0\x26\xa3\x0b\xde\x64\xd1\xd8\x0a\xad\x23\x3b\xb8\x94\x51\x04\xf6\x01\x1e\x15\xca\xbd\x9c\xe9\xb9\x51\x5c\x2e\xc2\xd3\xcd\xcd\xec\x32\x6e\x27\x59\x2f\x90\x67\xd9\x53\x04\xa7\x10\x59\x3c\x23\xcb\x05\xd1\x35\x9a\x28\x44\xcb\x37\x32\x99\x59\x28\x73\xc7\xbd\x27\x9b\x7b\x15\x6a\xe0\xba\x26\x14\xf7\x04\xa8\x33\xfb\xcb\xe9\x6d\x32\x3a\xea\x04\x49\x1c\xda\xdb\x0f\xc5\x7d\xe8\x5b\x3b\xe0\xac\x24\x3e\x95\x98\x1a\xcc\xc0\x90\xeb\xdf\x7c\x06\x9a\x0f\xad\x46\xc0\x09\x45\x2b\xa1\x3b\x99\x04\xe3\xc8\xda\x69\xd8\x2b\x3a\xf0\x6d\x36\xda\xa8\xb4\x90\x8f\xc9\x87\x42\xad\x98\x99\x49\xe3\xfc\x9e\x58\xe5\xc6\xf0\xf6\x34\xde\x0e\x63\x1f\x7c\xed\x93\x71\xb3\x10\x6d\x01\xe3\x23\xaf\x06\xe1\xed\xe4\xb6\x17\xf1\x7c\x5f\xc4\xef\x73\xe5\x01\x6f\x7c\x99\x7f\x1f\x4f\xd6\x4f\xde\x1b\x92\x8b\x17\xd4\x1f\x9e\xdb\x6d\x6c\x0a\xbd\xe5\x8b\xea\x27\xad\x7e\xe3\xad\xf2\x93\x29\xfa\x35\x06\xca\xb0\xf8\xcc\x72\x37\x83\x5f\x37\xa6\xea\x7e\x6e\xea\xb5\x6f\xa7\x20\xfd\xbf\x4a\x6a\x75\x94\x14\x95\x0a\xc1\xcb\xf5\xfc\x5f\x3f\xd9\xd1\x45\x31\x2e\x8d\x8d\xc9\x11\x2a\x15\x9f\x41\x08\x5a\xa7\x0b\x31\xf9\x0a\xe4\x51\xab\x57\x6f\xaf\xb0\x5d\xac\x5a\xb4\x60\x0b\xa1\x6b\xb7\xfd\xb0\x55\xef\xf9\x0c\x51\xb7\x93\x80\x7e\x98\x86\xdc\xe7\x05\xea\x18\x70\x4c\x34\x3a\xd5\xdd\x82\x89\x16\x86\xba\x6b\x14\x93\x06\x39\xd7\x24\xaf\x51\x84\xc8\xa6\xa2\x3a\x93\x8f\xa8\xb4\x5f\x4a\x31\x99\x69\xff\xc2\x93\xf7\x2c\xca\xee\xb0\x25\xf6\x66\xbd\xf6\xe2\xec\x66\xb5\x9f\xdf\xfd\x1c\x92\x6a\xeb\x86\x4f\xff\x6c\xb1\x37\x19\xf8\xe5\x56\xdb\xc4\x5d\xef\x11\xec\x84\xb4\x58\xa1\x69\x34\xa4\xc4\x8f\x3c\xe3\xc1\xa2\x39\x8a\xfc\x1a\xf3\xda\x1e\xb5\x40\x33\xe9\xe1\xe5\xde\xae\xdd\x4e\x4f\xe0\x3d\xb3\xd7\xf7\x87\x64\x74\x43\xf2\xcb\x76\x73\x7f\x78\x1b\x49\x7f\xc5\xb7\xf6\x74\x5b\x24\x42\x14\xd8\x1c\x70\x91\x4c\x45\xf2\x7e\x0c\xbf\x35\x7b\xb4\x1b\x95\xea\x89\xe7\x80\x67\x36\x80\x6a\x51\x2e\x7c\x1c\xf1\xe4\x08\x2e\x0a\x72\xbb\x01\x87\xfb\x31\xcf\x34\x98\x25\x33\xc0\x14\x82\x36\x85\xc2\x0c\x98\x06\x2e\x4d\xf8\xd2\x96\x31\xc3\xee\x98\x46\x38\x3a\x69\x5f\xe5\x5b\x9a\x5b\xb1\x79\xd6\x6e\x6b\xb1\x7d\xd1\xaa\xc9\x16\x9d\x7b\x97\xe0\x93\x29\x84\x12\x7d\x6e\x0a\x3e\xba\xaf\x1b\x46\x37\x7f\x5b\x7d\xc3\x86\x86\x43\xe2\xd7\x4e\xea\xed\xda\x33\x06\x36\x53\x12\xe7\x68\x8f\x5c\x3d\x85\x6d\x91\xc6\x70\xbf\x3d\x85\xb5\x7e\xee\x4b\xdb\x4e\xd5\xad\x53\x97\xb7\x53\x77\x96\x3d\x39\xbc\x2c\x29\x6f\x93\xdc\xdc\xda\x10\xfd\xd7\xba\x40\xbe\x46\xd3\x10\xdd\xfa\x38\xd3\xff\x98\x7f\xbc\xaa\x8b\xd9\xae\x56\x4c\x28\x71\xd8\x6c\xa8\x23\x6f\xcd\x55\xf1\x59\xd3\x8f\x5f\xdb\x8d\xfd\x65\x2e\xd2\x43\x63\x6e\xc9\xb3\x00\xba\x84\xae\xbf\x0e\x78\x3f\x1e\x1e\xda\x61\xcb\x2d\xdc\xad\xd1\xdc\x7b\x7b\x32\x85\x7f\xeb\x42\x26\x37\x72\xc5\x94\x5e\x32\xe1\x4f\x8e\xdd\xa4\xeb\x9b\xbd\x93\xdf\xdd\x7b\xb6\xca\xfd\x3e\xbb\xfc\xc5\xbb\x4c\x99\xc0\x9b\xc7\xc8\x46\x52\xdc\xff\xd8\x54\x77\x28\xeb\x1e\x59\x09\x61\x61\x21\x1f\xb5\x60\x3d\x7e\x8d\x3b\xea\x4b\xbe\xbf\x33\x7c\xd8\x2c\x99\xfe\xa4\xd0\x7e\x5f\xae\x85\x47\xfa\x41\x44\x3e\x4f\x7a\x3e\x4b\x7e\x61\x82\x67\xb0\xee\x7d\x05\xba\xe2\x42\x50\xf5\x6f\x4f\x22\xcf\x79\x06\xa6\x20\xf1\xf7\x51\xf3\x55\x81\x0c\x76\x9c\x47\xdf\x66\xed\x06\xae\x23\x44\x56\xbd\xa8\x33\xda\xb4\xc6\xd2\x17\x28\xf4\xd2\x5b\x43\x09\xe9\x89\xd8\x13\xdc\xeb\xfe\x54\xba\x47\xba\x8b\xe9\xfe\x92\xbb\xb7\xe4\xfc\x37\x00\x00\xff\xff\xc4\x13\x0d\x29\x74\x19\x00\x00") func templateDialectSqlUpdateTmplBytes() ([]byte, error) { return bindataRead( @@ -816,7 +816,7 @@ func templateDialectSqlUpdateTmpl() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "template/dialect/sql/update.tmpl", size: 13347, mode: os.FileMode(420), modTime: time.Unix(1, 0)} + info := bindataFileInfo{name: "template/dialect/sql/update.tmpl", size: 6516, mode: os.FileMode(420), modTime: time.Unix(1, 0)} a := &asset{bytes: bytes, info: info} return a, nil } diff --git a/entc/gen/template/dialect/sql/create.tmpl b/entc/gen/template/dialect/sql/create.tmpl index eb683e247..e88a55ea3 100644 --- a/entc/gen/template/dialect/sql/create.tmpl +++ b/entc/gen/template/dialect/sql/create.tmpl @@ -73,7 +73,7 @@ func ({{ $receiver }} *{{ $builder }}) sqlSave(ctx context.Context) (*{{ $.Name {{- if and $.ID.UserDefined (or $.ID.IsString $.ID.IsUUID) }} {{- /* Do nothing, because these 2 types must be supplied by the user. */ -}} {{- else }} - {{- if and $.ID.UserDefined }} + {{- if $.ID.UserDefined }} if {{ $.Receiver }}.ID == 0 { {{- end }} id := spec.ID.Value.(int64) diff --git a/entc/gen/template/dialect/sql/update.tmpl b/entc/gen/template/dialect/sql/update.tmpl index d32055851..4cafbdf69 100644 --- a/entc/gen/template/dialect/sql/update.tmpl +++ b/entc/gen/template/dialect/sql/update.tmpl @@ -13,327 +13,183 @@ in the LICENSE file in the root directory of this source tree. {{- $ret := "n" }}{{ if $one }}{{ $ret = $.Receiver }}{{ end }} func ({{ $receiver }} *{{ $builder }}) sqlSave(ctx context.Context) ({{ $ret }} {{ if $one }}*{{ $.Name }}{{ else }}int{{ end }}, err error) { - var ( - builder = sql.Dialect({{ $receiver }}.driver.Dialect()) - selector = builder.Select({{ $.Package }}.{{ if $one }}Columns...{{ else }}{{ $.ID.Constant }}{{ end }}).From(builder.Table({{ $.Package }}.Table)) - ) - {{- if $one }} - {{ $.Package }}.ID({{ $receiver }}.id)(selector) - {{- else }} - for _, p := range {{ $receiver }}.predicates { - p(selector) + spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: {{ $.Package }}.Table, + Columns: {{ $.Package }}.Columns, + ID: &sqlgraph.FieldSpec{ + {{- if $one }} + Value: {{ $receiver }}.id, + {{- end }} + Type: field.{{ $.ID.Type.ConstName }}, + Column: {{ $.Package }}.{{ $.ID.Constant }}, + }, + }, + } + {{- if not $one }} + if ps := {{ $receiver }}.predicates; len(ps) > 0 { + spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } } {{- end }} - rows := &sql.Rows{} - query, args := selector.Query() - if err = {{ $receiver }}.driver.Query(ctx, query, args, rows); err != nil { - return {{ $zero }}, err - } - defer rows.Close() - {{ $typ := "int" }}{{ if $.ID.UserDefined }}{{ $typ = $.ID.Type }}{{ end }} - var ids []{{ $typ }} - for rows.Next() { - var id {{ $typ }} - {{- if $one }} - {{ $.Receiver }} = &{{ $.Name }}{config: {{ $receiver }}.config} - if err := {{ $.Receiver }}.FromRows(rows); err != nil { - return {{ $zero }}, fmt.Errorf("{{ $pkg }}: failed scanning row into {{ $.Name }}: %v", err) - } - {{- if and $.ID.IsString (not $.ID.UserDefined) }} - id = {{ $.Receiver }}.id() - {{- else if or $.ID.IsUUID $.ID.IsInt }} - id = {{ $.Receiver }}.ID - {{- else }} - id = int({{ $.Receiver }}.ID) - {{- end }} - {{- else }} - if err := rows.Scan(&id); err != nil { - return {{ $zero }}, fmt.Errorf("{{ $pkg }}: failed reading id: %v", err) - } - {{- end }} - ids = append(ids, id) - } - {{- if $one }} - switch n := len(ids); { - case n == 0: - return {{ $zero }}, &ErrNotFound{fmt.Sprintf("{{ $.Name }} with id: %v", {{ $receiver }}.id)} - case n > 1: - return {{ $zero }}, fmt.Errorf("{{ $pkg }}: more than one {{ $.Name }} with the same id: %v", {{ $receiver }}.id) - } - {{- else }} - if len(ids) == 0 { - return {{ $zero }}, nil - } - {{- end }} - {{/* if there's something to update, start a transaction. */}} - tx, err := {{ $receiver }}.driver.Tx(ctx) - if err != nil { - return {{ $zero }}, err - } - {{- if $.Fields }} - var ( - res sql.Result - updater = builder.Update({{ $.Package }}.Table) - ) - {{- if and (not $.ID.IsInt) $.ID.UserDefined }} - idface := make([]interface{}, len(ids)) - for i := range ids { - idface[i] = ids[i] - } - updater = updater.Where(sql.In({{ $.Package }}.{{ $.ID.Constant }}, idface...)) - {{- else }} - updater = updater.Where(sql.InInts({{ $.Package }}.{{ $.ID.Constant }}, ids...)) - {{- end }} - {{- range $_, $f := $.Fields }} + {{- range $_, $f := $.Fields }} {{- if or (not $f.Immutable) $f.UpdateDefault }} if value := {{ $receiver }}.{{ $f.BuilderField }}; value != nil { - {{- if $f.IsJSON }} - buf, err := json.Marshal(*value) - if err != nil { - return {{ $zero }}, err - } - updater.Set({{ $.Package }}.{{ $f.Constant }}, buf) - {{- else }} - updater.Set({{ $.Package }}.{{ $f.Constant }}, *value) - {{- end }} - {{- if $one }} - {{ $.Receiver }}.{{ $f.StructField }} = {{ if not $f.Nillable }}*{{ end }}value - {{- end }} + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.{{ $f.Type.ConstName }}, + Value: *value, + Column: {{ $.Package }}.{{ $f.Constant }}, + }) } {{- if $f.Type.Numeric }} if value := {{ $receiver }}.add{{ $f.BuilderField }}; value != nil { - updater.Add({{ $.Package }}.{{ $f.Constant }}, *value) - {{- if $one }} - {{- if $f.Nillable }} - if {{ $.Receiver }}.{{ $f.StructField }} != nil { - *{{ $.Receiver }}.{{ $f.StructField }} += *value - } else { - {{ $.Receiver }}.{{ $f.StructField }} = value - } - {{- else }} - {{ $.Receiver }}.{{ $f.StructField }} += *value - {{- end }} - {{- end }} + spec.Fields.Add = append(spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.{{ $f.Type.ConstName }}, + Value: *value, + Column: {{ $.Package }}.{{ $f.Constant }}, + }) } {{- end }} {{- end }} {{- if $f.Optional }} if {{ $receiver }}.clear{{ $f.BuilderField }} { - {{- if $one }} - {{- if $f.Nillable }} - {{ $.Receiver }}.{{ $f.StructField }} = nil - {{- else }} - var value {{ $f.Type }} - {{ $.Receiver }}.{{ $f.StructField }} = value - {{- end }} - {{- end }} - updater.SetNull({{ $.Package }}.{{ $f.Constant }}) + spec.Fields.Clear = append(spec.Fields.Clear, &sqlgraph.FieldSpec{ + Type: field.{{ $f.Type.ConstName }}, + Column: {{ $.Package }}.{{ $f.Constant }}, + }) } {{- end }} - {{- end }} - if !updater.Empty() { - query, args := updater.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return {{ $zero }}, rollback(tx, err) - } - } - {{- else if $.Edges }}{{/* ent without fields, but with edges */}} - var res sql.Result {{- end }} {{- range $_, $e := $.Edges }} - {{- if $e.M2M }} - if len({{ $receiver }}.removed{{ $e.StructField }}) > 0 { - {{- $a := 0 }}{{ $b := 1 }}{{ if $e.IsInverse }}{{ $a = 1 }}{{ $b = 0 }}{{ end }} - eids := make([]int, len({{ $receiver }}.removed{{ $e.StructField }})) - for eid := range {{ $receiver }}.removed{{ $e.StructField }} { - {{- template "dialect/sql/update/convertid" $e -}} - eids = append(eids, eid) - } - query, args := builder.Delete({{ $.Package }}.{{ $e.TableConstant }}). - Where(sql.InInts({{ $.Package }}.{{ $e.PKConstant }}[{{ $a }}], ids...)). - Where(sql.InInts({{ $.Package }}.{{ $e.PKConstant }}[{{ $b }}], eids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return {{ $zero }}, rollback(tx, err) - } - {{- if $e.SelfRef }}{{/* M2M with self reference */}}{{/* TODO: use OR in the case above. */}} - query, args = builder.Delete({{ $.Package }}.{{ $e.TableConstant }}). - Where(sql.InInts({{ $.Package }}.{{ $e.PKConstant }}[{{ $b }}], ids...)). - Where(sql.InInts({{ $.Package }}.{{ $e.PKConstant }}[{{ $a }}], eids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return {{ $zero }}, rollback(tx, err) - } - {{- end }} - } - {{- else if $e.O2M }} - if len({{ $receiver }}.removed{{ $e.StructField }}) > 0 { - eids := make([]int, len({{ $receiver }}.removed{{ $e.StructField }})) - for eid := range {{ $receiver }}.removed{{ $e.StructField }} { - {{- template "dialect/sql/update/convertid" $e -}} - eids = append(eids, eid) - } - query, args := builder.Update({{ $.Package }}.{{ $e.TableConstant }}). - SetNull({{ $.Package }}.{{ $e.ColumnConstant }}). - Where(sql.InInts({{ $.Package }}.{{ $e.ColumnConstant }}, ids...)). - Where(sql.InInts({{ $e.Type.Package }}.{{ $e.Type.ID.Constant }}, eids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return {{ $zero }}, rollback(tx, err) - } - } - {{- else }}{{/* O2O or M2O */}} + {{- if $e.Unique }} if {{ $receiver }}.cleared{{ $e.StructField }} { - query, args := builder.Update({{ $.Package }}.{{ $e.TableConstant }}). - SetNull({{ $.Package }}.{{ $e.ColumnConstant }}). - Where(sql.InInts({{ $e.Type.Package }}.{{ $e.Type.ID.Constant }}, ids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return {{ $zero }}, rollback(tx, err) - } - {{- if $e.SelfRef }}{{/* O2O with self reference */}} - query, args = builder.Update({{ $.Package }}.{{ $e.TableConstant }}). - SetNull({{ $.Package }}.{{ $e.ColumnConstant }}). - Where(sql.InInts({{ $.Package }}.{{ $e.ColumnConstant }}, ids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return {{ $zero }}, rollback(tx, err) - } + {{- with extend $ "Edge" $e }} + {{ template "dialect/sql/defedge" . }} {{- end }} + spec.Edges.Clear = append(spec.Edges.Clear, edge) + } + {{- else }} + if nodes := {{ $receiver }}.removed{{ $e.StructField }}; len(nodes) > 0 { + {{- with extend $ "Edge" $e "Nodes" true "Zero" $zero }} + {{ template "dialect/sql/defedge" . }} + {{- end }} + spec.Edges.Clear = append(spec.Edges.Clear, edge) } {{- end }} - if len({{ $receiver }}.{{ $e.BuilderField }}) > 0 { - {{- if and $e.Unique $e.SelfRef }}{{/* O2O with self reference */}} - if n := len(ids); n > 1 { - return {{ $zero }}, rollback(tx, fmt.Errorf("{{ $pkg }}: can't link O2O edge \"{{ $e.Name }}\" to %d vertices (> 1)", n)) - } - for eid := range {{ $receiver }}.{{ $e.BuilderField }} { - {{- template "dialect/sql/update/convertid" $e -}} - query, args := builder.Update({{ $.Package }}.{{ $e.TableConstant }}). - Set({{ $.Package }}.{{ $e.ColumnConstant }}, eid). - Where(sql.EQ({{ $.Package }}.{{ $.ID.Constant }}, ids[0])).Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return {{ $zero }}, rollback(tx, err) - } - query, args = builder.Update({{ $.Package }}.{{ $e.TableConstant }}). - Set({{ $.Package }}.{{ $e.ColumnConstant }}, ids[0]). - Where(sql.EQ({{ $e.Type.Package }}.{{ $e.Type.ID.Constant }}, eid).And().IsNull({{ $.Package }}.{{ $e.ColumnConstant }})).Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return {{ $zero }}, rollback(tx, err) - } - affected, err := res.RowsAffected() - if err != nil { - return {{ $zero }}, rollback(tx, err) - } - if int(affected) < len({{ $receiver }}.{{ $e.BuilderField }}) { - return {{ $zero }}, rollback(tx, &ConstraintError{msg: fmt.Sprintf("\"{{ $e.Name }}\" (%v) already connected to a different \"{{ $.Name }}\"", eid)}) - } - } - {{- else if $e.M2M }} - values := make([][]int, 0, len(ids)) - for _, id := range ids { - for eid := range {{ $receiver }}.{{ $e.BuilderField }} { - {{- template "dialect/sql/update/convertid" $e -}} - values = append(values, []int{id, eid}, {{- if $e.SelfRef }}[]int{eid, id}{{ end }}){{/* self-ref creates the edges in both ways. */}} - } - } - {{- $a := 0 }}{{ $b := 1 }}{{ if $e.IsInverse }}{{ $a = 1 }}{{ $b = 0 }}{{ end }} - builder := builder.Insert({{ $.Package }}.{{ $e.TableConstant }}). - Columns({{ $.Package }}.{{ $e.PKConstant }}[{{ $a }}], {{ $.Package }}.{{ $e.PKConstant }}[{{ $b }}]) - for _, v := range values { - builder.Values(v[0], v[1]) - } - query, args := builder.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return {{ $zero }}, rollback(tx, err) - } - {{- else if $e.M2O }} - for eid := range {{ $receiver }}.{{ $e.BuilderField }} { - {{- template "dialect/sql/update/convertid" $e -}} - query, args := builder.Update({{ $.Package }}.{{ $e.TableConstant }}). - Set({{ $.Package }}.{{ $e.ColumnConstant }}, eid). - Where(sql.InInts({{ $.Package }}.{{ $.ID.Constant }}, ids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return {{ $zero }}, rollback(tx, err) - } - } - {{- else if $e.O2M }} - for _, id := range ids { - p := sql.P() - for eid := range {{ $receiver }}.{{ $e.BuilderField }} { - {{- template "dialect/sql/update/convertid" $e -}} - p.Or().EQ({{ $e.Type.Package }}.{{ $e.Type.ID.Constant }}, eid) - } - query, args := builder.Update({{ $.Package }}.{{ $e.TableConstant }}). - Set({{ $.Package }}.{{ $e.ColumnConstant }}, id). - Where(sql.And(p, sql.IsNull({{ $.Package }}.{{ $e.ColumnConstant }}))). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return {{ $zero }}, rollback(tx, err) - } - affected, err := res.RowsAffected() - if err != nil { - return {{ $zero }}, rollback(tx, err) - } - if int(affected) < len({{ $receiver }}.{{ $e.BuilderField }}) { - return {{ $zero }}, rollback(tx, &ConstraintError{msg: fmt.Sprintf("one of \"{{ $e.Name }}\" %v already connected to a different \"{{ $.Name }}\"", keys({{ $receiver }}.{{ $e.BuilderField }}))}) - } - } - {{- else }}{{/* O2O */}} - for _, id := range ids { - {{- if $.Type.ID.IsString }} - eid, serr := strconv.Atoi(keys({{ $receiver }}.{{ $e.BuilderField }})[0]) - if serr != nil { - return {{ $zero }}, rollback(tx, err) - } - {{- else }} - eid := keys({{ $receiver }}.{{ $e.BuilderField }})[0] - {{- end }} - {{- if $e.IsInverse }} - query, args := builder.Update({{ $.Package }}.{{ $e.TableConstant }}). - Set({{ $.Package }}.{{ $e.ColumnConstant }}, eid). - Where(sql.EQ({{ $.Package }}.{{ $.ID.Constant }}, id).And().IsNull({{ $.Package }}.{{ $e.ColumnConstant }})). - Query() - {{- else }} - query, args := builder.Update({{ $.Package }}.{{ $e.TableConstant }}). - Set({{ $.Package }}.{{ $e.ColumnConstant }}, id). - Where(sql.EQ({{ $e.Type.Package }}.{{ $e.Type.ID.Constant }}, eid).And().IsNull({{ $.Package }}.{{ $e.ColumnConstant }})). - Query() - {{- end }} - if err := tx.Exec(ctx, query, args, &res); err != nil { - return {{ $zero }}, rollback(tx, err) - } - affected, err := res.RowsAffected() - if err != nil { - return {{ $zero }}, rollback(tx, err) - } - if int(affected) < len({{ $receiver }}.{{ $e.BuilderField }}) { - return {{ $zero }}, rollback(tx, &ConstraintError{msg: fmt.Sprintf("one of \"{{ $e.Name }}\" %v already connected to a different \"{{ $.Name }}\"", keys({{ $receiver }}.{{ $e.BuilderField }}))}) - } - } + if nodes := {{ $receiver }}.{{ $e.BuilderField }}; len(nodes) > 0 { + {{- with extend $ "Edge" $e "Nodes" true "Zero" $zero }} + {{ template "dialect/sql/defedge" . }} {{- end }} + spec.Edges.Add = append(spec.Edges.Add, edge) } {{- end }} - if err = tx.Commit(); err != nil { + {{- if $one }} + {{ $ret }} = &{{ $.Name }}{config: {{ $receiver }}.config} + spec.ScanTypes = []interface{} { + &{{ if not $.ID.UserDefined }}sql.NullInt64{{ else }}{{ $.ID.NullType }}{{ end }}{}, + {{- range $_, $f := $.Fields }} + &{{ $f.NullType }}{}, + {{- end }} + } + spec.Assign = func(values ...interface{}) error { + if m, n := len(values), len(spec.ScanTypes); m != n { + return fmt.Errorf("mismatch number of scan values: %d != %d", m, n) + } + {{- if and $.ID.UserDefined (or $.ID.IsString $.ID.IsUUID) }} + {{- with extend $ "Idx" 0 "Field" $.ID "Ret" $ret }} + {{ template "dialect/sql/assignfield" . }} + {{- end }} + {{- else }} + value, ok := values[0].(*sql.NullInt64) + if !ok { + return fmt.Errorf("unexpected type %T for field id", value) + } + {{ $ret }}.ID = {{ if $.ID.IsString }}strconv.FormatInt(value.Int64, 10){{ else }}{{ $.ID.Type }}(value.Int64){{ end }} + {{- end }} + values = values[1:] + {{- range $i, $f := $.Fields }} + {{- with extend $ "Idx" $i "Field" $f "Ret" $ret }} + {{ template "dialect/sql/assignfield" . }} + {{- end }} + {{- end }} + return nil + } + {{- end }} + {{- if $one }} + if err = sqlgraph.UpdateNode(ctx, {{ $receiver }}.driver, spec); err != nil { + {{- else }} + if {{ $ret }}, err = sqlgraph.UpdateNodes(ctx, {{ $receiver }}.driver, spec); err != nil { + {{- end }} + if cerr, ok := isSQLConstraintError(err); ok { + err = cerr + } return {{ $zero }}, err } - return {{ if $one }}{{ $.Receiver }}{{ else }}len(ids){{ end }}, nil + return {{ $ret }}, nil } - {{ end }} -{{ define "dialect/sql/update/convertid" }} - {{- $id := $.Type.ID }} - {{- if not $id.UserDefined }} - {{- if $id.IsString }} - eid, serr := strconv.Atoi(eid) - if serr != nil { - err = rollback(tx, serr) - return {{/* return is not knwon at this point. */}} - } - {{- else if not $id.IsInt}} - eid := int(eid) - {{- end }} +{{ define "dialect/sql/defedge" }} + {{- $e := $.Scope.Edge -}} + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.{{ $e.Rel.Type }}, + Inverse: {{ $e.IsInverse }}, + Table: {{ $.Package }}.{{ $e.TableConstant }}, + Columns: {{ if $e.M2M }}{{ $.Package }}.{{ $e.PKConstant }}{{ else }}[]string{ {{ $.Package }}.{{ $e.ColumnConstant }} }{{ end }}, + Bidi: {{ $e.SelfRef }}, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.{{ $e.Type.ID.Type.ConstName }}, + Column: {{ $e.Type.Package }}.{{ $e.Type.ID.Constant }}, + }, + }, + } + {{- with $.Scope.Nodes }} + for k, _ := range nodes { + {{- $id := $e.Type.ID -}} + {{- /* Convert string-ids that are stored as int in the database */ -}} + {{- if and (not $id.UserDefined) $id.IsString }} + k, err := strconv.Atoi(k) + if err != nil { + return {{ $.Scope.Zero }}, err + } + {{- end }} + edge.Target.Nodes = append(edge.Target.Nodes, k) + } {{- end }} -{{ end }} +{{- end }} + +{{ define "dialect/sql/assignfield" }} + {{- $i := $.Scope.Idx -}} + {{- $f := $.Scope.Field -}} + {{- $ret := $.Scope.Ret -}} + {{- if $f.IsJSON }} + if value, ok := values[{{ $i }}].(*{{ $f.NullType }}); !ok { + return fmt.Errorf("unexpected type %T for field {{ $f.Name }}", values[{{ $i }}]) + } else if value != nil && len(*value) > 0 { + if err := json.Unmarshal(*value, &{{ $ret }}.{{ $f.StructField }}); err != nil { + return fmt.Errorf("unmarshal field {{ $f.Name }}: %v", err) + } + } + {{- else }} + {{- $nulltype := $f.NullType -}} + if value, ok := values[{{ $i }}].(*{{ $nulltype }}); !ok { + return fmt.Errorf("unexpected type %T for field {{ $f.Name }}", values[{{ $i }}]) + {{- if hasPrefix $nulltype "sql" }} + } else if value.Valid { + {{- if $f.Nillable }} + {{ $ret }}.{{ $f.StructField }} = new({{ $f.Type }}) + *{{ $ret }}.{{ $f.StructField }} = {{ $f.NullTypeField "value" }} + {{- else }} + {{ $ret }}.{{ $f.StructField }} = {{ $f.NullTypeField "value" }} + {{- end }} + {{- else }} + } else if value != nil { + {{ $ret }}.{{ $f.StructField }} = *value + {{- end }} + } + {{- end }} +{{- end }} diff --git a/entc/integration/config/ent/user_update.go b/entc/integration/config/ent/user_update.go index 5213d6ad2..2441b1ebc 100644 --- a/entc/integration/config/ent/user_update.go +++ b/entc/integration/config/ent/user_update.go @@ -11,8 +11,10 @@ import ( "fmt" "github.com/facebookincubator/ent/dialect/sql" + "github.com/facebookincubator/ent/dialect/sql/sqlgraph" "github.com/facebookincubator/ent/entc/integration/config/ent/predicate" "github.com/facebookincubator/ent/entc/integration/config/ent/user" + "github.com/facebookincubator/ent/schema/field" ) // UserUpdate is the builder for updating User entities. @@ -55,40 +57,30 @@ func (uu *UserUpdate) ExecX(ctx context.Context) { } func (uu *UserUpdate) sqlSave(ctx context.Context) (n int, err error) { - var ( - builder = sql.Dialect(uu.driver.Dialect()) - selector = builder.Select(user.FieldID).From(builder.Table(user.Table)) - ) - for _, p := range uu.predicates { - p(selector) + spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: user.Table, + Columns: user.Columns, + ID: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: user.FieldID, + }, + }, } - rows := &sql.Rows{} - query, args := selector.Query() - if err = uu.driver.Query(ctx, query, args, rows); err != nil { - return 0, err - } - defer rows.Close() - - var ids []int - for rows.Next() { - var id int - if err := rows.Scan(&id); err != nil { - return 0, fmt.Errorf("ent: failed reading id: %v", err) + if ps := uu.predicates; len(ps) > 0 { + spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } } - ids = append(ids, id) } - if len(ids) == 0 { - return 0, nil - } - - tx, err := uu.driver.Tx(ctx) - if err != nil { + if n, err = sqlgraph.UpdateNodes(ctx, uu.driver, spec); err != nil { + if cerr, ok := isSQLConstraintError(err); ok { + err = cerr + } return 0, err } - if err = tx.Commit(); err != nil { - return 0, err - } - return len(ids), nil + return n, nil } // UserUpdateOne is the builder for updating a single User entity. @@ -125,40 +117,37 @@ func (uuo *UserUpdateOne) ExecX(ctx context.Context) { } func (uuo *UserUpdateOne) sqlSave(ctx context.Context) (u *User, err error) { - var ( - builder = sql.Dialect(uuo.driver.Dialect()) - selector = builder.Select(user.Columns...).From(builder.Table(user.Table)) - ) - user.ID(uuo.id)(selector) - rows := &sql.Rows{} - query, args := selector.Query() - if err = uuo.driver.Query(ctx, query, args, rows); err != nil { - return nil, err + spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: user.Table, + Columns: user.Columns, + ID: &sqlgraph.FieldSpec{ + Value: uuo.id, + Type: field.TypeInt, + Column: user.FieldID, + }, + }, } - defer rows.Close() - - var ids []int - for rows.Next() { - var id int - u = &User{config: uuo.config} - if err := u.FromRows(rows); err != nil { - return nil, fmt.Errorf("ent: failed scanning row into User: %v", err) + u = &User{config: uuo.config} + spec.ScanTypes = []interface{}{ + &sql.NullInt64{}, + } + spec.Assign = func(values ...interface{}) error { + if m, n := len(values), len(spec.ScanTypes); m != n { + return fmt.Errorf("mismatch number of scan values: %d != %d", m, n) } - id = u.ID - ids = append(ids, id) + value, ok := values[0].(*sql.NullInt64) + if !ok { + return fmt.Errorf("unexpected type %T for field id", value) + } + u.ID = int(value.Int64) + values = values[1:] + return nil } - switch n := len(ids); { - case n == 0: - return nil, &ErrNotFound{fmt.Sprintf("User with id: %v", uuo.id)} - case n > 1: - return nil, fmt.Errorf("ent: more than one User with the same id: %v", uuo.id) - } - - tx, err := uuo.driver.Tx(ctx) - if err != nil { - return nil, err - } - if err = tx.Commit(); err != nil { + if err = sqlgraph.UpdateNode(ctx, uuo.driver, spec); err != nil { + if cerr, ok := isSQLConstraintError(err); ok { + err = cerr + } return nil, err } return u, nil diff --git a/entc/integration/customid/customid_test.go b/entc/integration/customid/customid_test.go index 48a622f34..808c5348e 100644 --- a/entc/integration/customid/customid_test.go +++ b/entc/integration/customid/customid_test.go @@ -10,7 +10,6 @@ import ( "github.com/facebookincubator/ent/entc/integration/customid/ent" - _ "github.com/go-sql-driver/mysql" "github.com/google/uuid" _ "github.com/mattn/go-sqlite3" "github.com/stretchr/testify/require" diff --git a/entc/integration/customid/ent/blob_update.go b/entc/integration/customid/ent/blob_update.go index d7f76efb7..57e601bba 100644 --- a/entc/integration/customid/ent/blob_update.go +++ b/entc/integration/customid/ent/blob_update.go @@ -11,8 +11,10 @@ import ( "fmt" "github.com/facebookincubator/ent/dialect/sql" + "github.com/facebookincubator/ent/dialect/sql/sqlgraph" "github.com/facebookincubator/ent/entc/integration/customid/ent/blob" "github.com/facebookincubator/ent/entc/integration/customid/ent/predicate" + "github.com/facebookincubator/ent/schema/field" "github.com/google/uuid" ) @@ -63,58 +65,37 @@ func (bu *BlobUpdate) ExecX(ctx context.Context) { } func (bu *BlobUpdate) sqlSave(ctx context.Context) (n int, err error) { - var ( - builder = sql.Dialect(bu.driver.Dialect()) - selector = builder.Select(blob.FieldID).From(builder.Table(blob.Table)) - ) - for _, p := range bu.predicates { - p(selector) + spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: blob.Table, + Columns: blob.Columns, + ID: &sqlgraph.FieldSpec{ + Type: field.TypeUUID, + Column: blob.FieldID, + }, + }, } - rows := &sql.Rows{} - query, args := selector.Query() - if err = bu.driver.Query(ctx, query, args, rows); err != nil { - return 0, err - } - defer rows.Close() - - var ids []uuid.UUID - for rows.Next() { - var id uuid.UUID - if err := rows.Scan(&id); err != nil { - return 0, fmt.Errorf("ent: failed reading id: %v", err) + if ps := bu.predicates; len(ps) > 0 { + spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } } - ids = append(ids, id) } - if len(ids) == 0 { - return 0, nil - } - - tx, err := bu.driver.Tx(ctx) - if err != nil { - return 0, err - } - var ( - res sql.Result - updater = builder.Update(blob.Table) - ) - idface := make([]interface{}, len(ids)) - for i := range ids { - idface[i] = ids[i] - } - updater = updater.Where(sql.In(blob.FieldID, idface...)) if value := bu.uuid; value != nil { - updater.Set(blob.FieldUUID, *value) + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeUUID, + Value: *value, + Column: blob.FieldUUID, + }) } - if !updater.Empty() { - query, args := updater.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) + if n, err = sqlgraph.UpdateNodes(ctx, bu.driver, spec); err != nil { + if cerr, ok := isSQLConstraintError(err); ok { + err = cerr } - } - if err = tx.Commit(); err != nil { return 0, err } - return len(ids), nil + return n, nil } // BlobUpdateOne is the builder for updating a single Blob entity. @@ -158,59 +139,50 @@ func (buo *BlobUpdateOne) ExecX(ctx context.Context) { } func (buo *BlobUpdateOne) sqlSave(ctx context.Context) (b *Blob, err error) { - var ( - builder = sql.Dialect(buo.driver.Dialect()) - selector = builder.Select(blob.Columns...).From(builder.Table(blob.Table)) - ) - blob.ID(buo.id)(selector) - rows := &sql.Rows{} - query, args := selector.Query() - if err = buo.driver.Query(ctx, query, args, rows); err != nil { - return nil, err + spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: blob.Table, + Columns: blob.Columns, + ID: &sqlgraph.FieldSpec{ + Value: buo.id, + Type: field.TypeUUID, + Column: blob.FieldID, + }, + }, } - defer rows.Close() - - var ids []uuid.UUID - for rows.Next() { - var id uuid.UUID - b = &Blob{config: buo.config} - if err := b.FromRows(rows); err != nil { - return nil, fmt.Errorf("ent: failed scanning row into Blob: %v", err) - } - id = b.ID - ids = append(ids, id) - } - switch n := len(ids); { - case n == 0: - return nil, &ErrNotFound{fmt.Sprintf("Blob with id: %v", buo.id)} - case n > 1: - return nil, fmt.Errorf("ent: more than one Blob with the same id: %v", buo.id) - } - - tx, err := buo.driver.Tx(ctx) - if err != nil { - return nil, err - } - var ( - res sql.Result - updater = builder.Update(blob.Table) - ) - idface := make([]interface{}, len(ids)) - for i := range ids { - idface[i] = ids[i] - } - updater = updater.Where(sql.In(blob.FieldID, idface...)) if value := buo.uuid; value != nil { - updater.Set(blob.FieldUUID, *value) - b.UUID = *value + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeUUID, + Value: *value, + Column: blob.FieldUUID, + }) } - if !updater.Empty() { - query, args := updater.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) + b = &Blob{config: buo.config} + spec.ScanTypes = []interface{}{ + &uuid.UUID{}, + &uuid.UUID{}, + } + spec.Assign = func(values ...interface{}) error { + if m, n := len(values), len(spec.ScanTypes); m != n { + return fmt.Errorf("mismatch number of scan values: %d != %d", m, n) } + if value, ok := values[0].(*uuid.UUID); !ok { + return fmt.Errorf("unexpected type %T for field id", values[0]) + } else if value != nil { + b.ID = *value + } + values = values[1:] + if value, ok := values[0].(*uuid.UUID); !ok { + return fmt.Errorf("unexpected type %T for field uuid", values[0]) + } else if value != nil { + b.UUID = *value + } + return nil } - if err = tx.Commit(); err != nil { + if err = sqlgraph.UpdateNode(ctx, buo.driver, spec); err != nil { + if cerr, ok := isSQLConstraintError(err); ok { + err = cerr + } return nil, err } return b, nil diff --git a/entc/integration/customid/ent/group_update.go b/entc/integration/customid/ent/group_update.go index 893d85ccd..1d093640f 100644 --- a/entc/integration/customid/ent/group_update.go +++ b/entc/integration/customid/ent/group_update.go @@ -11,8 +11,11 @@ import ( "fmt" "github.com/facebookincubator/ent/dialect/sql" + "github.com/facebookincubator/ent/dialect/sql/sqlgraph" "github.com/facebookincubator/ent/entc/integration/customid/ent/group" "github.com/facebookincubator/ent/entc/integration/customid/ent/predicate" + "github.com/facebookincubator/ent/entc/integration/customid/ent/user" + "github.com/facebookincubator/ent/schema/field" ) // GroupUpdate is the builder for updating Group entities. @@ -97,71 +100,68 @@ func (gu *GroupUpdate) ExecX(ctx context.Context) { } func (gu *GroupUpdate) sqlSave(ctx context.Context) (n int, err error) { - var ( - builder = sql.Dialect(gu.driver.Dialect()) - selector = builder.Select(group.FieldID).From(builder.Table(group.Table)) - ) - for _, p := range gu.predicates { - p(selector) + spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: group.Table, + Columns: group.Columns, + ID: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: group.FieldID, + }, + }, } - rows := &sql.Rows{} - query, args := selector.Query() - if err = gu.driver.Query(ctx, query, args, rows); err != nil { - return 0, err - } - defer rows.Close() - - var ids []int - for rows.Next() { - var id int - if err := rows.Scan(&id); err != nil { - return 0, fmt.Errorf("ent: failed reading id: %v", err) - } - ids = append(ids, id) - } - if len(ids) == 0 { - return 0, nil - } - - tx, err := gu.driver.Tx(ctx) - if err != nil { - return 0, err - } - var res sql.Result - if len(gu.removedUsers) > 0 { - eids := make([]int, len(gu.removedUsers)) - for eid := range gu.removedUsers { - eids = append(eids, eid) - } - query, args := builder.Delete(group.UsersTable). - Where(sql.InInts(group.UsersPrimaryKey[0], ids...)). - Where(sql.InInts(group.UsersPrimaryKey[1], eids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } - } - if len(gu.users) > 0 { - values := make([][]int, 0, len(ids)) - for _, id := range ids { - for eid := range gu.users { - values = append(values, []int{id, eid}) + if ps := gu.predicates; len(ps) > 0 { + spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) } } - builder := builder.Insert(group.UsersTable). - Columns(group.UsersPrimaryKey[0], group.UsersPrimaryKey[1]) - for _, v := range values { - builder.Values(v[0], v[1]) - } - query, args := builder.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } } - if err = tx.Commit(); err != nil { + if nodes := gu.removedUsers; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: false, + Table: group.UsersTable, + Columns: group.UsersPrimaryKey, + Bidi: false, + 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 := gu.users; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: false, + Table: group.UsersTable, + Columns: group.UsersPrimaryKey, + Bidi: false, + 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, gu.driver, spec); err != nil { + if cerr, ok := isSQLConstraintError(err); ok { + err = cerr + } return 0, err } - return len(ids), nil + return n, nil } // GroupUpdateOne is the builder for updating a single Group entity. @@ -240,71 +240,75 @@ func (guo *GroupUpdateOne) ExecX(ctx context.Context) { } func (guo *GroupUpdateOne) sqlSave(ctx context.Context) (gr *Group, err error) { - var ( - builder = sql.Dialect(guo.driver.Dialect()) - selector = builder.Select(group.Columns...).From(builder.Table(group.Table)) - ) - group.ID(guo.id)(selector) - rows := &sql.Rows{} - query, args := selector.Query() - if err = guo.driver.Query(ctx, query, args, rows); err != nil { - return nil, err + spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: group.Table, + Columns: group.Columns, + ID: &sqlgraph.FieldSpec{ + Value: guo.id, + Type: field.TypeInt, + Column: group.FieldID, + }, + }, } - defer rows.Close() - - var ids []int - for rows.Next() { - var id int - gr = &Group{config: guo.config} - if err := gr.FromRows(rows); err != nil { - return nil, fmt.Errorf("ent: failed scanning row into Group: %v", err) + if nodes := guo.removedUsers; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: false, + Table: group.UsersTable, + Columns: group.UsersPrimaryKey, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: user.FieldID, + }, + }, } - id = gr.ID - ids = append(ids, id) + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + spec.Edges.Clear = append(spec.Edges.Clear, edge) } - switch n := len(ids); { - case n == 0: - return nil, &ErrNotFound{fmt.Sprintf("Group with id: %v", guo.id)} - case n > 1: - return nil, fmt.Errorf("ent: more than one Group with the same id: %v", guo.id) + if nodes := guo.users; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: false, + Table: group.UsersTable, + Columns: group.UsersPrimaryKey, + Bidi: false, + 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) } - - tx, err := guo.driver.Tx(ctx) - if err != nil { - return nil, err + gr = &Group{config: guo.config} + spec.ScanTypes = []interface{}{ + &sql.NullInt64{}, } - var res sql.Result - if len(guo.removedUsers) > 0 { - eids := make([]int, len(guo.removedUsers)) - for eid := range guo.removedUsers { - eids = append(eids, eid) + spec.Assign = func(values ...interface{}) error { + if m, n := len(values), len(spec.ScanTypes); m != n { + return fmt.Errorf("mismatch number of scan values: %d != %d", m, n) } - query, args := builder.Delete(group.UsersTable). - Where(sql.InInts(group.UsersPrimaryKey[0], ids...)). - Where(sql.InInts(group.UsersPrimaryKey[1], eids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) + value, ok := values[0].(*sql.NullInt64) + if !ok { + return fmt.Errorf("unexpected type %T for field id", value) } + gr.ID = int(value.Int64) + values = values[1:] + return nil } - if len(guo.users) > 0 { - values := make([][]int, 0, len(ids)) - for _, id := range ids { - for eid := range guo.users { - values = append(values, []int{id, eid}) - } + if err = sqlgraph.UpdateNode(ctx, guo.driver, spec); err != nil { + if cerr, ok := isSQLConstraintError(err); ok { + err = cerr } - builder := builder.Insert(group.UsersTable). - Columns(group.UsersPrimaryKey[0], group.UsersPrimaryKey[1]) - for _, v := range values { - builder.Values(v[0], v[1]) - } - query, args := builder.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) - } - } - if err = tx.Commit(); err != nil { return nil, err } return gr, nil diff --git a/entc/integration/customid/ent/user_update.go b/entc/integration/customid/ent/user_update.go index 36b09ce24..1f6b6319c 100644 --- a/entc/integration/customid/ent/user_update.go +++ b/entc/integration/customid/ent/user_update.go @@ -11,8 +11,11 @@ import ( "fmt" "github.com/facebookincubator/ent/dialect/sql" + "github.com/facebookincubator/ent/dialect/sql/sqlgraph" + "github.com/facebookincubator/ent/entc/integration/customid/ent/group" "github.com/facebookincubator/ent/entc/integration/customid/ent/predicate" "github.com/facebookincubator/ent/entc/integration/customid/ent/user" + "github.com/facebookincubator/ent/schema/field" ) // UserUpdate is the builder for updating User entities. @@ -97,71 +100,68 @@ func (uu *UserUpdate) ExecX(ctx context.Context) { } func (uu *UserUpdate) sqlSave(ctx context.Context) (n int, err error) { - var ( - builder = sql.Dialect(uu.driver.Dialect()) - selector = builder.Select(user.FieldID).From(builder.Table(user.Table)) - ) - for _, p := range uu.predicates { - p(selector) + spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: user.Table, + Columns: user.Columns, + ID: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: user.FieldID, + }, + }, } - rows := &sql.Rows{} - query, args := selector.Query() - if err = uu.driver.Query(ctx, query, args, rows); err != nil { - return 0, err - } - defer rows.Close() - - var ids []int - for rows.Next() { - var id int - if err := rows.Scan(&id); err != nil { - return 0, fmt.Errorf("ent: failed reading id: %v", err) - } - ids = append(ids, id) - } - if len(ids) == 0 { - return 0, nil - } - - tx, err := uu.driver.Tx(ctx) - if err != nil { - return 0, err - } - var res sql.Result - if len(uu.removedGroups) > 0 { - eids := make([]int, len(uu.removedGroups)) - for eid := range uu.removedGroups { - eids = append(eids, eid) - } - query, args := builder.Delete(user.GroupsTable). - Where(sql.InInts(user.GroupsPrimaryKey[1], ids...)). - Where(sql.InInts(user.GroupsPrimaryKey[0], eids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } - } - if len(uu.groups) > 0 { - values := make([][]int, 0, len(ids)) - for _, id := range ids { - for eid := range uu.groups { - values = append(values, []int{id, eid}) + if ps := uu.predicates; len(ps) > 0 { + spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) } } - builder := builder.Insert(user.GroupsTable). - Columns(user.GroupsPrimaryKey[1], user.GroupsPrimaryKey[0]) - for _, v := range values { - builder.Values(v[0], v[1]) - } - query, args := builder.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } } - if err = tx.Commit(); err != nil { + if nodes := uu.removedGroups; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: true, + Table: user.GroupsTable, + Columns: user.GroupsPrimaryKey, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: group.FieldID, + }, + }, + } + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + spec.Edges.Clear = append(spec.Edges.Clear, edge) + } + if nodes := uu.groups; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: true, + Table: user.GroupsTable, + Columns: user.GroupsPrimaryKey, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: group.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 cerr, ok := isSQLConstraintError(err); ok { + err = cerr + } return 0, err } - return len(ids), nil + return n, nil } // UserUpdateOne is the builder for updating a single User entity. @@ -240,71 +240,75 @@ func (uuo *UserUpdateOne) ExecX(ctx context.Context) { } func (uuo *UserUpdateOne) sqlSave(ctx context.Context) (u *User, err error) { - var ( - builder = sql.Dialect(uuo.driver.Dialect()) - selector = builder.Select(user.Columns...).From(builder.Table(user.Table)) - ) - user.ID(uuo.id)(selector) - rows := &sql.Rows{} - query, args := selector.Query() - if err = uuo.driver.Query(ctx, query, args, rows); err != nil { - return nil, err + spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: user.Table, + Columns: user.Columns, + ID: &sqlgraph.FieldSpec{ + Value: uuo.id, + Type: field.TypeInt, + Column: user.FieldID, + }, + }, } - defer rows.Close() - - var ids []int - for rows.Next() { - var id int - u = &User{config: uuo.config} - if err := u.FromRows(rows); err != nil { - return nil, fmt.Errorf("ent: failed scanning row into User: %v", err) + if nodes := uuo.removedGroups; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: true, + Table: user.GroupsTable, + Columns: user.GroupsPrimaryKey, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: group.FieldID, + }, + }, } - id = u.ID - ids = append(ids, id) + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + spec.Edges.Clear = append(spec.Edges.Clear, edge) } - switch n := len(ids); { - case n == 0: - return nil, &ErrNotFound{fmt.Sprintf("User with id: %v", uuo.id)} - case n > 1: - return nil, fmt.Errorf("ent: more than one User with the same id: %v", uuo.id) + if nodes := uuo.groups; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: true, + Table: user.GroupsTable, + Columns: user.GroupsPrimaryKey, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: group.FieldID, + }, + }, + } + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + spec.Edges.Add = append(spec.Edges.Add, edge) } - - tx, err := uuo.driver.Tx(ctx) - if err != nil { - return nil, err + u = &User{config: uuo.config} + spec.ScanTypes = []interface{}{ + &sql.NullInt64{}, } - var res sql.Result - if len(uuo.removedGroups) > 0 { - eids := make([]int, len(uuo.removedGroups)) - for eid := range uuo.removedGroups { - eids = append(eids, eid) + spec.Assign = func(values ...interface{}) error { + if m, n := len(values), len(spec.ScanTypes); m != n { + return fmt.Errorf("mismatch number of scan values: %d != %d", m, n) } - query, args := builder.Delete(user.GroupsTable). - Where(sql.InInts(user.GroupsPrimaryKey[1], ids...)). - Where(sql.InInts(user.GroupsPrimaryKey[0], eids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) + value, ok := values[0].(*sql.NullInt64) + if !ok { + return fmt.Errorf("unexpected type %T for field id", value) } + u.ID = int(value.Int64) + values = values[1:] + return nil } - if len(uuo.groups) > 0 { - values := make([][]int, 0, len(ids)) - for _, id := range ids { - for eid := range uuo.groups { - values = append(values, []int{id, eid}) - } + if err = sqlgraph.UpdateNode(ctx, uuo.driver, spec); err != nil { + if cerr, ok := isSQLConstraintError(err); ok { + err = cerr } - builder := builder.Insert(user.GroupsTable). - Columns(user.GroupsPrimaryKey[1], user.GroupsPrimaryKey[0]) - for _, v := range values { - builder.Values(v[0], v[1]) - } - query, args := builder.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) - } - } - if err = tx.Commit(); err != nil { return nil, err } return u, nil diff --git a/entc/integration/ent/card_update.go b/entc/integration/ent/card_update.go index 975dd86ca..64bb07e74 100644 --- a/entc/integration/ent/card_update.go +++ b/entc/integration/ent/card_update.go @@ -14,9 +14,11 @@ import ( "time" "github.com/facebookincubator/ent/dialect/sql" + "github.com/facebookincubator/ent/dialect/sql/sqlgraph" "github.com/facebookincubator/ent/entc/integration/ent/card" "github.com/facebookincubator/ent/entc/integration/ent/predicate" "github.com/facebookincubator/ent/entc/integration/ent/user" + "github.com/facebookincubator/ent/schema/field" ) // CardUpdate is the builder for updating Card entities. @@ -127,91 +129,89 @@ func (cu *CardUpdate) ExecX(ctx context.Context) { } func (cu *CardUpdate) sqlSave(ctx context.Context) (n int, err error) { - var ( - builder = sql.Dialect(cu.driver.Dialect()) - selector = builder.Select(card.FieldID).From(builder.Table(card.Table)) - ) - for _, p := range cu.predicates { - p(selector) + spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: card.Table, + Columns: card.Columns, + ID: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: card.FieldID, + }, + }, } - rows := &sql.Rows{} - query, args := selector.Query() - if err = cu.driver.Query(ctx, query, args, rows); err != nil { - return 0, err - } - defer rows.Close() - - var ids []int - for rows.Next() { - var id int - if err := rows.Scan(&id); err != nil { - return 0, fmt.Errorf("ent: failed reading id: %v", err) + if ps := cu.predicates; len(ps) > 0 { + spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } } - ids = append(ids, id) } - if len(ids) == 0 { - return 0, nil - } - - tx, err := cu.driver.Tx(ctx) - if err != nil { - return 0, err - } - var ( - res sql.Result - updater = builder.Update(card.Table) - ) - updater = updater.Where(sql.InInts(card.FieldID, ids...)) if value := cu.update_time; value != nil { - updater.Set(card.FieldUpdateTime, *value) + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeTime, + Value: *value, + Column: card.FieldUpdateTime, + }) } if value := cu.name; value != nil { - updater.Set(card.FieldName, *value) + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: *value, + Column: card.FieldName, + }) } if cu.clearname { - updater.SetNull(card.FieldName) - } - if !updater.Empty() { - query, args := updater.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } + spec.Fields.Clear = append(spec.Fields.Clear, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: card.FieldName, + }) } if cu.clearedOwner { - query, args := builder.Update(card.OwnerTable). - SetNull(card.OwnerColumn). - Where(sql.InInts(user.FieldID, ids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2O, + Inverse: true, + Table: card.OwnerTable, + Columns: []string{card.OwnerColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: user.FieldID, + }, + }, } + spec.Edges.Clear = append(spec.Edges.Clear, edge) } - if len(cu.owner) > 0 { - for _, id := range ids { - eid, serr := strconv.Atoi(keys(cu.owner)[0]) - if serr != nil { - return 0, rollback(tx, err) - } - query, args := builder.Update(card.OwnerTable). - Set(card.OwnerColumn, eid). - Where(sql.EQ(card.FieldID, id).And().IsNull(card.OwnerColumn)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } - affected, err := res.RowsAffected() + if nodes := cu.owner; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2O, + Inverse: true, + Table: card.OwnerTable, + Columns: []string{card.OwnerColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: user.FieldID, + }, + }, + } + for k, _ := range nodes { + k, err := strconv.Atoi(k) if err != nil { - return 0, rollback(tx, err) - } - if int(affected) < len(cu.owner) { - return 0, rollback(tx, &ConstraintError{msg: fmt.Sprintf("one of \"owner\" %v already connected to a different \"Card\"", keys(cu.owner))}) + return 0, err } + edge.Target.Nodes = append(edge.Target.Nodes, k) } + spec.Edges.Add = append(spec.Edges.Add, edge) } - if err = tx.Commit(); err != nil { + if n, err = sqlgraph.UpdateNodes(ctx, cu.driver, spec); err != nil { + if cerr, ok := isSQLConstraintError(err); ok { + err = cerr + } return 0, err } - return len(ids), nil + return n, nil } // CardUpdateOne is the builder for updating a single Card entity. @@ -316,95 +316,120 @@ func (cuo *CardUpdateOne) ExecX(ctx context.Context) { } func (cuo *CardUpdateOne) sqlSave(ctx context.Context) (c *Card, err error) { - var ( - builder = sql.Dialect(cuo.driver.Dialect()) - selector = builder.Select(card.Columns...).From(builder.Table(card.Table)) - ) - card.ID(cuo.id)(selector) - rows := &sql.Rows{} - query, args := selector.Query() - if err = cuo.driver.Query(ctx, query, args, rows); err != nil { - return nil, err + spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: card.Table, + Columns: card.Columns, + ID: &sqlgraph.FieldSpec{ + Value: cuo.id, + Type: field.TypeString, + Column: card.FieldID, + }, + }, } - defer rows.Close() - - var ids []int - for rows.Next() { - var id int - c = &Card{config: cuo.config} - if err := c.FromRows(rows); err != nil { - return nil, fmt.Errorf("ent: failed scanning row into Card: %v", err) - } - id = c.id() - ids = append(ids, id) - } - switch n := len(ids); { - case n == 0: - return nil, &ErrNotFound{fmt.Sprintf("Card with id: %v", cuo.id)} - case n > 1: - return nil, fmt.Errorf("ent: more than one Card with the same id: %v", cuo.id) - } - - tx, err := cuo.driver.Tx(ctx) - if err != nil { - return nil, err - } - var ( - res sql.Result - updater = builder.Update(card.Table) - ) - updater = updater.Where(sql.InInts(card.FieldID, ids...)) if value := cuo.update_time; value != nil { - updater.Set(card.FieldUpdateTime, *value) - c.UpdateTime = *value + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeTime, + Value: *value, + Column: card.FieldUpdateTime, + }) } if value := cuo.name; value != nil { - updater.Set(card.FieldName, *value) - c.Name = *value + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: *value, + Column: card.FieldName, + }) } if cuo.clearname { - var value string - c.Name = value - updater.SetNull(card.FieldName) - } - if !updater.Empty() { - query, args := updater.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) - } + spec.Fields.Clear = append(spec.Fields.Clear, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: card.FieldName, + }) } if cuo.clearedOwner { - query, args := builder.Update(card.OwnerTable). - SetNull(card.OwnerColumn). - Where(sql.InInts(user.FieldID, ids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2O, + Inverse: true, + Table: card.OwnerTable, + Columns: []string{card.OwnerColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: user.FieldID, + }, + }, } + spec.Edges.Clear = append(spec.Edges.Clear, edge) } - if len(cuo.owner) > 0 { - for _, id := range ids { - eid, serr := strconv.Atoi(keys(cuo.owner)[0]) - if serr != nil { - return nil, rollback(tx, err) - } - query, args := builder.Update(card.OwnerTable). - Set(card.OwnerColumn, eid). - Where(sql.EQ(card.FieldID, id).And().IsNull(card.OwnerColumn)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) - } - affected, err := res.RowsAffected() + if nodes := cuo.owner; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2O, + Inverse: true, + Table: card.OwnerTable, + Columns: []string{card.OwnerColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: user.FieldID, + }, + }, + } + for k, _ := range nodes { + k, err := strconv.Atoi(k) if err != nil { - return nil, rollback(tx, err) - } - if int(affected) < len(cuo.owner) { - return nil, rollback(tx, &ConstraintError{msg: fmt.Sprintf("one of \"owner\" %v already connected to a different \"Card\"", keys(cuo.owner))}) + return nil, err } + edge.Target.Nodes = append(edge.Target.Nodes, k) } + spec.Edges.Add = append(spec.Edges.Add, edge) } - if err = tx.Commit(); err != nil { + c = &Card{config: cuo.config} + spec.ScanTypes = []interface{}{ + &sql.NullInt64{}, + &sql.NullTime{}, + &sql.NullTime{}, + &sql.NullString{}, + &sql.NullString{}, + } + spec.Assign = func(values ...interface{}) error { + if m, n := len(values), len(spec.ScanTypes); m != n { + return fmt.Errorf("mismatch number of scan values: %d != %d", m, n) + } + value, ok := values[0].(*sql.NullInt64) + if !ok { + return fmt.Errorf("unexpected type %T for field id", value) + } + c.ID = strconv.FormatInt(value.Int64, 10) + values = values[1:] + if value, ok := values[0].(*sql.NullTime); !ok { + return fmt.Errorf("unexpected type %T for field create_time", values[0]) + } else if value.Valid { + c.CreateTime = value.Time + } + if value, ok := values[1].(*sql.NullTime); !ok { + return fmt.Errorf("unexpected type %T for field update_time", values[1]) + } else if value.Valid { + c.UpdateTime = value.Time + } + if value, ok := values[2].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field number", values[2]) + } else if value.Valid { + c.Number = value.String + } + if value, ok := values[3].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field name", values[3]) + } else if value.Valid { + c.Name = value.String + } + return nil + } + if err = sqlgraph.UpdateNode(ctx, cuo.driver, spec); err != nil { + if cerr, ok := isSQLConstraintError(err); ok { + err = cerr + } return nil, err } return c, nil diff --git a/entc/integration/ent/comment_update.go b/entc/integration/ent/comment_update.go index 657d4dd87..4c18f164c 100644 --- a/entc/integration/ent/comment_update.go +++ b/entc/integration/ent/comment_update.go @@ -9,10 +9,13 @@ package ent import ( "context" "fmt" + "strconv" "github.com/facebookincubator/ent/dialect/sql" + "github.com/facebookincubator/ent/dialect/sql/sqlgraph" "github.com/facebookincubator/ent/entc/integration/ent/comment" "github.com/facebookincubator/ent/entc/integration/ent/predicate" + "github.com/facebookincubator/ent/schema/field" ) // CommentUpdate is the builder for updating Comment entities. @@ -128,72 +131,78 @@ func (cu *CommentUpdate) ExecX(ctx context.Context) { } func (cu *CommentUpdate) sqlSave(ctx context.Context) (n int, err error) { - var ( - builder = sql.Dialect(cu.driver.Dialect()) - selector = builder.Select(comment.FieldID).From(builder.Table(comment.Table)) - ) - for _, p := range cu.predicates { - p(selector) + spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: comment.Table, + Columns: comment.Columns, + ID: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: comment.FieldID, + }, + }, } - rows := &sql.Rows{} - query, args := selector.Query() - if err = cu.driver.Query(ctx, query, args, rows); err != nil { - return 0, err - } - defer rows.Close() - - var ids []int - for rows.Next() { - var id int - if err := rows.Scan(&id); err != nil { - return 0, fmt.Errorf("ent: failed reading id: %v", err) + if ps := cu.predicates; len(ps) > 0 { + spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } } - ids = append(ids, id) } - if len(ids) == 0 { - return 0, nil - } - - tx, err := cu.driver.Tx(ctx) - if err != nil { - return 0, err - } - var ( - res sql.Result - updater = builder.Update(comment.Table) - ) - updater = updater.Where(sql.InInts(comment.FieldID, ids...)) if value := cu.unique_int; value != nil { - updater.Set(comment.FieldUniqueInt, *value) + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: *value, + Column: comment.FieldUniqueInt, + }) } if value := cu.addunique_int; value != nil { - updater.Add(comment.FieldUniqueInt, *value) + spec.Fields.Add = append(spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: *value, + Column: comment.FieldUniqueInt, + }) } if value := cu.unique_float; value != nil { - updater.Set(comment.FieldUniqueFloat, *value) + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeFloat64, + Value: *value, + Column: comment.FieldUniqueFloat, + }) } if value := cu.addunique_float; value != nil { - updater.Add(comment.FieldUniqueFloat, *value) + spec.Fields.Add = append(spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.TypeFloat64, + Value: *value, + Column: comment.FieldUniqueFloat, + }) } if value := cu.nillable_int; value != nil { - updater.Set(comment.FieldNillableInt, *value) + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: *value, + Column: comment.FieldNillableInt, + }) } if value := cu.addnillable_int; value != nil { - updater.Add(comment.FieldNillableInt, *value) + spec.Fields.Add = append(spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: *value, + Column: comment.FieldNillableInt, + }) } if cu.clearnillable_int { - updater.SetNull(comment.FieldNillableInt) + spec.Fields.Clear = append(spec.Fields.Clear, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: comment.FieldNillableInt, + }) } - if !updater.Empty() { - query, args := updater.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) + if n, err = sqlgraph.UpdateNodes(ctx, cu.driver, spec); err != nil { + if cerr, ok := isSQLConstraintError(err); ok { + err = cerr } - } - if err = tx.Commit(); err != nil { return 0, err } - return len(ids), nil + return n, nil } // CommentUpdateOne is the builder for updating a single Comment entity. @@ -303,83 +312,104 @@ func (cuo *CommentUpdateOne) ExecX(ctx context.Context) { } func (cuo *CommentUpdateOne) sqlSave(ctx context.Context) (c *Comment, err error) { - var ( - builder = sql.Dialect(cuo.driver.Dialect()) - selector = builder.Select(comment.Columns...).From(builder.Table(comment.Table)) - ) - comment.ID(cuo.id)(selector) - rows := &sql.Rows{} - query, args := selector.Query() - if err = cuo.driver.Query(ctx, query, args, rows); err != nil { - return nil, err + spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: comment.Table, + Columns: comment.Columns, + ID: &sqlgraph.FieldSpec{ + Value: cuo.id, + Type: field.TypeString, + Column: comment.FieldID, + }, + }, } - defer rows.Close() - - var ids []int - for rows.Next() { - var id int - c = &Comment{config: cuo.config} - if err := c.FromRows(rows); err != nil { - return nil, fmt.Errorf("ent: failed scanning row into Comment: %v", err) - } - id = c.id() - ids = append(ids, id) - } - switch n := len(ids); { - case n == 0: - return nil, &ErrNotFound{fmt.Sprintf("Comment with id: %v", cuo.id)} - case n > 1: - return nil, fmt.Errorf("ent: more than one Comment with the same id: %v", cuo.id) - } - - tx, err := cuo.driver.Tx(ctx) - if err != nil { - return nil, err - } - var ( - res sql.Result - updater = builder.Update(comment.Table) - ) - updater = updater.Where(sql.InInts(comment.FieldID, ids...)) if value := cuo.unique_int; value != nil { - updater.Set(comment.FieldUniqueInt, *value) - c.UniqueInt = *value + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: *value, + Column: comment.FieldUniqueInt, + }) } if value := cuo.addunique_int; value != nil { - updater.Add(comment.FieldUniqueInt, *value) - c.UniqueInt += *value + spec.Fields.Add = append(spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: *value, + Column: comment.FieldUniqueInt, + }) } if value := cuo.unique_float; value != nil { - updater.Set(comment.FieldUniqueFloat, *value) - c.UniqueFloat = *value + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeFloat64, + Value: *value, + Column: comment.FieldUniqueFloat, + }) } if value := cuo.addunique_float; value != nil { - updater.Add(comment.FieldUniqueFloat, *value) - c.UniqueFloat += *value + spec.Fields.Add = append(spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.TypeFloat64, + Value: *value, + Column: comment.FieldUniqueFloat, + }) } if value := cuo.nillable_int; value != nil { - updater.Set(comment.FieldNillableInt, *value) - c.NillableInt = value + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: *value, + Column: comment.FieldNillableInt, + }) } if value := cuo.addnillable_int; value != nil { - updater.Add(comment.FieldNillableInt, *value) - if c.NillableInt != nil { - *c.NillableInt += *value - } else { - c.NillableInt = value - } + spec.Fields.Add = append(spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: *value, + Column: comment.FieldNillableInt, + }) } if cuo.clearnillable_int { - c.NillableInt = nil - updater.SetNull(comment.FieldNillableInt) + spec.Fields.Clear = append(spec.Fields.Clear, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: comment.FieldNillableInt, + }) } - if !updater.Empty() { - query, args := updater.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) + c = &Comment{config: cuo.config} + spec.ScanTypes = []interface{}{ + &sql.NullInt64{}, + &sql.NullInt64{}, + &sql.NullFloat64{}, + &sql.NullInt64{}, + } + spec.Assign = func(values ...interface{}) error { + if m, n := len(values), len(spec.ScanTypes); m != n { + return fmt.Errorf("mismatch number of scan values: %d != %d", m, n) } + value, ok := values[0].(*sql.NullInt64) + if !ok { + return fmt.Errorf("unexpected type %T for field id", value) + } + c.ID = strconv.FormatInt(value.Int64, 10) + values = values[1:] + if value, ok := values[0].(*sql.NullInt64); !ok { + return fmt.Errorf("unexpected type %T for field unique_int", values[0]) + } else if value.Valid { + c.UniqueInt = int(value.Int64) + } + if value, ok := values[1].(*sql.NullFloat64); !ok { + return fmt.Errorf("unexpected type %T for field unique_float", values[1]) + } else if value.Valid { + c.UniqueFloat = value.Float64 + } + if value, ok := values[2].(*sql.NullInt64); !ok { + return fmt.Errorf("unexpected type %T for field nillable_int", values[2]) + } else if value.Valid { + c.NillableInt = new(int) + *c.NillableInt = int(value.Int64) + } + return nil } - if err = tx.Commit(); err != nil { + if err = sqlgraph.UpdateNode(ctx, cuo.driver, spec); err != nil { + if cerr, ok := isSQLConstraintError(err); ok { + err = cerr + } return nil, err } return c, nil diff --git a/entc/integration/ent/fieldtype_update.go b/entc/integration/ent/fieldtype_update.go index 052bca0e7..e505e0589 100644 --- a/entc/integration/ent/fieldtype_update.go +++ b/entc/integration/ent/fieldtype_update.go @@ -9,10 +9,13 @@ package ent import ( "context" "fmt" + "strconv" "github.com/facebookincubator/ent/dialect/sql" + "github.com/facebookincubator/ent/dialect/sql/sqlgraph" "github.com/facebookincubator/ent/entc/integration/ent/fieldtype" "github.com/facebookincubator/ent/entc/integration/ent/predicate" + "github.com/facebookincubator/ent/schema/field" ) // FieldTypeUpdate is the builder for updating FieldType entities. @@ -568,186 +571,333 @@ func (ftu *FieldTypeUpdate) ExecX(ctx context.Context) { } func (ftu *FieldTypeUpdate) sqlSave(ctx context.Context) (n int, err error) { - var ( - builder = sql.Dialect(ftu.driver.Dialect()) - selector = builder.Select(fieldtype.FieldID).From(builder.Table(fieldtype.Table)) - ) - for _, p := range ftu.predicates { - p(selector) + spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: fieldtype.Table, + Columns: fieldtype.Columns, + ID: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: fieldtype.FieldID, + }, + }, } - rows := &sql.Rows{} - query, args := selector.Query() - if err = ftu.driver.Query(ctx, query, args, rows); err != nil { - return 0, err - } - defer rows.Close() - - var ids []int - for rows.Next() { - var id int - if err := rows.Scan(&id); err != nil { - return 0, fmt.Errorf("ent: failed reading id: %v", err) + if ps := ftu.predicates; len(ps) > 0 { + spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } } - ids = append(ids, id) } - if len(ids) == 0 { - return 0, nil - } - - tx, err := ftu.driver.Tx(ctx) - if err != nil { - return 0, err - } - var ( - res sql.Result - updater = builder.Update(fieldtype.Table) - ) - updater = updater.Where(sql.InInts(fieldtype.FieldID, ids...)) if value := ftu.int; value != nil { - updater.Set(fieldtype.FieldInt, *value) + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: *value, + Column: fieldtype.FieldInt, + }) } if value := ftu.addint; value != nil { - updater.Add(fieldtype.FieldInt, *value) + spec.Fields.Add = append(spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: *value, + Column: fieldtype.FieldInt, + }) } if value := ftu.int8; value != nil { - updater.Set(fieldtype.FieldInt8, *value) + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeInt8, + Value: *value, + Column: fieldtype.FieldInt8, + }) } if value := ftu.addint8; value != nil { - updater.Add(fieldtype.FieldInt8, *value) + spec.Fields.Add = append(spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.TypeInt8, + Value: *value, + Column: fieldtype.FieldInt8, + }) } if value := ftu.int16; value != nil { - updater.Set(fieldtype.FieldInt16, *value) + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeInt16, + Value: *value, + Column: fieldtype.FieldInt16, + }) } if value := ftu.addint16; value != nil { - updater.Add(fieldtype.FieldInt16, *value) + spec.Fields.Add = append(spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.TypeInt16, + Value: *value, + Column: fieldtype.FieldInt16, + }) } if value := ftu.int32; value != nil { - updater.Set(fieldtype.FieldInt32, *value) + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeInt32, + Value: *value, + Column: fieldtype.FieldInt32, + }) } if value := ftu.addint32; value != nil { - updater.Add(fieldtype.FieldInt32, *value) + spec.Fields.Add = append(spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.TypeInt32, + Value: *value, + Column: fieldtype.FieldInt32, + }) } if value := ftu.int64; value != nil { - updater.Set(fieldtype.FieldInt64, *value) + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeInt64, + Value: *value, + Column: fieldtype.FieldInt64, + }) } if value := ftu.addint64; value != nil { - updater.Add(fieldtype.FieldInt64, *value) + spec.Fields.Add = append(spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.TypeInt64, + Value: *value, + Column: fieldtype.FieldInt64, + }) } if value := ftu.optional_int; value != nil { - updater.Set(fieldtype.FieldOptionalInt, *value) + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: *value, + Column: fieldtype.FieldOptionalInt, + }) } if value := ftu.addoptional_int; value != nil { - updater.Add(fieldtype.FieldOptionalInt, *value) + spec.Fields.Add = append(spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: *value, + Column: fieldtype.FieldOptionalInt, + }) } if ftu.clearoptional_int { - updater.SetNull(fieldtype.FieldOptionalInt) + spec.Fields.Clear = append(spec.Fields.Clear, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: fieldtype.FieldOptionalInt, + }) } if value := ftu.optional_int8; value != nil { - updater.Set(fieldtype.FieldOptionalInt8, *value) + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeInt8, + Value: *value, + Column: fieldtype.FieldOptionalInt8, + }) } if value := ftu.addoptional_int8; value != nil { - updater.Add(fieldtype.FieldOptionalInt8, *value) + spec.Fields.Add = append(spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.TypeInt8, + Value: *value, + Column: fieldtype.FieldOptionalInt8, + }) } if ftu.clearoptional_int8 { - updater.SetNull(fieldtype.FieldOptionalInt8) + spec.Fields.Clear = append(spec.Fields.Clear, &sqlgraph.FieldSpec{ + Type: field.TypeInt8, + Column: fieldtype.FieldOptionalInt8, + }) } if value := ftu.optional_int16; value != nil { - updater.Set(fieldtype.FieldOptionalInt16, *value) + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeInt16, + Value: *value, + Column: fieldtype.FieldOptionalInt16, + }) } if value := ftu.addoptional_int16; value != nil { - updater.Add(fieldtype.FieldOptionalInt16, *value) + spec.Fields.Add = append(spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.TypeInt16, + Value: *value, + Column: fieldtype.FieldOptionalInt16, + }) } if ftu.clearoptional_int16 { - updater.SetNull(fieldtype.FieldOptionalInt16) + spec.Fields.Clear = append(spec.Fields.Clear, &sqlgraph.FieldSpec{ + Type: field.TypeInt16, + Column: fieldtype.FieldOptionalInt16, + }) } if value := ftu.optional_int32; value != nil { - updater.Set(fieldtype.FieldOptionalInt32, *value) + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeInt32, + Value: *value, + Column: fieldtype.FieldOptionalInt32, + }) } if value := ftu.addoptional_int32; value != nil { - updater.Add(fieldtype.FieldOptionalInt32, *value) + spec.Fields.Add = append(spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.TypeInt32, + Value: *value, + Column: fieldtype.FieldOptionalInt32, + }) } if ftu.clearoptional_int32 { - updater.SetNull(fieldtype.FieldOptionalInt32) + spec.Fields.Clear = append(spec.Fields.Clear, &sqlgraph.FieldSpec{ + Type: field.TypeInt32, + Column: fieldtype.FieldOptionalInt32, + }) } if value := ftu.optional_int64; value != nil { - updater.Set(fieldtype.FieldOptionalInt64, *value) + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeInt64, + Value: *value, + Column: fieldtype.FieldOptionalInt64, + }) } if value := ftu.addoptional_int64; value != nil { - updater.Add(fieldtype.FieldOptionalInt64, *value) + spec.Fields.Add = append(spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.TypeInt64, + Value: *value, + Column: fieldtype.FieldOptionalInt64, + }) } if ftu.clearoptional_int64 { - updater.SetNull(fieldtype.FieldOptionalInt64) + spec.Fields.Clear = append(spec.Fields.Clear, &sqlgraph.FieldSpec{ + Type: field.TypeInt64, + Column: fieldtype.FieldOptionalInt64, + }) } if value := ftu.nillable_int; value != nil { - updater.Set(fieldtype.FieldNillableInt, *value) + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: *value, + Column: fieldtype.FieldNillableInt, + }) } if value := ftu.addnillable_int; value != nil { - updater.Add(fieldtype.FieldNillableInt, *value) + spec.Fields.Add = append(spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: *value, + Column: fieldtype.FieldNillableInt, + }) } if ftu.clearnillable_int { - updater.SetNull(fieldtype.FieldNillableInt) + spec.Fields.Clear = append(spec.Fields.Clear, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: fieldtype.FieldNillableInt, + }) } if value := ftu.nillable_int8; value != nil { - updater.Set(fieldtype.FieldNillableInt8, *value) + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeInt8, + Value: *value, + Column: fieldtype.FieldNillableInt8, + }) } if value := ftu.addnillable_int8; value != nil { - updater.Add(fieldtype.FieldNillableInt8, *value) + spec.Fields.Add = append(spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.TypeInt8, + Value: *value, + Column: fieldtype.FieldNillableInt8, + }) } if ftu.clearnillable_int8 { - updater.SetNull(fieldtype.FieldNillableInt8) + spec.Fields.Clear = append(spec.Fields.Clear, &sqlgraph.FieldSpec{ + Type: field.TypeInt8, + Column: fieldtype.FieldNillableInt8, + }) } if value := ftu.nillable_int16; value != nil { - updater.Set(fieldtype.FieldNillableInt16, *value) + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeInt16, + Value: *value, + Column: fieldtype.FieldNillableInt16, + }) } if value := ftu.addnillable_int16; value != nil { - updater.Add(fieldtype.FieldNillableInt16, *value) + spec.Fields.Add = append(spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.TypeInt16, + Value: *value, + Column: fieldtype.FieldNillableInt16, + }) } if ftu.clearnillable_int16 { - updater.SetNull(fieldtype.FieldNillableInt16) + spec.Fields.Clear = append(spec.Fields.Clear, &sqlgraph.FieldSpec{ + Type: field.TypeInt16, + Column: fieldtype.FieldNillableInt16, + }) } if value := ftu.nillable_int32; value != nil { - updater.Set(fieldtype.FieldNillableInt32, *value) + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeInt32, + Value: *value, + Column: fieldtype.FieldNillableInt32, + }) } if value := ftu.addnillable_int32; value != nil { - updater.Add(fieldtype.FieldNillableInt32, *value) + spec.Fields.Add = append(spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.TypeInt32, + Value: *value, + Column: fieldtype.FieldNillableInt32, + }) } if ftu.clearnillable_int32 { - updater.SetNull(fieldtype.FieldNillableInt32) + spec.Fields.Clear = append(spec.Fields.Clear, &sqlgraph.FieldSpec{ + Type: field.TypeInt32, + Column: fieldtype.FieldNillableInt32, + }) } if value := ftu.nillable_int64; value != nil { - updater.Set(fieldtype.FieldNillableInt64, *value) + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeInt64, + Value: *value, + Column: fieldtype.FieldNillableInt64, + }) } if value := ftu.addnillable_int64; value != nil { - updater.Add(fieldtype.FieldNillableInt64, *value) + spec.Fields.Add = append(spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.TypeInt64, + Value: *value, + Column: fieldtype.FieldNillableInt64, + }) } if ftu.clearnillable_int64 { - updater.SetNull(fieldtype.FieldNillableInt64) + spec.Fields.Clear = append(spec.Fields.Clear, &sqlgraph.FieldSpec{ + Type: field.TypeInt64, + Column: fieldtype.FieldNillableInt64, + }) } if value := ftu.validate_optional_int32; value != nil { - updater.Set(fieldtype.FieldValidateOptionalInt32, *value) + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeInt32, + Value: *value, + Column: fieldtype.FieldValidateOptionalInt32, + }) } if value := ftu.addvalidate_optional_int32; value != nil { - updater.Add(fieldtype.FieldValidateOptionalInt32, *value) + spec.Fields.Add = append(spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.TypeInt32, + Value: *value, + Column: fieldtype.FieldValidateOptionalInt32, + }) } if ftu.clearvalidate_optional_int32 { - updater.SetNull(fieldtype.FieldValidateOptionalInt32) + spec.Fields.Clear = append(spec.Fields.Clear, &sqlgraph.FieldSpec{ + Type: field.TypeInt32, + Column: fieldtype.FieldValidateOptionalInt32, + }) } if value := ftu.state; value != nil { - updater.Set(fieldtype.FieldState, *value) + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeEnum, + Value: *value, + Column: fieldtype.FieldState, + }) } if ftu.clearstate { - updater.SetNull(fieldtype.FieldState) + spec.Fields.Clear = append(spec.Fields.Clear, &sqlgraph.FieldSpec{ + Type: field.TypeEnum, + Column: fieldtype.FieldState, + }) } - if !updater.Empty() { - query, args := updater.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) + if n, err = sqlgraph.UpdateNodes(ctx, ftu.driver, spec); err != nil { + if cerr, ok := isSQLConstraintError(err); ok { + err = cerr } - } - if err = tx.Commit(); err != nil { return 0, err } - return len(ids), nil + return n, nil } // FieldTypeUpdateOne is the builder for updating a single FieldType entity. @@ -1297,258 +1447,447 @@ func (ftuo *FieldTypeUpdateOne) ExecX(ctx context.Context) { } func (ftuo *FieldTypeUpdateOne) sqlSave(ctx context.Context) (ft *FieldType, err error) { - var ( - builder = sql.Dialect(ftuo.driver.Dialect()) - selector = builder.Select(fieldtype.Columns...).From(builder.Table(fieldtype.Table)) - ) - fieldtype.ID(ftuo.id)(selector) - rows := &sql.Rows{} - query, args := selector.Query() - if err = ftuo.driver.Query(ctx, query, args, rows); err != nil { - return nil, err + spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: fieldtype.Table, + Columns: fieldtype.Columns, + ID: &sqlgraph.FieldSpec{ + Value: ftuo.id, + Type: field.TypeString, + Column: fieldtype.FieldID, + }, + }, } - defer rows.Close() - - var ids []int - for rows.Next() { - var id int - ft = &FieldType{config: ftuo.config} - if err := ft.FromRows(rows); err != nil { - return nil, fmt.Errorf("ent: failed scanning row into FieldType: %v", err) - } - id = ft.id() - ids = append(ids, id) - } - switch n := len(ids); { - case n == 0: - return nil, &ErrNotFound{fmt.Sprintf("FieldType with id: %v", ftuo.id)} - case n > 1: - return nil, fmt.Errorf("ent: more than one FieldType with the same id: %v", ftuo.id) - } - - tx, err := ftuo.driver.Tx(ctx) - if err != nil { - return nil, err - } - var ( - res sql.Result - updater = builder.Update(fieldtype.Table) - ) - updater = updater.Where(sql.InInts(fieldtype.FieldID, ids...)) if value := ftuo.int; value != nil { - updater.Set(fieldtype.FieldInt, *value) - ft.Int = *value + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: *value, + Column: fieldtype.FieldInt, + }) } if value := ftuo.addint; value != nil { - updater.Add(fieldtype.FieldInt, *value) - ft.Int += *value + spec.Fields.Add = append(spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: *value, + Column: fieldtype.FieldInt, + }) } if value := ftuo.int8; value != nil { - updater.Set(fieldtype.FieldInt8, *value) - ft.Int8 = *value + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeInt8, + Value: *value, + Column: fieldtype.FieldInt8, + }) } if value := ftuo.addint8; value != nil { - updater.Add(fieldtype.FieldInt8, *value) - ft.Int8 += *value + spec.Fields.Add = append(spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.TypeInt8, + Value: *value, + Column: fieldtype.FieldInt8, + }) } if value := ftuo.int16; value != nil { - updater.Set(fieldtype.FieldInt16, *value) - ft.Int16 = *value + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeInt16, + Value: *value, + Column: fieldtype.FieldInt16, + }) } if value := ftuo.addint16; value != nil { - updater.Add(fieldtype.FieldInt16, *value) - ft.Int16 += *value + spec.Fields.Add = append(spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.TypeInt16, + Value: *value, + Column: fieldtype.FieldInt16, + }) } if value := ftuo.int32; value != nil { - updater.Set(fieldtype.FieldInt32, *value) - ft.Int32 = *value + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeInt32, + Value: *value, + Column: fieldtype.FieldInt32, + }) } if value := ftuo.addint32; value != nil { - updater.Add(fieldtype.FieldInt32, *value) - ft.Int32 += *value + spec.Fields.Add = append(spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.TypeInt32, + Value: *value, + Column: fieldtype.FieldInt32, + }) } if value := ftuo.int64; value != nil { - updater.Set(fieldtype.FieldInt64, *value) - ft.Int64 = *value + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeInt64, + Value: *value, + Column: fieldtype.FieldInt64, + }) } if value := ftuo.addint64; value != nil { - updater.Add(fieldtype.FieldInt64, *value) - ft.Int64 += *value + spec.Fields.Add = append(spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.TypeInt64, + Value: *value, + Column: fieldtype.FieldInt64, + }) } if value := ftuo.optional_int; value != nil { - updater.Set(fieldtype.FieldOptionalInt, *value) - ft.OptionalInt = *value + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: *value, + Column: fieldtype.FieldOptionalInt, + }) } if value := ftuo.addoptional_int; value != nil { - updater.Add(fieldtype.FieldOptionalInt, *value) - ft.OptionalInt += *value + spec.Fields.Add = append(spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: *value, + Column: fieldtype.FieldOptionalInt, + }) } if ftuo.clearoptional_int { - var value int - ft.OptionalInt = value - updater.SetNull(fieldtype.FieldOptionalInt) + spec.Fields.Clear = append(spec.Fields.Clear, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: fieldtype.FieldOptionalInt, + }) } if value := ftuo.optional_int8; value != nil { - updater.Set(fieldtype.FieldOptionalInt8, *value) - ft.OptionalInt8 = *value + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeInt8, + Value: *value, + Column: fieldtype.FieldOptionalInt8, + }) } if value := ftuo.addoptional_int8; value != nil { - updater.Add(fieldtype.FieldOptionalInt8, *value) - ft.OptionalInt8 += *value + spec.Fields.Add = append(spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.TypeInt8, + Value: *value, + Column: fieldtype.FieldOptionalInt8, + }) } if ftuo.clearoptional_int8 { - var value int8 - ft.OptionalInt8 = value - updater.SetNull(fieldtype.FieldOptionalInt8) + spec.Fields.Clear = append(spec.Fields.Clear, &sqlgraph.FieldSpec{ + Type: field.TypeInt8, + Column: fieldtype.FieldOptionalInt8, + }) } if value := ftuo.optional_int16; value != nil { - updater.Set(fieldtype.FieldOptionalInt16, *value) - ft.OptionalInt16 = *value + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeInt16, + Value: *value, + Column: fieldtype.FieldOptionalInt16, + }) } if value := ftuo.addoptional_int16; value != nil { - updater.Add(fieldtype.FieldOptionalInt16, *value) - ft.OptionalInt16 += *value + spec.Fields.Add = append(spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.TypeInt16, + Value: *value, + Column: fieldtype.FieldOptionalInt16, + }) } if ftuo.clearoptional_int16 { - var value int16 - ft.OptionalInt16 = value - updater.SetNull(fieldtype.FieldOptionalInt16) + spec.Fields.Clear = append(spec.Fields.Clear, &sqlgraph.FieldSpec{ + Type: field.TypeInt16, + Column: fieldtype.FieldOptionalInt16, + }) } if value := ftuo.optional_int32; value != nil { - updater.Set(fieldtype.FieldOptionalInt32, *value) - ft.OptionalInt32 = *value + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeInt32, + Value: *value, + Column: fieldtype.FieldOptionalInt32, + }) } if value := ftuo.addoptional_int32; value != nil { - updater.Add(fieldtype.FieldOptionalInt32, *value) - ft.OptionalInt32 += *value + spec.Fields.Add = append(spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.TypeInt32, + Value: *value, + Column: fieldtype.FieldOptionalInt32, + }) } if ftuo.clearoptional_int32 { - var value int32 - ft.OptionalInt32 = value - updater.SetNull(fieldtype.FieldOptionalInt32) + spec.Fields.Clear = append(spec.Fields.Clear, &sqlgraph.FieldSpec{ + Type: field.TypeInt32, + Column: fieldtype.FieldOptionalInt32, + }) } if value := ftuo.optional_int64; value != nil { - updater.Set(fieldtype.FieldOptionalInt64, *value) - ft.OptionalInt64 = *value + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeInt64, + Value: *value, + Column: fieldtype.FieldOptionalInt64, + }) } if value := ftuo.addoptional_int64; value != nil { - updater.Add(fieldtype.FieldOptionalInt64, *value) - ft.OptionalInt64 += *value + spec.Fields.Add = append(spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.TypeInt64, + Value: *value, + Column: fieldtype.FieldOptionalInt64, + }) } if ftuo.clearoptional_int64 { - var value int64 - ft.OptionalInt64 = value - updater.SetNull(fieldtype.FieldOptionalInt64) + spec.Fields.Clear = append(spec.Fields.Clear, &sqlgraph.FieldSpec{ + Type: field.TypeInt64, + Column: fieldtype.FieldOptionalInt64, + }) } if value := ftuo.nillable_int; value != nil { - updater.Set(fieldtype.FieldNillableInt, *value) - ft.NillableInt = value + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: *value, + Column: fieldtype.FieldNillableInt, + }) } if value := ftuo.addnillable_int; value != nil { - updater.Add(fieldtype.FieldNillableInt, *value) - if ft.NillableInt != nil { - *ft.NillableInt += *value - } else { - ft.NillableInt = value - } + spec.Fields.Add = append(spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: *value, + Column: fieldtype.FieldNillableInt, + }) } if ftuo.clearnillable_int { - ft.NillableInt = nil - updater.SetNull(fieldtype.FieldNillableInt) + spec.Fields.Clear = append(spec.Fields.Clear, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: fieldtype.FieldNillableInt, + }) } if value := ftuo.nillable_int8; value != nil { - updater.Set(fieldtype.FieldNillableInt8, *value) - ft.NillableInt8 = value + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeInt8, + Value: *value, + Column: fieldtype.FieldNillableInt8, + }) } if value := ftuo.addnillable_int8; value != nil { - updater.Add(fieldtype.FieldNillableInt8, *value) - if ft.NillableInt8 != nil { - *ft.NillableInt8 += *value - } else { - ft.NillableInt8 = value - } + spec.Fields.Add = append(spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.TypeInt8, + Value: *value, + Column: fieldtype.FieldNillableInt8, + }) } if ftuo.clearnillable_int8 { - ft.NillableInt8 = nil - updater.SetNull(fieldtype.FieldNillableInt8) + spec.Fields.Clear = append(spec.Fields.Clear, &sqlgraph.FieldSpec{ + Type: field.TypeInt8, + Column: fieldtype.FieldNillableInt8, + }) } if value := ftuo.nillable_int16; value != nil { - updater.Set(fieldtype.FieldNillableInt16, *value) - ft.NillableInt16 = value + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeInt16, + Value: *value, + Column: fieldtype.FieldNillableInt16, + }) } if value := ftuo.addnillable_int16; value != nil { - updater.Add(fieldtype.FieldNillableInt16, *value) - if ft.NillableInt16 != nil { - *ft.NillableInt16 += *value - } else { - ft.NillableInt16 = value - } + spec.Fields.Add = append(spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.TypeInt16, + Value: *value, + Column: fieldtype.FieldNillableInt16, + }) } if ftuo.clearnillable_int16 { - ft.NillableInt16 = nil - updater.SetNull(fieldtype.FieldNillableInt16) + spec.Fields.Clear = append(spec.Fields.Clear, &sqlgraph.FieldSpec{ + Type: field.TypeInt16, + Column: fieldtype.FieldNillableInt16, + }) } if value := ftuo.nillable_int32; value != nil { - updater.Set(fieldtype.FieldNillableInt32, *value) - ft.NillableInt32 = value + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeInt32, + Value: *value, + Column: fieldtype.FieldNillableInt32, + }) } if value := ftuo.addnillable_int32; value != nil { - updater.Add(fieldtype.FieldNillableInt32, *value) - if ft.NillableInt32 != nil { - *ft.NillableInt32 += *value - } else { - ft.NillableInt32 = value - } + spec.Fields.Add = append(spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.TypeInt32, + Value: *value, + Column: fieldtype.FieldNillableInt32, + }) } if ftuo.clearnillable_int32 { - ft.NillableInt32 = nil - updater.SetNull(fieldtype.FieldNillableInt32) + spec.Fields.Clear = append(spec.Fields.Clear, &sqlgraph.FieldSpec{ + Type: field.TypeInt32, + Column: fieldtype.FieldNillableInt32, + }) } if value := ftuo.nillable_int64; value != nil { - updater.Set(fieldtype.FieldNillableInt64, *value) - ft.NillableInt64 = value + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeInt64, + Value: *value, + Column: fieldtype.FieldNillableInt64, + }) } if value := ftuo.addnillable_int64; value != nil { - updater.Add(fieldtype.FieldNillableInt64, *value) - if ft.NillableInt64 != nil { - *ft.NillableInt64 += *value - } else { - ft.NillableInt64 = value - } + spec.Fields.Add = append(spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.TypeInt64, + Value: *value, + Column: fieldtype.FieldNillableInt64, + }) } if ftuo.clearnillable_int64 { - ft.NillableInt64 = nil - updater.SetNull(fieldtype.FieldNillableInt64) + spec.Fields.Clear = append(spec.Fields.Clear, &sqlgraph.FieldSpec{ + Type: field.TypeInt64, + Column: fieldtype.FieldNillableInt64, + }) } if value := ftuo.validate_optional_int32; value != nil { - updater.Set(fieldtype.FieldValidateOptionalInt32, *value) - ft.ValidateOptionalInt32 = *value + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeInt32, + Value: *value, + Column: fieldtype.FieldValidateOptionalInt32, + }) } if value := ftuo.addvalidate_optional_int32; value != nil { - updater.Add(fieldtype.FieldValidateOptionalInt32, *value) - ft.ValidateOptionalInt32 += *value + spec.Fields.Add = append(spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.TypeInt32, + Value: *value, + Column: fieldtype.FieldValidateOptionalInt32, + }) } if ftuo.clearvalidate_optional_int32 { - var value int32 - ft.ValidateOptionalInt32 = value - updater.SetNull(fieldtype.FieldValidateOptionalInt32) + spec.Fields.Clear = append(spec.Fields.Clear, &sqlgraph.FieldSpec{ + Type: field.TypeInt32, + Column: fieldtype.FieldValidateOptionalInt32, + }) } if value := ftuo.state; value != nil { - updater.Set(fieldtype.FieldState, *value) - ft.State = *value + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeEnum, + Value: *value, + Column: fieldtype.FieldState, + }) } if ftuo.clearstate { - var value fieldtype.State - ft.State = value - updater.SetNull(fieldtype.FieldState) + spec.Fields.Clear = append(spec.Fields.Clear, &sqlgraph.FieldSpec{ + Type: field.TypeEnum, + Column: fieldtype.FieldState, + }) } - if !updater.Empty() { - query, args := updater.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) + ft = &FieldType{config: ftuo.config} + spec.ScanTypes = []interface{}{ + &sql.NullInt64{}, + &sql.NullInt64{}, + &sql.NullInt64{}, + &sql.NullInt64{}, + &sql.NullInt64{}, + &sql.NullInt64{}, + &sql.NullInt64{}, + &sql.NullInt64{}, + &sql.NullInt64{}, + &sql.NullInt64{}, + &sql.NullInt64{}, + &sql.NullInt64{}, + &sql.NullInt64{}, + &sql.NullInt64{}, + &sql.NullInt64{}, + &sql.NullInt64{}, + &sql.NullInt64{}, + &sql.NullString{}, + } + spec.Assign = func(values ...interface{}) error { + if m, n := len(values), len(spec.ScanTypes); m != n { + return fmt.Errorf("mismatch number of scan values: %d != %d", m, n) } + value, ok := values[0].(*sql.NullInt64) + if !ok { + return fmt.Errorf("unexpected type %T for field id", value) + } + ft.ID = strconv.FormatInt(value.Int64, 10) + values = values[1:] + if value, ok := values[0].(*sql.NullInt64); !ok { + return fmt.Errorf("unexpected type %T for field int", values[0]) + } else if value.Valid { + ft.Int = int(value.Int64) + } + if value, ok := values[1].(*sql.NullInt64); !ok { + return fmt.Errorf("unexpected type %T for field int8", values[1]) + } else if value.Valid { + ft.Int8 = int8(value.Int64) + } + if value, ok := values[2].(*sql.NullInt64); !ok { + return fmt.Errorf("unexpected type %T for field int16", values[2]) + } else if value.Valid { + ft.Int16 = int16(value.Int64) + } + if value, ok := values[3].(*sql.NullInt64); !ok { + return fmt.Errorf("unexpected type %T for field int32", values[3]) + } else if value.Valid { + ft.Int32 = int32(value.Int64) + } + if value, ok := values[4].(*sql.NullInt64); !ok { + return fmt.Errorf("unexpected type %T for field int64", values[4]) + } else if value.Valid { + ft.Int64 = value.Int64 + } + if value, ok := values[5].(*sql.NullInt64); !ok { + return fmt.Errorf("unexpected type %T for field optional_int", values[5]) + } else if value.Valid { + ft.OptionalInt = int(value.Int64) + } + if value, ok := values[6].(*sql.NullInt64); !ok { + return fmt.Errorf("unexpected type %T for field optional_int8", values[6]) + } else if value.Valid { + ft.OptionalInt8 = int8(value.Int64) + } + if value, ok := values[7].(*sql.NullInt64); !ok { + return fmt.Errorf("unexpected type %T for field optional_int16", values[7]) + } else if value.Valid { + ft.OptionalInt16 = int16(value.Int64) + } + if value, ok := values[8].(*sql.NullInt64); !ok { + return fmt.Errorf("unexpected type %T for field optional_int32", values[8]) + } else if value.Valid { + ft.OptionalInt32 = int32(value.Int64) + } + if value, ok := values[9].(*sql.NullInt64); !ok { + return fmt.Errorf("unexpected type %T for field optional_int64", values[9]) + } else if value.Valid { + ft.OptionalInt64 = value.Int64 + } + if value, ok := values[10].(*sql.NullInt64); !ok { + return fmt.Errorf("unexpected type %T for field nillable_int", values[10]) + } else if value.Valid { + ft.NillableInt = new(int) + *ft.NillableInt = int(value.Int64) + } + if value, ok := values[11].(*sql.NullInt64); !ok { + return fmt.Errorf("unexpected type %T for field nillable_int8", values[11]) + } else if value.Valid { + ft.NillableInt8 = new(int8) + *ft.NillableInt8 = int8(value.Int64) + } + if value, ok := values[12].(*sql.NullInt64); !ok { + return fmt.Errorf("unexpected type %T for field nillable_int16", values[12]) + } else if value.Valid { + ft.NillableInt16 = new(int16) + *ft.NillableInt16 = int16(value.Int64) + } + if value, ok := values[13].(*sql.NullInt64); !ok { + return fmt.Errorf("unexpected type %T for field nillable_int32", values[13]) + } else if value.Valid { + ft.NillableInt32 = new(int32) + *ft.NillableInt32 = int32(value.Int64) + } + if value, ok := values[14].(*sql.NullInt64); !ok { + return fmt.Errorf("unexpected type %T for field nillable_int64", values[14]) + } else if value.Valid { + ft.NillableInt64 = new(int64) + *ft.NillableInt64 = value.Int64 + } + if value, ok := values[15].(*sql.NullInt64); !ok { + return fmt.Errorf("unexpected type %T for field validate_optional_int32", values[15]) + } else if value.Valid { + ft.ValidateOptionalInt32 = int32(value.Int64) + } + if value, ok := values[16].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field state", values[16]) + } else if value.Valid { + ft.State = fieldtype.State(value.String) + } + return nil } - if err = tx.Commit(); err != nil { + if err = sqlgraph.UpdateNode(ctx, ftuo.driver, spec); err != nil { + if cerr, ok := isSQLConstraintError(err); ok { + err = cerr + } return nil, err } return ft, nil diff --git a/entc/integration/ent/file_update.go b/entc/integration/ent/file_update.go index 5a806ebcd..0665afa54 100644 --- a/entc/integration/ent/file_update.go +++ b/entc/integration/ent/file_update.go @@ -13,10 +13,12 @@ import ( "strconv" "github.com/facebookincubator/ent/dialect/sql" + "github.com/facebookincubator/ent/dialect/sql/sqlgraph" "github.com/facebookincubator/ent/entc/integration/ent/file" "github.com/facebookincubator/ent/entc/integration/ent/filetype" "github.com/facebookincubator/ent/entc/integration/ent/predicate" "github.com/facebookincubator/ent/entc/integration/ent/user" + "github.com/facebookincubator/ent/schema/field" ) // FileUpdate is the builder for updating File entities. @@ -210,122 +212,155 @@ func (fu *FileUpdate) ExecX(ctx context.Context) { } func (fu *FileUpdate) sqlSave(ctx context.Context) (n int, err error) { - var ( - builder = sql.Dialect(fu.driver.Dialect()) - selector = builder.Select(file.FieldID).From(builder.Table(file.Table)) - ) - for _, p := range fu.predicates { - p(selector) + spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: file.Table, + Columns: file.Columns, + ID: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: file.FieldID, + }, + }, } - rows := &sql.Rows{} - query, args := selector.Query() - if err = fu.driver.Query(ctx, query, args, rows); err != nil { - return 0, err - } - defer rows.Close() - - var ids []int - for rows.Next() { - var id int - if err := rows.Scan(&id); err != nil { - return 0, fmt.Errorf("ent: failed reading id: %v", err) + if ps := fu.predicates; len(ps) > 0 { + spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } } - ids = append(ids, id) } - if len(ids) == 0 { - return 0, nil - } - - tx, err := fu.driver.Tx(ctx) - if err != nil { - return 0, err - } - var ( - res sql.Result - updater = builder.Update(file.Table) - ) - updater = updater.Where(sql.InInts(file.FieldID, ids...)) if value := fu.size; value != nil { - updater.Set(file.FieldSize, *value) + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: *value, + Column: file.FieldSize, + }) } if value := fu.addsize; value != nil { - updater.Add(file.FieldSize, *value) + spec.Fields.Add = append(spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: *value, + Column: file.FieldSize, + }) } if value := fu.name; value != nil { - updater.Set(file.FieldName, *value) + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: *value, + Column: file.FieldName, + }) } if value := fu.user; value != nil { - updater.Set(file.FieldUser, *value) + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: *value, + Column: file.FieldUser, + }) } if fu.clearuser { - updater.SetNull(file.FieldUser) + spec.Fields.Clear = append(spec.Fields.Clear, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: file.FieldUser, + }) } if value := fu.group; value != nil { - updater.Set(file.FieldGroup, *value) + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: *value, + Column: file.FieldGroup, + }) } if fu.cleargroup { - updater.SetNull(file.FieldGroup) - } - if !updater.Empty() { - query, args := updater.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } + spec.Fields.Clear = append(spec.Fields.Clear, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: file.FieldGroup, + }) } if fu.clearedOwner { - query, args := builder.Update(file.OwnerTable). - SetNull(file.OwnerColumn). - Where(sql.InInts(user.FieldID, ids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: file.OwnerTable, + Columns: []string{file.OwnerColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: user.FieldID, + }, + }, } + spec.Edges.Clear = append(spec.Edges.Clear, edge) } - if len(fu.owner) > 0 { - for eid := range fu.owner { - eid, serr := strconv.Atoi(eid) - if serr != nil { - err = rollback(tx, serr) - return - } - query, args := builder.Update(file.OwnerTable). - Set(file.OwnerColumn, eid). - Where(sql.InInts(file.FieldID, ids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } + if nodes := fu.owner; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: file.OwnerTable, + Columns: []string{file.OwnerColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: user.FieldID, + }, + }, } + for k, _ := range nodes { + k, err := strconv.Atoi(k) + if err != nil { + return 0, err + } + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + spec.Edges.Add = append(spec.Edges.Add, edge) } if fu.clearedType { - query, args := builder.Update(file.TypeTable). - SetNull(file.TypeColumn). - Where(sql.InInts(filetype.FieldID, ids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: file.TypeTable, + Columns: []string{file.TypeColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: filetype.FieldID, + }, + }, } + spec.Edges.Clear = append(spec.Edges.Clear, edge) } - if len(fu._type) > 0 { - for eid := range fu._type { - eid, serr := strconv.Atoi(eid) - if serr != nil { - err = rollback(tx, serr) - return - } - query, args := builder.Update(file.TypeTable). - Set(file.TypeColumn, eid). - Where(sql.InInts(file.FieldID, ids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } + if nodes := fu._type; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: file.TypeTable, + Columns: []string{file.TypeColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: filetype.FieldID, + }, + }, } + for k, _ := range nodes { + k, err := strconv.Atoi(k) + if err != nil { + return 0, err + } + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + spec.Edges.Add = append(spec.Edges.Add, edge) } - if err = tx.Commit(); err != nil { + if n, err = sqlgraph.UpdateNodes(ctx, fu.driver, spec); err != nil { + if cerr, ok := isSQLConstraintError(err); ok { + err = cerr + } return 0, err } - return len(ids), nil + return n, nil } // FileUpdateOne is the builder for updating a single File entity. @@ -513,130 +548,187 @@ func (fuo *FileUpdateOne) ExecX(ctx context.Context) { } func (fuo *FileUpdateOne) sqlSave(ctx context.Context) (f *File, err error) { - var ( - builder = sql.Dialect(fuo.driver.Dialect()) - selector = builder.Select(file.Columns...).From(builder.Table(file.Table)) - ) - file.ID(fuo.id)(selector) - rows := &sql.Rows{} - query, args := selector.Query() - if err = fuo.driver.Query(ctx, query, args, rows); err != nil { - return nil, err + spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: file.Table, + Columns: file.Columns, + ID: &sqlgraph.FieldSpec{ + Value: fuo.id, + Type: field.TypeString, + Column: file.FieldID, + }, + }, } - defer rows.Close() - - var ids []int - for rows.Next() { - var id int - f = &File{config: fuo.config} - if err := f.FromRows(rows); err != nil { - return nil, fmt.Errorf("ent: failed scanning row into File: %v", err) - } - id = f.id() - ids = append(ids, id) - } - switch n := len(ids); { - case n == 0: - return nil, &ErrNotFound{fmt.Sprintf("File with id: %v", fuo.id)} - case n > 1: - return nil, fmt.Errorf("ent: more than one File with the same id: %v", fuo.id) - } - - tx, err := fuo.driver.Tx(ctx) - if err != nil { - return nil, err - } - var ( - res sql.Result - updater = builder.Update(file.Table) - ) - updater = updater.Where(sql.InInts(file.FieldID, ids...)) if value := fuo.size; value != nil { - updater.Set(file.FieldSize, *value) - f.Size = *value + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: *value, + Column: file.FieldSize, + }) } if value := fuo.addsize; value != nil { - updater.Add(file.FieldSize, *value) - f.Size += *value + spec.Fields.Add = append(spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: *value, + Column: file.FieldSize, + }) } if value := fuo.name; value != nil { - updater.Set(file.FieldName, *value) - f.Name = *value + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: *value, + Column: file.FieldName, + }) } if value := fuo.user; value != nil { - updater.Set(file.FieldUser, *value) - f.User = value + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: *value, + Column: file.FieldUser, + }) } if fuo.clearuser { - f.User = nil - updater.SetNull(file.FieldUser) + spec.Fields.Clear = append(spec.Fields.Clear, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: file.FieldUser, + }) } if value := fuo.group; value != nil { - updater.Set(file.FieldGroup, *value) - f.Group = *value + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: *value, + Column: file.FieldGroup, + }) } if fuo.cleargroup { - var value string - f.Group = value - updater.SetNull(file.FieldGroup) - } - if !updater.Empty() { - query, args := updater.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) - } + spec.Fields.Clear = append(spec.Fields.Clear, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: file.FieldGroup, + }) } if fuo.clearedOwner { - query, args := builder.Update(file.OwnerTable). - SetNull(file.OwnerColumn). - Where(sql.InInts(user.FieldID, ids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: file.OwnerTable, + Columns: []string{file.OwnerColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: user.FieldID, + }, + }, } + spec.Edges.Clear = append(spec.Edges.Clear, edge) } - if len(fuo.owner) > 0 { - for eid := range fuo.owner { - eid, serr := strconv.Atoi(eid) - if serr != nil { - err = rollback(tx, serr) - return - } - query, args := builder.Update(file.OwnerTable). - Set(file.OwnerColumn, eid). - Where(sql.InInts(file.FieldID, ids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) - } + if nodes := fuo.owner; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: file.OwnerTable, + Columns: []string{file.OwnerColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: user.FieldID, + }, + }, } + for k, _ := range nodes { + k, err := strconv.Atoi(k) + if err != nil { + return nil, err + } + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + spec.Edges.Add = append(spec.Edges.Add, edge) } if fuo.clearedType { - query, args := builder.Update(file.TypeTable). - SetNull(file.TypeColumn). - Where(sql.InInts(filetype.FieldID, ids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: file.TypeTable, + Columns: []string{file.TypeColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: filetype.FieldID, + }, + }, } + spec.Edges.Clear = append(spec.Edges.Clear, edge) } - if len(fuo._type) > 0 { - for eid := range fuo._type { - eid, serr := strconv.Atoi(eid) - if serr != nil { - err = rollback(tx, serr) - return - } - query, args := builder.Update(file.TypeTable). - Set(file.TypeColumn, eid). - Where(sql.InInts(file.FieldID, ids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) - } + if nodes := fuo._type; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: file.TypeTable, + Columns: []string{file.TypeColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: filetype.FieldID, + }, + }, } + for k, _ := range nodes { + k, err := strconv.Atoi(k) + if err != nil { + return nil, err + } + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + spec.Edges.Add = append(spec.Edges.Add, edge) } - if err = tx.Commit(); err != nil { + f = &File{config: fuo.config} + spec.ScanTypes = []interface{}{ + &sql.NullInt64{}, + &sql.NullInt64{}, + &sql.NullString{}, + &sql.NullString{}, + &sql.NullString{}, + } + spec.Assign = func(values ...interface{}) error { + if m, n := len(values), len(spec.ScanTypes); m != n { + return fmt.Errorf("mismatch number of scan values: %d != %d", m, n) + } + value, ok := values[0].(*sql.NullInt64) + if !ok { + return fmt.Errorf("unexpected type %T for field id", value) + } + f.ID = strconv.FormatInt(value.Int64, 10) + values = values[1:] + if value, ok := values[0].(*sql.NullInt64); !ok { + return fmt.Errorf("unexpected type %T for field size", values[0]) + } else if value.Valid { + f.Size = int(value.Int64) + } + if value, ok := values[1].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field name", values[1]) + } else if value.Valid { + f.Name = value.String + } + if value, ok := values[2].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field user", values[2]) + } else if value.Valid { + f.User = new(string) + *f.User = value.String + } + if value, ok := values[3].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field group", values[3]) + } else if value.Valid { + f.Group = value.String + } + return nil + } + if err = sqlgraph.UpdateNode(ctx, fuo.driver, spec); err != nil { + if cerr, ok := isSQLConstraintError(err); ok { + err = cerr + } return nil, err } return f, nil diff --git a/entc/integration/ent/filetype_update.go b/entc/integration/ent/filetype_update.go index dc0fe0c50..1c802feec 100644 --- a/entc/integration/ent/filetype_update.go +++ b/entc/integration/ent/filetype_update.go @@ -12,9 +12,11 @@ import ( "strconv" "github.com/facebookincubator/ent/dialect/sql" + "github.com/facebookincubator/ent/dialect/sql/sqlgraph" "github.com/facebookincubator/ent/entc/integration/ent/file" "github.com/facebookincubator/ent/entc/integration/ent/filetype" "github.com/facebookincubator/ent/entc/integration/ent/predicate" + "github.com/facebookincubator/ent/schema/field" ) // FileTypeUpdate is the builder for updating FileType entities. @@ -106,100 +108,83 @@ func (ftu *FileTypeUpdate) ExecX(ctx context.Context) { } func (ftu *FileTypeUpdate) sqlSave(ctx context.Context) (n int, err error) { - var ( - builder = sql.Dialect(ftu.driver.Dialect()) - selector = builder.Select(filetype.FieldID).From(builder.Table(filetype.Table)) - ) - for _, p := range ftu.predicates { - p(selector) + spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: filetype.Table, + Columns: filetype.Columns, + ID: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: filetype.FieldID, + }, + }, } - rows := &sql.Rows{} - query, args := selector.Query() - if err = ftu.driver.Query(ctx, query, args, rows); err != nil { - return 0, err - } - defer rows.Close() - - var ids []int - for rows.Next() { - var id int - if err := rows.Scan(&id); err != nil { - return 0, fmt.Errorf("ent: failed reading id: %v", err) + if ps := ftu.predicates; len(ps) > 0 { + spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } } - ids = append(ids, id) } - if len(ids) == 0 { - return 0, nil - } - - tx, err := ftu.driver.Tx(ctx) - if err != nil { - return 0, err - } - var ( - res sql.Result - updater = builder.Update(filetype.Table) - ) - updater = updater.Where(sql.InInts(filetype.FieldID, ids...)) if value := ftu.name; value != nil { - updater.Set(filetype.FieldName, *value) + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: *value, + Column: filetype.FieldName, + }) } - if !updater.Empty() { - query, args := updater.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) + if nodes := ftu.removedFiles; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: filetype.FilesTable, + Columns: []string{filetype.FilesColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: file.FieldID, + }, + }, } - } - if len(ftu.removedFiles) > 0 { - eids := make([]int, len(ftu.removedFiles)) - for eid := range ftu.removedFiles { - eid, serr := strconv.Atoi(eid) - if serr != nil { - err = rollback(tx, serr) - return - } - eids = append(eids, eid) - } - query, args := builder.Update(filetype.FilesTable). - SetNull(filetype.FilesColumn). - Where(sql.InInts(filetype.FilesColumn, ids...)). - Where(sql.InInts(file.FieldID, eids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } - } - if len(ftu.files) > 0 { - for _, id := range ids { - p := sql.P() - for eid := range ftu.files { - eid, serr := strconv.Atoi(eid) - if serr != nil { - err = rollback(tx, serr) - return - } - p.Or().EQ(file.FieldID, eid) - } - query, args := builder.Update(filetype.FilesTable). - Set(filetype.FilesColumn, id). - Where(sql.And(p, sql.IsNull(filetype.FilesColumn))). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } - affected, err := res.RowsAffected() + for k, _ := range nodes { + k, err := strconv.Atoi(k) if err != nil { - return 0, rollback(tx, err) - } - if int(affected) < len(ftu.files) { - return 0, rollback(tx, &ConstraintError{msg: fmt.Sprintf("one of \"files\" %v already connected to a different \"FileType\"", keys(ftu.files))}) + return 0, err } + edge.Target.Nodes = append(edge.Target.Nodes, k) } + spec.Edges.Clear = append(spec.Edges.Clear, edge) } - if err = tx.Commit(); err != nil { + if nodes := ftu.files; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: filetype.FilesTable, + Columns: []string{filetype.FilesColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: file.FieldID, + }, + }, + } + for k, _ := range nodes { + k, err := strconv.Atoi(k) + if err != nil { + return 0, err + } + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + spec.Edges.Add = append(spec.Edges.Add, edge) + } + if n, err = sqlgraph.UpdateNodes(ctx, ftu.driver, spec); err != nil { + if cerr, ok := isSQLConstraintError(err); ok { + err = cerr + } return 0, err } - return len(ids), nil + return n, nil } // FileTypeUpdateOne is the builder for updating a single FileType entity. @@ -285,101 +270,96 @@ func (ftuo *FileTypeUpdateOne) ExecX(ctx context.Context) { } func (ftuo *FileTypeUpdateOne) sqlSave(ctx context.Context) (ft *FileType, err error) { - var ( - builder = sql.Dialect(ftuo.driver.Dialect()) - selector = builder.Select(filetype.Columns...).From(builder.Table(filetype.Table)) - ) - filetype.ID(ftuo.id)(selector) - rows := &sql.Rows{} - query, args := selector.Query() - if err = ftuo.driver.Query(ctx, query, args, rows); err != nil { - return nil, err + spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: filetype.Table, + Columns: filetype.Columns, + ID: &sqlgraph.FieldSpec{ + Value: ftuo.id, + Type: field.TypeString, + Column: filetype.FieldID, + }, + }, } - defer rows.Close() - - var ids []int - for rows.Next() { - var id int - ft = &FileType{config: ftuo.config} - if err := ft.FromRows(rows); err != nil { - return nil, fmt.Errorf("ent: failed scanning row into FileType: %v", err) - } - id = ft.id() - ids = append(ids, id) - } - switch n := len(ids); { - case n == 0: - return nil, &ErrNotFound{fmt.Sprintf("FileType with id: %v", ftuo.id)} - case n > 1: - return nil, fmt.Errorf("ent: more than one FileType with the same id: %v", ftuo.id) - } - - tx, err := ftuo.driver.Tx(ctx) - if err != nil { - return nil, err - } - var ( - res sql.Result - updater = builder.Update(filetype.Table) - ) - updater = updater.Where(sql.InInts(filetype.FieldID, ids...)) if value := ftuo.name; value != nil { - updater.Set(filetype.FieldName, *value) - ft.Name = *value + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: *value, + Column: filetype.FieldName, + }) } - if !updater.Empty() { - query, args := updater.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) + if nodes := ftuo.removedFiles; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: filetype.FilesTable, + Columns: []string{filetype.FilesColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: file.FieldID, + }, + }, } - } - if len(ftuo.removedFiles) > 0 { - eids := make([]int, len(ftuo.removedFiles)) - for eid := range ftuo.removedFiles { - eid, serr := strconv.Atoi(eid) - if serr != nil { - err = rollback(tx, serr) - return - } - eids = append(eids, eid) - } - query, args := builder.Update(filetype.FilesTable). - SetNull(filetype.FilesColumn). - Where(sql.InInts(filetype.FilesColumn, ids...)). - Where(sql.InInts(file.FieldID, eids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) - } - } - if len(ftuo.files) > 0 { - for _, id := range ids { - p := sql.P() - for eid := range ftuo.files { - eid, serr := strconv.Atoi(eid) - if serr != nil { - err = rollback(tx, serr) - return - } - p.Or().EQ(file.FieldID, eid) - } - query, args := builder.Update(filetype.FilesTable). - Set(filetype.FilesColumn, id). - Where(sql.And(p, sql.IsNull(filetype.FilesColumn))). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) - } - affected, err := res.RowsAffected() + for k, _ := range nodes { + k, err := strconv.Atoi(k) if err != nil { - return nil, rollback(tx, err) - } - if int(affected) < len(ftuo.files) { - return nil, rollback(tx, &ConstraintError{msg: fmt.Sprintf("one of \"files\" %v already connected to a different \"FileType\"", keys(ftuo.files))}) + return nil, err } + edge.Target.Nodes = append(edge.Target.Nodes, k) } + spec.Edges.Clear = append(spec.Edges.Clear, edge) } - if err = tx.Commit(); err != nil { + if nodes := ftuo.files; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: filetype.FilesTable, + Columns: []string{filetype.FilesColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: file.FieldID, + }, + }, + } + for k, _ := range nodes { + k, err := strconv.Atoi(k) + if err != nil { + return nil, err + } + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + spec.Edges.Add = append(spec.Edges.Add, edge) + } + ft = &FileType{config: ftuo.config} + spec.ScanTypes = []interface{}{ + &sql.NullInt64{}, + &sql.NullString{}, + } + spec.Assign = func(values ...interface{}) error { + if m, n := len(values), len(spec.ScanTypes); m != n { + return fmt.Errorf("mismatch number of scan values: %d != %d", m, n) + } + value, ok := values[0].(*sql.NullInt64) + if !ok { + return fmt.Errorf("unexpected type %T for field id", value) + } + ft.ID = strconv.FormatInt(value.Int64, 10) + values = values[1:] + if value, ok := values[0].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field name", values[0]) + } else if value.Valid { + ft.Name = value.String + } + return nil + } + if err = sqlgraph.UpdateNode(ctx, ftuo.driver, spec); err != nil { + if cerr, ok := isSQLConstraintError(err); ok { + err = cerr + } return nil, err } return ft, nil diff --git a/entc/integration/ent/group_update.go b/entc/integration/ent/group_update.go index c83213589..18e235baa 100644 --- a/entc/integration/ent/group_update.go +++ b/entc/integration/ent/group_update.go @@ -14,11 +14,13 @@ import ( "time" "github.com/facebookincubator/ent/dialect/sql" + "github.com/facebookincubator/ent/dialect/sql/sqlgraph" "github.com/facebookincubator/ent/entc/integration/ent/file" "github.com/facebookincubator/ent/entc/integration/ent/group" "github.com/facebookincubator/ent/entc/integration/ent/groupinfo" "github.com/facebookincubator/ent/entc/integration/ent/predicate" "github.com/facebookincubator/ent/entc/integration/ent/user" + "github.com/facebookincubator/ent/schema/field" ) // GroupUpdate is the builder for updating Group entities. @@ -317,232 +319,261 @@ func (gu *GroupUpdate) ExecX(ctx context.Context) { } func (gu *GroupUpdate) sqlSave(ctx context.Context) (n int, err error) { - var ( - builder = sql.Dialect(gu.driver.Dialect()) - selector = builder.Select(group.FieldID).From(builder.Table(group.Table)) - ) - for _, p := range gu.predicates { - p(selector) + spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: group.Table, + Columns: group.Columns, + ID: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: group.FieldID, + }, + }, } - rows := &sql.Rows{} - query, args := selector.Query() - if err = gu.driver.Query(ctx, query, args, rows); err != nil { - return 0, err - } - defer rows.Close() - - var ids []int - for rows.Next() { - var id int - if err := rows.Scan(&id); err != nil { - return 0, fmt.Errorf("ent: failed reading id: %v", err) + if ps := gu.predicates; len(ps) > 0 { + spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } } - ids = append(ids, id) } - if len(ids) == 0 { - return 0, nil - } - - tx, err := gu.driver.Tx(ctx) - if err != nil { - return 0, err - } - var ( - res sql.Result - updater = builder.Update(group.Table) - ) - updater = updater.Where(sql.InInts(group.FieldID, ids...)) if value := gu.active; value != nil { - updater.Set(group.FieldActive, *value) + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeBool, + Value: *value, + Column: group.FieldActive, + }) } if value := gu.expire; value != nil { - updater.Set(group.FieldExpire, *value) + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeTime, + Value: *value, + Column: group.FieldExpire, + }) } if value := gu._type; value != nil { - updater.Set(group.FieldType, *value) + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: *value, + Column: group.FieldType, + }) } if gu.clear_type { - updater.SetNull(group.FieldType) + spec.Fields.Clear = append(spec.Fields.Clear, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: group.FieldType, + }) } if value := gu.max_users; value != nil { - updater.Set(group.FieldMaxUsers, *value) + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: *value, + Column: group.FieldMaxUsers, + }) } if value := gu.addmax_users; value != nil { - updater.Add(group.FieldMaxUsers, *value) + spec.Fields.Add = append(spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: *value, + Column: group.FieldMaxUsers, + }) } if gu.clearmax_users { - updater.SetNull(group.FieldMaxUsers) + spec.Fields.Clear = append(spec.Fields.Clear, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: group.FieldMaxUsers, + }) } if value := gu.name; value != nil { - updater.Set(group.FieldName, *value) + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: *value, + Column: group.FieldName, + }) } - if !updater.Empty() { - query, args := updater.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) + if nodes := gu.removedFiles; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: group.FilesTable, + Columns: []string{group.FilesColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: file.FieldID, + }, + }, } - } - if len(gu.removedFiles) > 0 { - eids := make([]int, len(gu.removedFiles)) - for eid := range gu.removedFiles { - eid, serr := strconv.Atoi(eid) - if serr != nil { - err = rollback(tx, serr) - return - } - eids = append(eids, eid) - } - query, args := builder.Update(group.FilesTable). - SetNull(group.FilesColumn). - Where(sql.InInts(group.FilesColumn, ids...)). - Where(sql.InInts(file.FieldID, eids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } - } - if len(gu.files) > 0 { - for _, id := range ids { - p := sql.P() - for eid := range gu.files { - eid, serr := strconv.Atoi(eid) - if serr != nil { - err = rollback(tx, serr) - return - } - p.Or().EQ(file.FieldID, eid) - } - query, args := builder.Update(group.FilesTable). - Set(group.FilesColumn, id). - Where(sql.And(p, sql.IsNull(group.FilesColumn))). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } - affected, err := res.RowsAffected() + for k, _ := range nodes { + k, err := strconv.Atoi(k) if err != nil { - return 0, rollback(tx, err) - } - if int(affected) < len(gu.files) { - return 0, rollback(tx, &ConstraintError{msg: fmt.Sprintf("one of \"files\" %v already connected to a different \"Group\"", keys(gu.files))}) + return 0, err } + edge.Target.Nodes = append(edge.Target.Nodes, k) } + spec.Edges.Clear = append(spec.Edges.Clear, edge) } - if len(gu.removedBlocked) > 0 { - eids := make([]int, len(gu.removedBlocked)) - for eid := range gu.removedBlocked { - eid, serr := strconv.Atoi(eid) - if serr != nil { - err = rollback(tx, serr) - return - } - eids = append(eids, eid) + if nodes := gu.files; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: group.FilesTable, + Columns: []string{group.FilesColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: file.FieldID, + }, + }, } - query, args := builder.Update(group.BlockedTable). - SetNull(group.BlockedColumn). - Where(sql.InInts(group.BlockedColumn, ids...)). - Where(sql.InInts(user.FieldID, eids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } - } - if len(gu.blocked) > 0 { - for _, id := range ids { - p := sql.P() - for eid := range gu.blocked { - eid, serr := strconv.Atoi(eid) - if serr != nil { - err = rollback(tx, serr) - return - } - p.Or().EQ(user.FieldID, eid) - } - query, args := builder.Update(group.BlockedTable). - Set(group.BlockedColumn, id). - Where(sql.And(p, sql.IsNull(group.BlockedColumn))). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } - affected, err := res.RowsAffected() + for k, _ := range nodes { + k, err := strconv.Atoi(k) if err != nil { - return 0, rollback(tx, err) - } - if int(affected) < len(gu.blocked) { - return 0, rollback(tx, &ConstraintError{msg: fmt.Sprintf("one of \"blocked\" %v already connected to a different \"Group\"", keys(gu.blocked))}) + return 0, err } + edge.Target.Nodes = append(edge.Target.Nodes, k) } + spec.Edges.Add = append(spec.Edges.Add, edge) } - if len(gu.removedUsers) > 0 { - eids := make([]int, len(gu.removedUsers)) - for eid := range gu.removedUsers { - eid, serr := strconv.Atoi(eid) - if serr != nil { - err = rollback(tx, serr) - return + if nodes := gu.removedBlocked; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: group.BlockedTable, + Columns: []string{group.BlockedColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: user.FieldID, + }, + }, + } + for k, _ := range nodes { + k, err := strconv.Atoi(k) + if err != nil { + return 0, err } - eids = append(eids, eid) - } - query, args := builder.Delete(group.UsersTable). - Where(sql.InInts(group.UsersPrimaryKey[1], ids...)). - Where(sql.InInts(group.UsersPrimaryKey[0], eids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) + edge.Target.Nodes = append(edge.Target.Nodes, k) } + spec.Edges.Clear = append(spec.Edges.Clear, edge) } - if len(gu.users) > 0 { - values := make([][]int, 0, len(ids)) - for _, id := range ids { - for eid := range gu.users { - eid, serr := strconv.Atoi(eid) - if serr != nil { - err = rollback(tx, serr) - return - } - values = append(values, []int{id, eid}) + if nodes := gu.blocked; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: group.BlockedTable, + Columns: []string{group.BlockedColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: user.FieldID, + }, + }, + } + for k, _ := range nodes { + k, err := strconv.Atoi(k) + if err != nil { + return 0, err } + edge.Target.Nodes = append(edge.Target.Nodes, k) } - builder := builder.Insert(group.UsersTable). - Columns(group.UsersPrimaryKey[1], group.UsersPrimaryKey[0]) - for _, v := range values { - builder.Values(v[0], v[1]) + spec.Edges.Add = append(spec.Edges.Add, edge) + } + if nodes := gu.removedUsers; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: true, + Table: group.UsersTable, + Columns: group.UsersPrimaryKey, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: user.FieldID, + }, + }, } - query, args := builder.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) + for k, _ := range nodes { + k, err := strconv.Atoi(k) + if err != nil { + return 0, err + } + edge.Target.Nodes = append(edge.Target.Nodes, k) } + spec.Edges.Clear = append(spec.Edges.Clear, edge) + } + if nodes := gu.users; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: true, + Table: group.UsersTable, + Columns: group.UsersPrimaryKey, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: user.FieldID, + }, + }, + } + for k, _ := range nodes { + k, err := strconv.Atoi(k) + if err != nil { + return 0, err + } + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + spec.Edges.Add = append(spec.Edges.Add, edge) } if gu.clearedInfo { - query, args := builder.Update(group.InfoTable). - SetNull(group.InfoColumn). - Where(sql.InInts(groupinfo.FieldID, ids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: false, + Table: group.InfoTable, + Columns: []string{group.InfoColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: groupinfo.FieldID, + }, + }, } + spec.Edges.Clear = append(spec.Edges.Clear, edge) } - if len(gu.info) > 0 { - for eid := range gu.info { - eid, serr := strconv.Atoi(eid) - if serr != nil { - err = rollback(tx, serr) - return - } - query, args := builder.Update(group.InfoTable). - Set(group.InfoColumn, eid). - Where(sql.InInts(group.FieldID, ids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } + if nodes := gu.info; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: false, + Table: group.InfoTable, + Columns: []string{group.InfoColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: groupinfo.FieldID, + }, + }, } + for k, _ := range nodes { + k, err := strconv.Atoi(k) + if err != nil { + return 0, err + } + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + spec.Edges.Add = append(spec.Edges.Add, edge) } - if err = tx.Commit(); err != nil { + if n, err = sqlgraph.UpdateNodes(ctx, gu.driver, spec); err != nil { + if cerr, ok := isSQLConstraintError(err); ok { + err = cerr + } return 0, err } - return len(ids), nil + return n, nil } // GroupUpdateOne is the builder for updating a single Group entity. @@ -835,241 +866,299 @@ func (guo *GroupUpdateOne) ExecX(ctx context.Context) { } func (guo *GroupUpdateOne) sqlSave(ctx context.Context) (gr *Group, err error) { - var ( - builder = sql.Dialect(guo.driver.Dialect()) - selector = builder.Select(group.Columns...).From(builder.Table(group.Table)) - ) - group.ID(guo.id)(selector) - rows := &sql.Rows{} - query, args := selector.Query() - if err = guo.driver.Query(ctx, query, args, rows); err != nil { - return nil, err + spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: group.Table, + Columns: group.Columns, + ID: &sqlgraph.FieldSpec{ + Value: guo.id, + Type: field.TypeString, + Column: group.FieldID, + }, + }, } - defer rows.Close() - - var ids []int - for rows.Next() { - var id int - gr = &Group{config: guo.config} - if err := gr.FromRows(rows); err != nil { - return nil, fmt.Errorf("ent: failed scanning row into Group: %v", err) - } - id = gr.id() - ids = append(ids, id) - } - switch n := len(ids); { - case n == 0: - return nil, &ErrNotFound{fmt.Sprintf("Group with id: %v", guo.id)} - case n > 1: - return nil, fmt.Errorf("ent: more than one Group with the same id: %v", guo.id) - } - - tx, err := guo.driver.Tx(ctx) - if err != nil { - return nil, err - } - var ( - res sql.Result - updater = builder.Update(group.Table) - ) - updater = updater.Where(sql.InInts(group.FieldID, ids...)) if value := guo.active; value != nil { - updater.Set(group.FieldActive, *value) - gr.Active = *value + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeBool, + Value: *value, + Column: group.FieldActive, + }) } if value := guo.expire; value != nil { - updater.Set(group.FieldExpire, *value) - gr.Expire = *value + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeTime, + Value: *value, + Column: group.FieldExpire, + }) } if value := guo._type; value != nil { - updater.Set(group.FieldType, *value) - gr.Type = value + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: *value, + Column: group.FieldType, + }) } if guo.clear_type { - gr.Type = nil - updater.SetNull(group.FieldType) + spec.Fields.Clear = append(spec.Fields.Clear, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: group.FieldType, + }) } if value := guo.max_users; value != nil { - updater.Set(group.FieldMaxUsers, *value) - gr.MaxUsers = *value + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: *value, + Column: group.FieldMaxUsers, + }) } if value := guo.addmax_users; value != nil { - updater.Add(group.FieldMaxUsers, *value) - gr.MaxUsers += *value + spec.Fields.Add = append(spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: *value, + Column: group.FieldMaxUsers, + }) } if guo.clearmax_users { - var value int - gr.MaxUsers = value - updater.SetNull(group.FieldMaxUsers) + spec.Fields.Clear = append(spec.Fields.Clear, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: group.FieldMaxUsers, + }) } if value := guo.name; value != nil { - updater.Set(group.FieldName, *value) - gr.Name = *value + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: *value, + Column: group.FieldName, + }) } - if !updater.Empty() { - query, args := updater.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) + if nodes := guo.removedFiles; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: group.FilesTable, + Columns: []string{group.FilesColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: file.FieldID, + }, + }, } - } - if len(guo.removedFiles) > 0 { - eids := make([]int, len(guo.removedFiles)) - for eid := range guo.removedFiles { - eid, serr := strconv.Atoi(eid) - if serr != nil { - err = rollback(tx, serr) - return - } - eids = append(eids, eid) - } - query, args := builder.Update(group.FilesTable). - SetNull(group.FilesColumn). - Where(sql.InInts(group.FilesColumn, ids...)). - Where(sql.InInts(file.FieldID, eids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) - } - } - if len(guo.files) > 0 { - for _, id := range ids { - p := sql.P() - for eid := range guo.files { - eid, serr := strconv.Atoi(eid) - if serr != nil { - err = rollback(tx, serr) - return - } - p.Or().EQ(file.FieldID, eid) - } - query, args := builder.Update(group.FilesTable). - Set(group.FilesColumn, id). - Where(sql.And(p, sql.IsNull(group.FilesColumn))). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) - } - affected, err := res.RowsAffected() + for k, _ := range nodes { + k, err := strconv.Atoi(k) if err != nil { - return nil, rollback(tx, err) - } - if int(affected) < len(guo.files) { - return nil, rollback(tx, &ConstraintError{msg: fmt.Sprintf("one of \"files\" %v already connected to a different \"Group\"", keys(guo.files))}) + return nil, err } + edge.Target.Nodes = append(edge.Target.Nodes, k) } + spec.Edges.Clear = append(spec.Edges.Clear, edge) } - if len(guo.removedBlocked) > 0 { - eids := make([]int, len(guo.removedBlocked)) - for eid := range guo.removedBlocked { - eid, serr := strconv.Atoi(eid) - if serr != nil { - err = rollback(tx, serr) - return - } - eids = append(eids, eid) + if nodes := guo.files; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: group.FilesTable, + Columns: []string{group.FilesColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: file.FieldID, + }, + }, } - query, args := builder.Update(group.BlockedTable). - SetNull(group.BlockedColumn). - Where(sql.InInts(group.BlockedColumn, ids...)). - Where(sql.InInts(user.FieldID, eids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) - } - } - if len(guo.blocked) > 0 { - for _, id := range ids { - p := sql.P() - for eid := range guo.blocked { - eid, serr := strconv.Atoi(eid) - if serr != nil { - err = rollback(tx, serr) - return - } - p.Or().EQ(user.FieldID, eid) - } - query, args := builder.Update(group.BlockedTable). - Set(group.BlockedColumn, id). - Where(sql.And(p, sql.IsNull(group.BlockedColumn))). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) - } - affected, err := res.RowsAffected() + for k, _ := range nodes { + k, err := strconv.Atoi(k) if err != nil { - return nil, rollback(tx, err) - } - if int(affected) < len(guo.blocked) { - return nil, rollback(tx, &ConstraintError{msg: fmt.Sprintf("one of \"blocked\" %v already connected to a different \"Group\"", keys(guo.blocked))}) + return nil, err } + edge.Target.Nodes = append(edge.Target.Nodes, k) } + spec.Edges.Add = append(spec.Edges.Add, edge) } - if len(guo.removedUsers) > 0 { - eids := make([]int, len(guo.removedUsers)) - for eid := range guo.removedUsers { - eid, serr := strconv.Atoi(eid) - if serr != nil { - err = rollback(tx, serr) - return + if nodes := guo.removedBlocked; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: group.BlockedTable, + Columns: []string{group.BlockedColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: user.FieldID, + }, + }, + } + for k, _ := range nodes { + k, err := strconv.Atoi(k) + if err != nil { + return nil, err } - eids = append(eids, eid) - } - query, args := builder.Delete(group.UsersTable). - Where(sql.InInts(group.UsersPrimaryKey[1], ids...)). - Where(sql.InInts(group.UsersPrimaryKey[0], eids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) + edge.Target.Nodes = append(edge.Target.Nodes, k) } + spec.Edges.Clear = append(spec.Edges.Clear, edge) } - if len(guo.users) > 0 { - values := make([][]int, 0, len(ids)) - for _, id := range ids { - for eid := range guo.users { - eid, serr := strconv.Atoi(eid) - if serr != nil { - err = rollback(tx, serr) - return - } - values = append(values, []int{id, eid}) + if nodes := guo.blocked; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: group.BlockedTable, + Columns: []string{group.BlockedColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: user.FieldID, + }, + }, + } + for k, _ := range nodes { + k, err := strconv.Atoi(k) + if err != nil { + return nil, err } + edge.Target.Nodes = append(edge.Target.Nodes, k) } - builder := builder.Insert(group.UsersTable). - Columns(group.UsersPrimaryKey[1], group.UsersPrimaryKey[0]) - for _, v := range values { - builder.Values(v[0], v[1]) + spec.Edges.Add = append(spec.Edges.Add, edge) + } + if nodes := guo.removedUsers; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: true, + Table: group.UsersTable, + Columns: group.UsersPrimaryKey, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: user.FieldID, + }, + }, } - query, args := builder.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) + for k, _ := range nodes { + k, err := strconv.Atoi(k) + if err != nil { + return nil, err + } + edge.Target.Nodes = append(edge.Target.Nodes, k) } + spec.Edges.Clear = append(spec.Edges.Clear, edge) + } + if nodes := guo.users; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: true, + Table: group.UsersTable, + Columns: group.UsersPrimaryKey, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: user.FieldID, + }, + }, + } + for k, _ := range nodes { + k, err := strconv.Atoi(k) + if err != nil { + return nil, err + } + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + spec.Edges.Add = append(spec.Edges.Add, edge) } if guo.clearedInfo { - query, args := builder.Update(group.InfoTable). - SetNull(group.InfoColumn). - Where(sql.InInts(groupinfo.FieldID, ids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: false, + Table: group.InfoTable, + Columns: []string{group.InfoColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: groupinfo.FieldID, + }, + }, } + spec.Edges.Clear = append(spec.Edges.Clear, edge) } - if len(guo.info) > 0 { - for eid := range guo.info { - eid, serr := strconv.Atoi(eid) - if serr != nil { - err = rollback(tx, serr) - return - } - query, args := builder.Update(group.InfoTable). - Set(group.InfoColumn, eid). - Where(sql.InInts(group.FieldID, ids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) - } + if nodes := guo.info; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: false, + Table: group.InfoTable, + Columns: []string{group.InfoColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: groupinfo.FieldID, + }, + }, } + for k, _ := range nodes { + k, err := strconv.Atoi(k) + if err != nil { + return nil, err + } + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + spec.Edges.Add = append(spec.Edges.Add, edge) } - if err = tx.Commit(); err != nil { + gr = &Group{config: guo.config} + spec.ScanTypes = []interface{}{ + &sql.NullInt64{}, + &sql.NullBool{}, + &sql.NullTime{}, + &sql.NullString{}, + &sql.NullInt64{}, + &sql.NullString{}, + } + spec.Assign = func(values ...interface{}) error { + if m, n := len(values), len(spec.ScanTypes); m != n { + return fmt.Errorf("mismatch number of scan values: %d != %d", m, n) + } + value, ok := values[0].(*sql.NullInt64) + if !ok { + return fmt.Errorf("unexpected type %T for field id", value) + } + gr.ID = strconv.FormatInt(value.Int64, 10) + values = values[1:] + if value, ok := values[0].(*sql.NullBool); !ok { + return fmt.Errorf("unexpected type %T for field active", values[0]) + } else if value.Valid { + gr.Active = value.Bool + } + if value, ok := values[1].(*sql.NullTime); !ok { + return fmt.Errorf("unexpected type %T for field expire", values[1]) + } else if value.Valid { + gr.Expire = value.Time + } + if value, ok := values[2].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field type", values[2]) + } else if value.Valid { + gr.Type = new(string) + *gr.Type = value.String + } + if value, ok := values[3].(*sql.NullInt64); !ok { + return fmt.Errorf("unexpected type %T for field max_users", values[3]) + } else if value.Valid { + gr.MaxUsers = int(value.Int64) + } + if value, ok := values[4].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field name", values[4]) + } else if value.Valid { + gr.Name = value.String + } + return nil + } + if err = sqlgraph.UpdateNode(ctx, guo.driver, spec); err != nil { + if cerr, ok := isSQLConstraintError(err); ok { + err = cerr + } return nil, err } return gr, nil diff --git a/entc/integration/ent/groupinfo_update.go b/entc/integration/ent/groupinfo_update.go index e476a4947..31d91c187 100644 --- a/entc/integration/ent/groupinfo_update.go +++ b/entc/integration/ent/groupinfo_update.go @@ -12,9 +12,11 @@ import ( "strconv" "github.com/facebookincubator/ent/dialect/sql" + "github.com/facebookincubator/ent/dialect/sql/sqlgraph" "github.com/facebookincubator/ent/entc/integration/ent/group" "github.com/facebookincubator/ent/entc/integration/ent/groupinfo" "github.com/facebookincubator/ent/entc/integration/ent/predicate" + "github.com/facebookincubator/ent/schema/field" ) // GroupInfoUpdate is the builder for updating GroupInfo entities. @@ -133,106 +135,97 @@ func (giu *GroupInfoUpdate) ExecX(ctx context.Context) { } func (giu *GroupInfoUpdate) sqlSave(ctx context.Context) (n int, err error) { - var ( - builder = sql.Dialect(giu.driver.Dialect()) - selector = builder.Select(groupinfo.FieldID).From(builder.Table(groupinfo.Table)) - ) - for _, p := range giu.predicates { - p(selector) + spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: groupinfo.Table, + Columns: groupinfo.Columns, + ID: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: groupinfo.FieldID, + }, + }, } - rows := &sql.Rows{} - query, args := selector.Query() - if err = giu.driver.Query(ctx, query, args, rows); err != nil { - return 0, err - } - defer rows.Close() - - var ids []int - for rows.Next() { - var id int - if err := rows.Scan(&id); err != nil { - return 0, fmt.Errorf("ent: failed reading id: %v", err) + if ps := giu.predicates; len(ps) > 0 { + spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } } - ids = append(ids, id) } - if len(ids) == 0 { - return 0, nil - } - - tx, err := giu.driver.Tx(ctx) - if err != nil { - return 0, err - } - var ( - res sql.Result - updater = builder.Update(groupinfo.Table) - ) - updater = updater.Where(sql.InInts(groupinfo.FieldID, ids...)) if value := giu.desc; value != nil { - updater.Set(groupinfo.FieldDesc, *value) + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: *value, + Column: groupinfo.FieldDesc, + }) } if value := giu.max_users; value != nil { - updater.Set(groupinfo.FieldMaxUsers, *value) + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: *value, + Column: groupinfo.FieldMaxUsers, + }) } if value := giu.addmax_users; value != nil { - updater.Add(groupinfo.FieldMaxUsers, *value) + spec.Fields.Add = append(spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: *value, + Column: groupinfo.FieldMaxUsers, + }) } - if !updater.Empty() { - query, args := updater.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) + if nodes := giu.removedGroups; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: true, + Table: groupinfo.GroupsTable, + Columns: []string{groupinfo.GroupsColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: group.FieldID, + }, + }, } - } - if len(giu.removedGroups) > 0 { - eids := make([]int, len(giu.removedGroups)) - for eid := range giu.removedGroups { - eid, serr := strconv.Atoi(eid) - if serr != nil { - err = rollback(tx, serr) - return - } - eids = append(eids, eid) - } - query, args := builder.Update(groupinfo.GroupsTable). - SetNull(groupinfo.GroupsColumn). - Where(sql.InInts(groupinfo.GroupsColumn, ids...)). - Where(sql.InInts(group.FieldID, eids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } - } - if len(giu.groups) > 0 { - for _, id := range ids { - p := sql.P() - for eid := range giu.groups { - eid, serr := strconv.Atoi(eid) - if serr != nil { - err = rollback(tx, serr) - return - } - p.Or().EQ(group.FieldID, eid) - } - query, args := builder.Update(groupinfo.GroupsTable). - Set(groupinfo.GroupsColumn, id). - Where(sql.And(p, sql.IsNull(groupinfo.GroupsColumn))). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } - affected, err := res.RowsAffected() + for k, _ := range nodes { + k, err := strconv.Atoi(k) if err != nil { - return 0, rollback(tx, err) - } - if int(affected) < len(giu.groups) { - return 0, rollback(tx, &ConstraintError{msg: fmt.Sprintf("one of \"groups\" %v already connected to a different \"GroupInfo\"", keys(giu.groups))}) + return 0, err } + edge.Target.Nodes = append(edge.Target.Nodes, k) } + spec.Edges.Clear = append(spec.Edges.Clear, edge) } - if err = tx.Commit(); err != nil { + if nodes := giu.groups; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: true, + Table: groupinfo.GroupsTable, + Columns: []string{groupinfo.GroupsColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: group.FieldID, + }, + }, + } + for k, _ := range nodes { + k, err := strconv.Atoi(k) + if err != nil { + return 0, err + } + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + spec.Edges.Add = append(spec.Edges.Add, edge) + } + if n, err = sqlgraph.UpdateNodes(ctx, giu.driver, spec); err != nil { + if cerr, ok := isSQLConstraintError(err); ok { + err = cerr + } return 0, err } - return len(ids), nil + return n, nil } // GroupInfoUpdateOne is the builder for updating a single GroupInfo entity. @@ -345,109 +338,116 @@ func (giuo *GroupInfoUpdateOne) ExecX(ctx context.Context) { } func (giuo *GroupInfoUpdateOne) sqlSave(ctx context.Context) (gi *GroupInfo, err error) { - var ( - builder = sql.Dialect(giuo.driver.Dialect()) - selector = builder.Select(groupinfo.Columns...).From(builder.Table(groupinfo.Table)) - ) - groupinfo.ID(giuo.id)(selector) - rows := &sql.Rows{} - query, args := selector.Query() - if err = giuo.driver.Query(ctx, query, args, rows); err != nil { - return nil, err + spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: groupinfo.Table, + Columns: groupinfo.Columns, + ID: &sqlgraph.FieldSpec{ + Value: giuo.id, + Type: field.TypeString, + Column: groupinfo.FieldID, + }, + }, } - defer rows.Close() - - var ids []int - for rows.Next() { - var id int - gi = &GroupInfo{config: giuo.config} - if err := gi.FromRows(rows); err != nil { - return nil, fmt.Errorf("ent: failed scanning row into GroupInfo: %v", err) - } - id = gi.id() - ids = append(ids, id) - } - switch n := len(ids); { - case n == 0: - return nil, &ErrNotFound{fmt.Sprintf("GroupInfo with id: %v", giuo.id)} - case n > 1: - return nil, fmt.Errorf("ent: more than one GroupInfo with the same id: %v", giuo.id) - } - - tx, err := giuo.driver.Tx(ctx) - if err != nil { - return nil, err - } - var ( - res sql.Result - updater = builder.Update(groupinfo.Table) - ) - updater = updater.Where(sql.InInts(groupinfo.FieldID, ids...)) if value := giuo.desc; value != nil { - updater.Set(groupinfo.FieldDesc, *value) - gi.Desc = *value + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: *value, + Column: groupinfo.FieldDesc, + }) } if value := giuo.max_users; value != nil { - updater.Set(groupinfo.FieldMaxUsers, *value) - gi.MaxUsers = *value + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: *value, + Column: groupinfo.FieldMaxUsers, + }) } if value := giuo.addmax_users; value != nil { - updater.Add(groupinfo.FieldMaxUsers, *value) - gi.MaxUsers += *value + spec.Fields.Add = append(spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: *value, + Column: groupinfo.FieldMaxUsers, + }) } - if !updater.Empty() { - query, args := updater.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) + if nodes := giuo.removedGroups; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: true, + Table: groupinfo.GroupsTable, + Columns: []string{groupinfo.GroupsColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: group.FieldID, + }, + }, } - } - if len(giuo.removedGroups) > 0 { - eids := make([]int, len(giuo.removedGroups)) - for eid := range giuo.removedGroups { - eid, serr := strconv.Atoi(eid) - if serr != nil { - err = rollback(tx, serr) - return - } - eids = append(eids, eid) - } - query, args := builder.Update(groupinfo.GroupsTable). - SetNull(groupinfo.GroupsColumn). - Where(sql.InInts(groupinfo.GroupsColumn, ids...)). - Where(sql.InInts(group.FieldID, eids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) - } - } - if len(giuo.groups) > 0 { - for _, id := range ids { - p := sql.P() - for eid := range giuo.groups { - eid, serr := strconv.Atoi(eid) - if serr != nil { - err = rollback(tx, serr) - return - } - p.Or().EQ(group.FieldID, eid) - } - query, args := builder.Update(groupinfo.GroupsTable). - Set(groupinfo.GroupsColumn, id). - Where(sql.And(p, sql.IsNull(groupinfo.GroupsColumn))). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) - } - affected, err := res.RowsAffected() + for k, _ := range nodes { + k, err := strconv.Atoi(k) if err != nil { - return nil, rollback(tx, err) - } - if int(affected) < len(giuo.groups) { - return nil, rollback(tx, &ConstraintError{msg: fmt.Sprintf("one of \"groups\" %v already connected to a different \"GroupInfo\"", keys(giuo.groups))}) + return nil, err } + edge.Target.Nodes = append(edge.Target.Nodes, k) } + spec.Edges.Clear = append(spec.Edges.Clear, edge) } - if err = tx.Commit(); err != nil { + if nodes := giuo.groups; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: true, + Table: groupinfo.GroupsTable, + Columns: []string{groupinfo.GroupsColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: group.FieldID, + }, + }, + } + for k, _ := range nodes { + k, err := strconv.Atoi(k) + if err != nil { + return nil, err + } + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + spec.Edges.Add = append(spec.Edges.Add, edge) + } + gi = &GroupInfo{config: giuo.config} + spec.ScanTypes = []interface{}{ + &sql.NullInt64{}, + &sql.NullString{}, + &sql.NullInt64{}, + } + spec.Assign = func(values ...interface{}) error { + if m, n := len(values), len(spec.ScanTypes); m != n { + return fmt.Errorf("mismatch number of scan values: %d != %d", m, n) + } + value, ok := values[0].(*sql.NullInt64) + if !ok { + return fmt.Errorf("unexpected type %T for field id", value) + } + gi.ID = strconv.FormatInt(value.Int64, 10) + values = values[1:] + if value, ok := values[0].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field desc", values[0]) + } else if value.Valid { + gi.Desc = value.String + } + if value, ok := values[1].(*sql.NullInt64); !ok { + return fmt.Errorf("unexpected type %T for field max_users", values[1]) + } else if value.Valid { + gi.MaxUsers = int(value.Int64) + } + return nil + } + if err = sqlgraph.UpdateNode(ctx, giuo.driver, spec); err != nil { + if cerr, ok := isSQLConstraintError(err); ok { + err = cerr + } return nil, err } return gi, nil diff --git a/entc/integration/ent/item_update.go b/entc/integration/ent/item_update.go index b26d29510..8fcf56a60 100644 --- a/entc/integration/ent/item_update.go +++ b/entc/integration/ent/item_update.go @@ -9,10 +9,13 @@ package ent import ( "context" "fmt" + "strconv" "github.com/facebookincubator/ent/dialect/sql" + "github.com/facebookincubator/ent/dialect/sql/sqlgraph" "github.com/facebookincubator/ent/entc/integration/ent/item" "github.com/facebookincubator/ent/entc/integration/ent/predicate" + "github.com/facebookincubator/ent/schema/field" ) // ItemUpdate is the builder for updating Item entities. @@ -55,40 +58,30 @@ func (iu *ItemUpdate) ExecX(ctx context.Context) { } func (iu *ItemUpdate) sqlSave(ctx context.Context) (n int, err error) { - var ( - builder = sql.Dialect(iu.driver.Dialect()) - selector = builder.Select(item.FieldID).From(builder.Table(item.Table)) - ) - for _, p := range iu.predicates { - p(selector) + spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: item.Table, + Columns: item.Columns, + ID: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: item.FieldID, + }, + }, } - rows := &sql.Rows{} - query, args := selector.Query() - if err = iu.driver.Query(ctx, query, args, rows); err != nil { - return 0, err - } - defer rows.Close() - - var ids []int - for rows.Next() { - var id int - if err := rows.Scan(&id); err != nil { - return 0, fmt.Errorf("ent: failed reading id: %v", err) + if ps := iu.predicates; len(ps) > 0 { + spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } } - ids = append(ids, id) } - if len(ids) == 0 { - return 0, nil - } - - tx, err := iu.driver.Tx(ctx) - if err != nil { + if n, err = sqlgraph.UpdateNodes(ctx, iu.driver, spec); err != nil { + if cerr, ok := isSQLConstraintError(err); ok { + err = cerr + } return 0, err } - if err = tx.Commit(); err != nil { - return 0, err - } - return len(ids), nil + return n, nil } // ItemUpdateOne is the builder for updating a single Item entity. @@ -125,40 +118,37 @@ func (iuo *ItemUpdateOne) ExecX(ctx context.Context) { } func (iuo *ItemUpdateOne) sqlSave(ctx context.Context) (i *Item, err error) { - var ( - builder = sql.Dialect(iuo.driver.Dialect()) - selector = builder.Select(item.Columns...).From(builder.Table(item.Table)) - ) - item.ID(iuo.id)(selector) - rows := &sql.Rows{} - query, args := selector.Query() - if err = iuo.driver.Query(ctx, query, args, rows); err != nil { - return nil, err + spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: item.Table, + Columns: item.Columns, + ID: &sqlgraph.FieldSpec{ + Value: iuo.id, + Type: field.TypeString, + Column: item.FieldID, + }, + }, } - defer rows.Close() - - var ids []int - for rows.Next() { - var id int - i = &Item{config: iuo.config} - if err := i.FromRows(rows); err != nil { - return nil, fmt.Errorf("ent: failed scanning row into Item: %v", err) + i = &Item{config: iuo.config} + spec.ScanTypes = []interface{}{ + &sql.NullInt64{}, + } + spec.Assign = func(values ...interface{}) error { + if m, n := len(values), len(spec.ScanTypes); m != n { + return fmt.Errorf("mismatch number of scan values: %d != %d", m, n) } - id = i.id() - ids = append(ids, id) + value, ok := values[0].(*sql.NullInt64) + if !ok { + return fmt.Errorf("unexpected type %T for field id", value) + } + i.ID = strconv.FormatInt(value.Int64, 10) + values = values[1:] + return nil } - switch n := len(ids); { - case n == 0: - return nil, &ErrNotFound{fmt.Sprintf("Item with id: %v", iuo.id)} - case n > 1: - return nil, fmt.Errorf("ent: more than one Item with the same id: %v", iuo.id) - } - - tx, err := iuo.driver.Tx(ctx) - if err != nil { - return nil, err - } - if err = tx.Commit(); err != nil { + if err = sqlgraph.UpdateNode(ctx, iuo.driver, spec); err != nil { + if cerr, ok := isSQLConstraintError(err); ok { + err = cerr + } return nil, err } return i, nil diff --git a/entc/integration/ent/node_update.go b/entc/integration/ent/node_update.go index 5a980962b..4ddb188cb 100644 --- a/entc/integration/ent/node_update.go +++ b/entc/integration/ent/node_update.go @@ -13,8 +13,10 @@ import ( "strconv" "github.com/facebookincubator/ent/dialect/sql" + "github.com/facebookincubator/ent/dialect/sql/sqlgraph" "github.com/facebookincubator/ent/entc/integration/ent/node" "github.com/facebookincubator/ent/entc/integration/ent/predicate" + "github.com/facebookincubator/ent/schema/field" ) // NodeUpdate is the builder for updating Node entities. @@ -158,122 +160,128 @@ func (nu *NodeUpdate) ExecX(ctx context.Context) { } func (nu *NodeUpdate) sqlSave(ctx context.Context) (n int, err error) { - var ( - builder = sql.Dialect(nu.driver.Dialect()) - selector = builder.Select(node.FieldID).From(builder.Table(node.Table)) - ) - for _, p := range nu.predicates { - p(selector) + spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: node.Table, + Columns: node.Columns, + ID: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: node.FieldID, + }, + }, } - rows := &sql.Rows{} - query, args := selector.Query() - if err = nu.driver.Query(ctx, query, args, rows); err != nil { - return 0, err - } - defer rows.Close() - - var ids []int - for rows.Next() { - var id int - if err := rows.Scan(&id); err != nil { - return 0, fmt.Errorf("ent: failed reading id: %v", err) + if ps := nu.predicates; len(ps) > 0 { + spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } } - ids = append(ids, id) } - if len(ids) == 0 { - return 0, nil - } - - tx, err := nu.driver.Tx(ctx) - if err != nil { - return 0, err - } - var ( - res sql.Result - updater = builder.Update(node.Table) - ) - updater = updater.Where(sql.InInts(node.FieldID, ids...)) if value := nu.value; value != nil { - updater.Set(node.FieldValue, *value) + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: *value, + Column: node.FieldValue, + }) } if value := nu.addvalue; value != nil { - updater.Add(node.FieldValue, *value) + spec.Fields.Add = append(spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: *value, + Column: node.FieldValue, + }) } if nu.clearvalue { - updater.SetNull(node.FieldValue) - } - if !updater.Empty() { - query, args := updater.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } + spec.Fields.Clear = append(spec.Fields.Clear, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: node.FieldValue, + }) } if nu.clearedPrev { - query, args := builder.Update(node.PrevTable). - SetNull(node.PrevColumn). - Where(sql.InInts(node.FieldID, ids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2O, + Inverse: true, + Table: node.PrevTable, + Columns: []string{node.PrevColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: node.FieldID, + }, + }, } + spec.Edges.Clear = append(spec.Edges.Clear, edge) } - if len(nu.prev) > 0 { - for _, id := range ids { - eid, serr := strconv.Atoi(keys(nu.prev)[0]) - if serr != nil { - return 0, rollback(tx, err) - } - query, args := builder.Update(node.PrevTable). - Set(node.PrevColumn, eid). - Where(sql.EQ(node.FieldID, id).And().IsNull(node.PrevColumn)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } - affected, err := res.RowsAffected() - if err != nil { - return 0, rollback(tx, err) - } - if int(affected) < len(nu.prev) { - return 0, rollback(tx, &ConstraintError{msg: fmt.Sprintf("one of \"prev\" %v already connected to a different \"Node\"", keys(nu.prev))}) - } + if nodes := nu.prev; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2O, + Inverse: true, + Table: node.PrevTable, + Columns: []string{node.PrevColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: node.FieldID, + }, + }, } + for k, _ := range nodes { + k, err := strconv.Atoi(k) + if err != nil { + return 0, err + } + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + spec.Edges.Add = append(spec.Edges.Add, edge) } if nu.clearedNext { - query, args := builder.Update(node.NextTable). - SetNull(node.NextColumn). - Where(sql.InInts(node.FieldID, ids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2O, + Inverse: false, + Table: node.NextTable, + Columns: []string{node.NextColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: node.FieldID, + }, + }, } + spec.Edges.Clear = append(spec.Edges.Clear, edge) } - if len(nu.next) > 0 { - for _, id := range ids { - eid, serr := strconv.Atoi(keys(nu.next)[0]) - if serr != nil { - return 0, rollback(tx, err) - } - query, args := builder.Update(node.NextTable). - Set(node.NextColumn, id). - Where(sql.EQ(node.FieldID, eid).And().IsNull(node.NextColumn)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } - affected, err := res.RowsAffected() + if nodes := nu.next; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2O, + Inverse: false, + Table: node.NextTable, + Columns: []string{node.NextColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: node.FieldID, + }, + }, + } + for k, _ := range nodes { + k, err := strconv.Atoi(k) if err != nil { - return 0, rollback(tx, err) - } - if int(affected) < len(nu.next) { - return 0, rollback(tx, &ConstraintError{msg: fmt.Sprintf("one of \"next\" %v already connected to a different \"Node\"", keys(nu.next))}) + return 0, err } + edge.Target.Nodes = append(edge.Target.Nodes, k) } + spec.Edges.Add = append(spec.Edges.Add, edge) } - if err = tx.Commit(); err != nil { + if n, err = sqlgraph.UpdateNodes(ctx, nu.driver, spec); err != nil { + if cerr, ok := isSQLConstraintError(err); ok { + err = cerr + } return 0, err } - return len(ids), nil + return n, nil } // NodeUpdateOne is the builder for updating a single Node entity. @@ -411,126 +419,141 @@ func (nuo *NodeUpdateOne) ExecX(ctx context.Context) { } func (nuo *NodeUpdateOne) sqlSave(ctx context.Context) (n *Node, err error) { - var ( - builder = sql.Dialect(nuo.driver.Dialect()) - selector = builder.Select(node.Columns...).From(builder.Table(node.Table)) - ) - node.ID(nuo.id)(selector) - rows := &sql.Rows{} - query, args := selector.Query() - if err = nuo.driver.Query(ctx, query, args, rows); err != nil { - return nil, err + spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: node.Table, + Columns: node.Columns, + ID: &sqlgraph.FieldSpec{ + Value: nuo.id, + Type: field.TypeString, + Column: node.FieldID, + }, + }, } - defer rows.Close() - - var ids []int - for rows.Next() { - var id int - n = &Node{config: nuo.config} - if err := n.FromRows(rows); err != nil { - return nil, fmt.Errorf("ent: failed scanning row into Node: %v", err) - } - id = n.id() - ids = append(ids, id) - } - switch n := len(ids); { - case n == 0: - return nil, &ErrNotFound{fmt.Sprintf("Node with id: %v", nuo.id)} - case n > 1: - return nil, fmt.Errorf("ent: more than one Node with the same id: %v", nuo.id) - } - - tx, err := nuo.driver.Tx(ctx) - if err != nil { - return nil, err - } - var ( - res sql.Result - updater = builder.Update(node.Table) - ) - updater = updater.Where(sql.InInts(node.FieldID, ids...)) if value := nuo.value; value != nil { - updater.Set(node.FieldValue, *value) - n.Value = *value + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: *value, + Column: node.FieldValue, + }) } if value := nuo.addvalue; value != nil { - updater.Add(node.FieldValue, *value) - n.Value += *value + spec.Fields.Add = append(spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: *value, + Column: node.FieldValue, + }) } if nuo.clearvalue { - var value int - n.Value = value - updater.SetNull(node.FieldValue) - } - if !updater.Empty() { - query, args := updater.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) - } + spec.Fields.Clear = append(spec.Fields.Clear, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: node.FieldValue, + }) } if nuo.clearedPrev { - query, args := builder.Update(node.PrevTable). - SetNull(node.PrevColumn). - Where(sql.InInts(node.FieldID, ids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2O, + Inverse: true, + Table: node.PrevTable, + Columns: []string{node.PrevColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: node.FieldID, + }, + }, } + spec.Edges.Clear = append(spec.Edges.Clear, edge) } - if len(nuo.prev) > 0 { - for _, id := range ids { - eid, serr := strconv.Atoi(keys(nuo.prev)[0]) - if serr != nil { - return nil, rollback(tx, err) - } - query, args := builder.Update(node.PrevTable). - Set(node.PrevColumn, eid). - Where(sql.EQ(node.FieldID, id).And().IsNull(node.PrevColumn)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) - } - affected, err := res.RowsAffected() - if err != nil { - return nil, rollback(tx, err) - } - if int(affected) < len(nuo.prev) { - return nil, rollback(tx, &ConstraintError{msg: fmt.Sprintf("one of \"prev\" %v already connected to a different \"Node\"", keys(nuo.prev))}) - } + if nodes := nuo.prev; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2O, + Inverse: true, + Table: node.PrevTable, + Columns: []string{node.PrevColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: node.FieldID, + }, + }, } + for k, _ := range nodes { + k, err := strconv.Atoi(k) + if err != nil { + return nil, err + } + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + spec.Edges.Add = append(spec.Edges.Add, edge) } if nuo.clearedNext { - query, args := builder.Update(node.NextTable). - SetNull(node.NextColumn). - Where(sql.InInts(node.FieldID, ids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2O, + Inverse: false, + Table: node.NextTable, + Columns: []string{node.NextColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: node.FieldID, + }, + }, } + spec.Edges.Clear = append(spec.Edges.Clear, edge) } - if len(nuo.next) > 0 { - for _, id := range ids { - eid, serr := strconv.Atoi(keys(nuo.next)[0]) - if serr != nil { - return nil, rollback(tx, err) - } - query, args := builder.Update(node.NextTable). - Set(node.NextColumn, id). - Where(sql.EQ(node.FieldID, eid).And().IsNull(node.NextColumn)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) - } - affected, err := res.RowsAffected() + if nodes := nuo.next; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2O, + Inverse: false, + Table: node.NextTable, + Columns: []string{node.NextColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: node.FieldID, + }, + }, + } + for k, _ := range nodes { + k, err := strconv.Atoi(k) if err != nil { - return nil, rollback(tx, err) - } - if int(affected) < len(nuo.next) { - return nil, rollback(tx, &ConstraintError{msg: fmt.Sprintf("one of \"next\" %v already connected to a different \"Node\"", keys(nuo.next))}) + return nil, err } + edge.Target.Nodes = append(edge.Target.Nodes, k) } + spec.Edges.Add = append(spec.Edges.Add, edge) } - if err = tx.Commit(); err != nil { + n = &Node{config: nuo.config} + spec.ScanTypes = []interface{}{ + &sql.NullInt64{}, + &sql.NullInt64{}, + } + spec.Assign = func(values ...interface{}) error { + if m, n := len(values), len(spec.ScanTypes); m != n { + return fmt.Errorf("mismatch number of scan values: %d != %d", m, n) + } + value, ok := values[0].(*sql.NullInt64) + if !ok { + return fmt.Errorf("unexpected type %T for field id", value) + } + n.ID = strconv.FormatInt(value.Int64, 10) + values = values[1:] + if value, ok := values[0].(*sql.NullInt64); !ok { + return fmt.Errorf("unexpected type %T for field value", values[0]) + } else if value.Valid { + n.Value = int(value.Int64) + } + return nil + } + if err = sqlgraph.UpdateNode(ctx, nuo.driver, spec); err != nil { + if cerr, ok := isSQLConstraintError(err); ok { + err = cerr + } return nil, err } return n, nil diff --git a/entc/integration/ent/pet_update.go b/entc/integration/ent/pet_update.go index 6a1f42e91..e44ff51e7 100644 --- a/entc/integration/ent/pet_update.go +++ b/entc/integration/ent/pet_update.go @@ -13,9 +13,11 @@ import ( "strconv" "github.com/facebookincubator/ent/dialect/sql" + "github.com/facebookincubator/ent/dialect/sql/sqlgraph" "github.com/facebookincubator/ent/entc/integration/ent/pet" "github.com/facebookincubator/ent/entc/integration/ent/predicate" "github.com/facebookincubator/ent/entc/integration/ent/user" + "github.com/facebookincubator/ent/schema/field" ) // PetUpdate is the builder for updating Pet entities. @@ -131,110 +133,115 @@ func (pu *PetUpdate) ExecX(ctx context.Context) { } func (pu *PetUpdate) sqlSave(ctx context.Context) (n int, err error) { - var ( - builder = sql.Dialect(pu.driver.Dialect()) - selector = builder.Select(pet.FieldID).From(builder.Table(pet.Table)) - ) - for _, p := range pu.predicates { - p(selector) + spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: pet.Table, + Columns: pet.Columns, + ID: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: pet.FieldID, + }, + }, } - rows := &sql.Rows{} - query, args := selector.Query() - if err = pu.driver.Query(ctx, query, args, rows); err != nil { - return 0, err - } - defer rows.Close() - - var ids []int - for rows.Next() { - var id int - if err := rows.Scan(&id); err != nil { - return 0, fmt.Errorf("ent: failed reading id: %v", err) + if ps := pu.predicates; len(ps) > 0 { + spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } } - ids = append(ids, id) } - if len(ids) == 0 { - return 0, nil - } - - tx, err := pu.driver.Tx(ctx) - if err != nil { - return 0, err - } - var ( - res sql.Result - updater = builder.Update(pet.Table) - ) - updater = updater.Where(sql.InInts(pet.FieldID, ids...)) if value := pu.name; value != nil { - updater.Set(pet.FieldName, *value) - } - if !updater.Empty() { - query, args := updater.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: *value, + Column: pet.FieldName, + }) } if pu.clearedTeam { - query, args := builder.Update(pet.TeamTable). - SetNull(pet.TeamColumn). - Where(sql.InInts(user.FieldID, ids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2O, + Inverse: true, + Table: pet.TeamTable, + Columns: []string{pet.TeamColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: user.FieldID, + }, + }, } + spec.Edges.Clear = append(spec.Edges.Clear, edge) } - if len(pu.team) > 0 { - for _, id := range ids { - eid, serr := strconv.Atoi(keys(pu.team)[0]) - if serr != nil { - return 0, rollback(tx, err) - } - query, args := builder.Update(pet.TeamTable). - Set(pet.TeamColumn, eid). - Where(sql.EQ(pet.FieldID, id).And().IsNull(pet.TeamColumn)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } - affected, err := res.RowsAffected() - if err != nil { - return 0, rollback(tx, err) - } - if int(affected) < len(pu.team) { - return 0, rollback(tx, &ConstraintError{msg: fmt.Sprintf("one of \"team\" %v already connected to a different \"Pet\"", keys(pu.team))}) - } + if nodes := pu.team; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2O, + Inverse: true, + Table: pet.TeamTable, + Columns: []string{pet.TeamColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: user.FieldID, + }, + }, } + for k, _ := range nodes { + k, err := strconv.Atoi(k) + if err != nil { + return 0, err + } + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + spec.Edges.Add = append(spec.Edges.Add, edge) } if pu.clearedOwner { - query, args := builder.Update(pet.OwnerTable). - SetNull(pet.OwnerColumn). - Where(sql.InInts(user.FieldID, ids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: pet.OwnerTable, + Columns: []string{pet.OwnerColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: user.FieldID, + }, + }, } + spec.Edges.Clear = append(spec.Edges.Clear, edge) } - if len(pu.owner) > 0 { - for eid := range pu.owner { - eid, serr := strconv.Atoi(eid) - if serr != nil { - err = rollback(tx, serr) - return - } - query, args := builder.Update(pet.OwnerTable). - Set(pet.OwnerColumn, eid). - Where(sql.InInts(pet.FieldID, ids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } + if nodes := pu.owner; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: pet.OwnerTable, + Columns: []string{pet.OwnerColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: user.FieldID, + }, + }, } + for k, _ := range nodes { + k, err := strconv.Atoi(k) + if err != nil { + return 0, err + } + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + spec.Edges.Add = append(spec.Edges.Add, edge) } - if err = tx.Commit(); err != nil { + if n, err = sqlgraph.UpdateNodes(ctx, pu.driver, spec); err != nil { + if cerr, ok := isSQLConstraintError(err); ok { + err = cerr + } return 0, err } - return len(ids), nil + return n, nil } // PetUpdateOne is the builder for updating a single Pet entity. @@ -344,111 +351,128 @@ func (puo *PetUpdateOne) ExecX(ctx context.Context) { } func (puo *PetUpdateOne) sqlSave(ctx context.Context) (pe *Pet, err error) { - var ( - builder = sql.Dialect(puo.driver.Dialect()) - selector = builder.Select(pet.Columns...).From(builder.Table(pet.Table)) - ) - pet.ID(puo.id)(selector) - rows := &sql.Rows{} - query, args := selector.Query() - if err = puo.driver.Query(ctx, query, args, rows); err != nil { - return nil, err + spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: pet.Table, + Columns: pet.Columns, + ID: &sqlgraph.FieldSpec{ + Value: puo.id, + Type: field.TypeString, + Column: pet.FieldID, + }, + }, } - defer rows.Close() - - var ids []int - for rows.Next() { - var id int - pe = &Pet{config: puo.config} - if err := pe.FromRows(rows); err != nil { - return nil, fmt.Errorf("ent: failed scanning row into Pet: %v", err) - } - id = pe.id() - ids = append(ids, id) - } - switch n := len(ids); { - case n == 0: - return nil, &ErrNotFound{fmt.Sprintf("Pet with id: %v", puo.id)} - case n > 1: - return nil, fmt.Errorf("ent: more than one Pet with the same id: %v", puo.id) - } - - tx, err := puo.driver.Tx(ctx) - if err != nil { - return nil, err - } - var ( - res sql.Result - updater = builder.Update(pet.Table) - ) - updater = updater.Where(sql.InInts(pet.FieldID, ids...)) if value := puo.name; value != nil { - updater.Set(pet.FieldName, *value) - pe.Name = *value - } - if !updater.Empty() { - query, args := updater.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) - } + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: *value, + Column: pet.FieldName, + }) } if puo.clearedTeam { - query, args := builder.Update(pet.TeamTable). - SetNull(pet.TeamColumn). - Where(sql.InInts(user.FieldID, ids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2O, + Inverse: true, + Table: pet.TeamTable, + Columns: []string{pet.TeamColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: user.FieldID, + }, + }, } + spec.Edges.Clear = append(spec.Edges.Clear, edge) } - if len(puo.team) > 0 { - for _, id := range ids { - eid, serr := strconv.Atoi(keys(puo.team)[0]) - if serr != nil { - return nil, rollback(tx, err) - } - query, args := builder.Update(pet.TeamTable). - Set(pet.TeamColumn, eid). - Where(sql.EQ(pet.FieldID, id).And().IsNull(pet.TeamColumn)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) - } - affected, err := res.RowsAffected() - if err != nil { - return nil, rollback(tx, err) - } - if int(affected) < len(puo.team) { - return nil, rollback(tx, &ConstraintError{msg: fmt.Sprintf("one of \"team\" %v already connected to a different \"Pet\"", keys(puo.team))}) - } + if nodes := puo.team; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2O, + Inverse: true, + Table: pet.TeamTable, + Columns: []string{pet.TeamColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: user.FieldID, + }, + }, } + for k, _ := range nodes { + k, err := strconv.Atoi(k) + if err != nil { + return nil, err + } + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + spec.Edges.Add = append(spec.Edges.Add, edge) } if puo.clearedOwner { - query, args := builder.Update(pet.OwnerTable). - SetNull(pet.OwnerColumn). - Where(sql.InInts(user.FieldID, ids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: pet.OwnerTable, + Columns: []string{pet.OwnerColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: user.FieldID, + }, + }, } + spec.Edges.Clear = append(spec.Edges.Clear, edge) } - if len(puo.owner) > 0 { - for eid := range puo.owner { - eid, serr := strconv.Atoi(eid) - if serr != nil { - err = rollback(tx, serr) - return - } - query, args := builder.Update(pet.OwnerTable). - Set(pet.OwnerColumn, eid). - Where(sql.InInts(pet.FieldID, ids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) - } + if nodes := puo.owner; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: pet.OwnerTable, + Columns: []string{pet.OwnerColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: user.FieldID, + }, + }, } + for k, _ := range nodes { + k, err := strconv.Atoi(k) + if err != nil { + return nil, err + } + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + spec.Edges.Add = append(spec.Edges.Add, edge) } - if err = tx.Commit(); err != nil { + pe = &Pet{config: puo.config} + spec.ScanTypes = []interface{}{ + &sql.NullInt64{}, + &sql.NullString{}, + } + spec.Assign = func(values ...interface{}) error { + if m, n := len(values), len(spec.ScanTypes); m != n { + return fmt.Errorf("mismatch number of scan values: %d != %d", m, n) + } + value, ok := values[0].(*sql.NullInt64) + if !ok { + return fmt.Errorf("unexpected type %T for field id", value) + } + pe.ID = strconv.FormatInt(value.Int64, 10) + values = values[1:] + if value, ok := values[0].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field name", values[0]) + } else if value.Valid { + pe.Name = value.String + } + return nil + } + if err = sqlgraph.UpdateNode(ctx, puo.driver, spec); err != nil { + if cerr, ok := isSQLConstraintError(err); ok { + err = cerr + } return nil, err } return pe, nil diff --git a/entc/integration/ent/user_update.go b/entc/integration/ent/user_update.go index 0de506b06..22c0ac27c 100644 --- a/entc/integration/ent/user_update.go +++ b/entc/integration/ent/user_update.go @@ -13,11 +13,14 @@ import ( "strconv" "github.com/facebookincubator/ent/dialect/sql" + "github.com/facebookincubator/ent/dialect/sql/sqlgraph" "github.com/facebookincubator/ent/entc/integration/ent/card" "github.com/facebookincubator/ent/entc/integration/ent/file" + "github.com/facebookincubator/ent/entc/integration/ent/group" "github.com/facebookincubator/ent/entc/integration/ent/pet" "github.com/facebookincubator/ent/entc/integration/ent/predicate" "github.com/facebookincubator/ent/entc/integration/ent/user" + "github.com/facebookincubator/ent/schema/field" ) // UserUpdate is the builder for updating User entities. @@ -596,520 +599,575 @@ func (uu *UserUpdate) ExecX(ctx context.Context) { } func (uu *UserUpdate) sqlSave(ctx context.Context) (n int, err error) { - var ( - builder = sql.Dialect(uu.driver.Dialect()) - selector = builder.Select(user.FieldID).From(builder.Table(user.Table)) - ) - for _, p := range uu.predicates { - p(selector) + spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: user.Table, + Columns: user.Columns, + ID: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: user.FieldID, + }, + }, } - rows := &sql.Rows{} - query, args := selector.Query() - if err = uu.driver.Query(ctx, query, args, rows); err != nil { - return 0, err - } - defer rows.Close() - - var ids []int - for rows.Next() { - var id int - if err := rows.Scan(&id); err != nil { - return 0, fmt.Errorf("ent: failed reading id: %v", err) + if ps := uu.predicates; len(ps) > 0 { + spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } } - ids = append(ids, id) } - if len(ids) == 0 { - return 0, nil - } - - tx, err := uu.driver.Tx(ctx) - if err != nil { - return 0, err - } - var ( - res sql.Result - updater = builder.Update(user.Table) - ) - updater = updater.Where(sql.InInts(user.FieldID, ids...)) if value := uu.age; value != nil { - updater.Set(user.FieldAge, *value) + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: *value, + Column: user.FieldAge, + }) } if value := uu.addage; value != nil { - updater.Add(user.FieldAge, *value) + spec.Fields.Add = append(spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: *value, + Column: user.FieldAge, + }) } if value := uu.name; value != nil { - updater.Set(user.FieldName, *value) + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: *value, + Column: user.FieldName, + }) } if value := uu.last; value != nil { - updater.Set(user.FieldLast, *value) + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: *value, + Column: user.FieldLast, + }) } if value := uu.nickname; value != nil { - updater.Set(user.FieldNickname, *value) + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: *value, + Column: user.FieldNickname, + }) } if uu.clearnickname { - updater.SetNull(user.FieldNickname) + spec.Fields.Clear = append(spec.Fields.Clear, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: user.FieldNickname, + }) } if value := uu.phone; value != nil { - updater.Set(user.FieldPhone, *value) + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: *value, + Column: user.FieldPhone, + }) } if uu.clearphone { - updater.SetNull(user.FieldPhone) + spec.Fields.Clear = append(spec.Fields.Clear, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: user.FieldPhone, + }) } if value := uu.password; value != nil { - updater.Set(user.FieldPassword, *value) + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: *value, + Column: user.FieldPassword, + }) } if uu.clearpassword { - updater.SetNull(user.FieldPassword) - } - if !updater.Empty() { - query, args := updater.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } + spec.Fields.Clear = append(spec.Fields.Clear, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: user.FieldPassword, + }) } if uu.clearedCard { - query, args := builder.Update(user.CardTable). - SetNull(user.CardColumn). - Where(sql.InInts(card.FieldID, ids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2O, + Inverse: false, + Table: user.CardTable, + Columns: []string{user.CardColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: card.FieldID, + }, + }, } + spec.Edges.Clear = append(spec.Edges.Clear, edge) } - if len(uu.card) > 0 { - for _, id := range ids { - eid, serr := strconv.Atoi(keys(uu.card)[0]) - if serr != nil { - return 0, rollback(tx, err) - } - query, args := builder.Update(user.CardTable). - Set(user.CardColumn, id). - Where(sql.EQ(card.FieldID, eid).And().IsNull(user.CardColumn)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } - affected, err := res.RowsAffected() + if nodes := uu.card; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2O, + Inverse: false, + Table: user.CardTable, + Columns: []string{user.CardColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: card.FieldID, + }, + }, + } + for k, _ := range nodes { + k, err := strconv.Atoi(k) if err != nil { - return 0, rollback(tx, err) - } - if int(affected) < len(uu.card) { - return 0, rollback(tx, &ConstraintError{msg: fmt.Sprintf("one of \"card\" %v already connected to a different \"User\"", keys(uu.card))}) + return 0, err } + edge.Target.Nodes = append(edge.Target.Nodes, k) } + spec.Edges.Add = append(spec.Edges.Add, edge) } - if len(uu.removedPets) > 0 { - eids := make([]int, len(uu.removedPets)) - for eid := range uu.removedPets { - eid, serr := strconv.Atoi(eid) - if serr != nil { - err = rollback(tx, serr) - return - } - eids = append(eids, eid) + if nodes := uu.removedPets; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: user.PetsTable, + Columns: []string{user.PetsColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: pet.FieldID, + }, + }, } - query, args := builder.Update(user.PetsTable). - SetNull(user.PetsColumn). - Where(sql.InInts(user.PetsColumn, ids...)). - Where(sql.InInts(pet.FieldID, eids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } - } - if len(uu.pets) > 0 { - for _, id := range ids { - p := sql.P() - for eid := range uu.pets { - eid, serr := strconv.Atoi(eid) - if serr != nil { - err = rollback(tx, serr) - return - } - p.Or().EQ(pet.FieldID, eid) - } - query, args := builder.Update(user.PetsTable). - Set(user.PetsColumn, id). - Where(sql.And(p, sql.IsNull(user.PetsColumn))). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } - affected, err := res.RowsAffected() + for k, _ := range nodes { + k, err := strconv.Atoi(k) if err != nil { - return 0, rollback(tx, err) - } - if int(affected) < len(uu.pets) { - return 0, rollback(tx, &ConstraintError{msg: fmt.Sprintf("one of \"pets\" %v already connected to a different \"User\"", keys(uu.pets))}) + return 0, err } + edge.Target.Nodes = append(edge.Target.Nodes, k) } + spec.Edges.Clear = append(spec.Edges.Clear, edge) } - if len(uu.removedFiles) > 0 { - eids := make([]int, len(uu.removedFiles)) - for eid := range uu.removedFiles { - eid, serr := strconv.Atoi(eid) - if serr != nil { - err = rollback(tx, serr) - return - } - eids = append(eids, eid) + if nodes := uu.pets; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: user.PetsTable, + Columns: []string{user.PetsColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: pet.FieldID, + }, + }, } - query, args := builder.Update(user.FilesTable). - SetNull(user.FilesColumn). - Where(sql.InInts(user.FilesColumn, ids...)). - Where(sql.InInts(file.FieldID, eids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } - } - if len(uu.files) > 0 { - for _, id := range ids { - p := sql.P() - for eid := range uu.files { - eid, serr := strconv.Atoi(eid) - if serr != nil { - err = rollback(tx, serr) - return - } - p.Or().EQ(file.FieldID, eid) - } - query, args := builder.Update(user.FilesTable). - Set(user.FilesColumn, id). - Where(sql.And(p, sql.IsNull(user.FilesColumn))). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } - affected, err := res.RowsAffected() + for k, _ := range nodes { + k, err := strconv.Atoi(k) if err != nil { - return 0, rollback(tx, err) - } - if int(affected) < len(uu.files) { - return 0, rollback(tx, &ConstraintError{msg: fmt.Sprintf("one of \"files\" %v already connected to a different \"User\"", keys(uu.files))}) + return 0, err } + edge.Target.Nodes = append(edge.Target.Nodes, k) } + spec.Edges.Add = append(spec.Edges.Add, edge) } - if len(uu.removedGroups) > 0 { - eids := make([]int, len(uu.removedGroups)) - for eid := range uu.removedGroups { - eid, serr := strconv.Atoi(eid) - if serr != nil { - err = rollback(tx, serr) - return + if nodes := uu.removedFiles; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: user.FilesTable, + Columns: []string{user.FilesColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: file.FieldID, + }, + }, + } + for k, _ := range nodes { + k, err := strconv.Atoi(k) + if err != nil { + return 0, err } - eids = append(eids, eid) - } - query, args := builder.Delete(user.GroupsTable). - Where(sql.InInts(user.GroupsPrimaryKey[0], ids...)). - Where(sql.InInts(user.GroupsPrimaryKey[1], eids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) + edge.Target.Nodes = append(edge.Target.Nodes, k) } + spec.Edges.Clear = append(spec.Edges.Clear, edge) } - if len(uu.groups) > 0 { - values := make([][]int, 0, len(ids)) - for _, id := range ids { - for eid := range uu.groups { - eid, serr := strconv.Atoi(eid) - if serr != nil { - err = rollback(tx, serr) - return - } - values = append(values, []int{id, eid}) + if nodes := uu.files; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: user.FilesTable, + Columns: []string{user.FilesColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: file.FieldID, + }, + }, + } + for k, _ := range nodes { + k, err := strconv.Atoi(k) + if err != nil { + return 0, err } + edge.Target.Nodes = append(edge.Target.Nodes, k) } - builder := builder.Insert(user.GroupsTable). - Columns(user.GroupsPrimaryKey[0], user.GroupsPrimaryKey[1]) - for _, v := range values { - builder.Values(v[0], v[1]) - } - query, args := builder.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } + spec.Edges.Add = append(spec.Edges.Add, edge) } - if len(uu.removedFriends) > 0 { - eids := make([]int, len(uu.removedFriends)) - for eid := range uu.removedFriends { - eid, serr := strconv.Atoi(eid) - if serr != nil { - err = rollback(tx, serr) - return + if nodes := uu.removedGroups; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: false, + Table: user.GroupsTable, + Columns: user.GroupsPrimaryKey, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: group.FieldID, + }, + }, + } + for k, _ := range nodes { + k, err := strconv.Atoi(k) + if err != nil { + return 0, err } - eids = append(eids, eid) - } - query, args := builder.Delete(user.FriendsTable). - Where(sql.InInts(user.FriendsPrimaryKey[0], ids...)). - Where(sql.InInts(user.FriendsPrimaryKey[1], eids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } - query, args = builder.Delete(user.FriendsTable). - Where(sql.InInts(user.FriendsPrimaryKey[1], ids...)). - Where(sql.InInts(user.FriendsPrimaryKey[0], eids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) + edge.Target.Nodes = append(edge.Target.Nodes, k) } + spec.Edges.Clear = append(spec.Edges.Clear, edge) } - if len(uu.friends) > 0 { - values := make([][]int, 0, len(ids)) - for _, id := range ids { - for eid := range uu.friends { - eid, serr := strconv.Atoi(eid) - if serr != nil { - err = rollback(tx, serr) - return - } - values = append(values, []int{id, eid}, []int{eid, id}) + if nodes := uu.groups; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: false, + Table: user.GroupsTable, + Columns: user.GroupsPrimaryKey, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: group.FieldID, + }, + }, + } + for k, _ := range nodes { + k, err := strconv.Atoi(k) + if err != nil { + return 0, err } + edge.Target.Nodes = append(edge.Target.Nodes, k) } - builder := builder.Insert(user.FriendsTable). - Columns(user.FriendsPrimaryKey[0], user.FriendsPrimaryKey[1]) - for _, v := range values { - builder.Values(v[0], v[1]) - } - query, args := builder.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } + spec.Edges.Add = append(spec.Edges.Add, edge) } - if len(uu.removedFollowers) > 0 { - eids := make([]int, len(uu.removedFollowers)) - for eid := range uu.removedFollowers { - eid, serr := strconv.Atoi(eid) - if serr != nil { - err = rollback(tx, serr) - return + if nodes := uu.removedFriends; 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.TypeString, + Column: user.FieldID, + }, + }, + } + for k, _ := range nodes { + k, err := strconv.Atoi(k) + if err != nil { + return 0, err } - eids = append(eids, eid) - } - query, args := builder.Delete(user.FollowersTable). - Where(sql.InInts(user.FollowersPrimaryKey[1], ids...)). - Where(sql.InInts(user.FollowersPrimaryKey[0], eids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) + edge.Target.Nodes = append(edge.Target.Nodes, k) } + spec.Edges.Clear = append(spec.Edges.Clear, edge) } - if len(uu.followers) > 0 { - values := make([][]int, 0, len(ids)) - for _, id := range ids { - for eid := range uu.followers { - eid, serr := strconv.Atoi(eid) - if serr != nil { - err = rollback(tx, serr) - return - } - values = append(values, []int{id, eid}) + if nodes := uu.friends; 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.TypeString, + Column: user.FieldID, + }, + }, + } + for k, _ := range nodes { + k, err := strconv.Atoi(k) + if err != nil { + return 0, err } + edge.Target.Nodes = append(edge.Target.Nodes, k) } - builder := builder.Insert(user.FollowersTable). - Columns(user.FollowersPrimaryKey[1], user.FollowersPrimaryKey[0]) - for _, v := range values { - builder.Values(v[0], v[1]) - } - query, args := builder.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } + spec.Edges.Add = append(spec.Edges.Add, edge) } - if len(uu.removedFollowing) > 0 { - eids := make([]int, len(uu.removedFollowing)) - for eid := range uu.removedFollowing { - eid, serr := strconv.Atoi(eid) - if serr != nil { - err = rollback(tx, serr) - return + if nodes := uu.removedFollowers; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: true, + Table: user.FollowersTable, + Columns: user.FollowersPrimaryKey, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: user.FieldID, + }, + }, + } + for k, _ := range nodes { + k, err := strconv.Atoi(k) + if err != nil { + return 0, err } - eids = append(eids, eid) - } - query, args := builder.Delete(user.FollowingTable). - Where(sql.InInts(user.FollowingPrimaryKey[0], ids...)). - Where(sql.InInts(user.FollowingPrimaryKey[1], eids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) + edge.Target.Nodes = append(edge.Target.Nodes, k) } + spec.Edges.Clear = append(spec.Edges.Clear, edge) } - if len(uu.following) > 0 { - values := make([][]int, 0, len(ids)) - for _, id := range ids { - for eid := range uu.following { - eid, serr := strconv.Atoi(eid) - if serr != nil { - err = rollback(tx, serr) - return - } - values = append(values, []int{id, eid}) + if nodes := uu.followers; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: true, + Table: user.FollowersTable, + Columns: user.FollowersPrimaryKey, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: user.FieldID, + }, + }, + } + for k, _ := range nodes { + k, err := strconv.Atoi(k) + if err != nil { + return 0, err } + edge.Target.Nodes = append(edge.Target.Nodes, k) } - builder := builder.Insert(user.FollowingTable). - Columns(user.FollowingPrimaryKey[0], user.FollowingPrimaryKey[1]) - for _, v := range values { - builder.Values(v[0], v[1]) + spec.Edges.Add = append(spec.Edges.Add, edge) + } + if nodes := uu.removedFollowing; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: false, + Table: user.FollowingTable, + Columns: user.FollowingPrimaryKey, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: user.FieldID, + }, + }, } - query, args := builder.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) + for k, _ := range nodes { + k, err := strconv.Atoi(k) + if err != nil { + return 0, err + } + edge.Target.Nodes = append(edge.Target.Nodes, k) } + spec.Edges.Clear = append(spec.Edges.Clear, edge) + } + if nodes := uu.following; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: false, + Table: user.FollowingTable, + Columns: user.FollowingPrimaryKey, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: user.FieldID, + }, + }, + } + for k, _ := range nodes { + k, err := strconv.Atoi(k) + if err != nil { + return 0, err + } + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + spec.Edges.Add = append(spec.Edges.Add, edge) } if uu.clearedTeam { - query, args := builder.Update(user.TeamTable). - SetNull(user.TeamColumn). - Where(sql.InInts(pet.FieldID, ids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2O, + Inverse: false, + Table: user.TeamTable, + Columns: []string{user.TeamColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: pet.FieldID, + }, + }, } + spec.Edges.Clear = append(spec.Edges.Clear, edge) } - if len(uu.team) > 0 { - for _, id := range ids { - eid, serr := strconv.Atoi(keys(uu.team)[0]) - if serr != nil { - return 0, rollback(tx, err) - } - query, args := builder.Update(user.TeamTable). - Set(user.TeamColumn, id). - Where(sql.EQ(pet.FieldID, eid).And().IsNull(user.TeamColumn)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } - affected, err := res.RowsAffected() - if err != nil { - return 0, rollback(tx, err) - } - if int(affected) < len(uu.team) { - return 0, rollback(tx, &ConstraintError{msg: fmt.Sprintf("one of \"team\" %v already connected to a different \"User\"", keys(uu.team))}) - } + if nodes := uu.team; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2O, + Inverse: false, + Table: user.TeamTable, + Columns: []string{user.TeamColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: pet.FieldID, + }, + }, } + for k, _ := range nodes { + k, err := strconv.Atoi(k) + if err != nil { + return 0, err + } + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + spec.Edges.Add = append(spec.Edges.Add, edge) } if uu.clearedSpouse { - query, args := builder.Update(user.SpouseTable). - SetNull(user.SpouseColumn). - Where(sql.InInts(user.FieldID, ids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } - query, args = builder.Update(user.SpouseTable). - SetNull(user.SpouseColumn). - Where(sql.InInts(user.SpouseColumn, ids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2O, + Inverse: false, + Table: user.SpouseTable, + Columns: []string{user.SpouseColumn}, + Bidi: true, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: user.FieldID, + }, + }, } + spec.Edges.Clear = append(spec.Edges.Clear, edge) } - if len(uu.spouse) > 0 { - if n := len(ids); n > 1 { - return 0, rollback(tx, fmt.Errorf("ent: can't link O2O edge \"spouse\" to %d vertices (> 1)", n)) + if nodes := uu.spouse; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2O, + Inverse: false, + Table: user.SpouseTable, + Columns: []string{user.SpouseColumn}, + Bidi: true, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: user.FieldID, + }, + }, } - for eid := range uu.spouse { - eid, serr := strconv.Atoi(eid) - if serr != nil { - err = rollback(tx, serr) - return - } - query, args := builder.Update(user.SpouseTable). - Set(user.SpouseColumn, eid). - Where(sql.EQ(user.FieldID, ids[0])).Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } - query, args = builder.Update(user.SpouseTable). - Set(user.SpouseColumn, ids[0]). - Where(sql.EQ(user.FieldID, eid).And().IsNull(user.SpouseColumn)).Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } - affected, err := res.RowsAffected() + for k, _ := range nodes { + k, err := strconv.Atoi(k) if err != nil { - return 0, rollback(tx, err) - } - if int(affected) < len(uu.spouse) { - return 0, rollback(tx, &ConstraintError{msg: fmt.Sprintf("\"spouse\" (%v) already connected to a different \"User\"", eid)}) + return 0, err } + edge.Target.Nodes = append(edge.Target.Nodes, k) } + spec.Edges.Add = append(spec.Edges.Add, edge) } - if len(uu.removedChildren) > 0 { - eids := make([]int, len(uu.removedChildren)) - for eid := range uu.removedChildren { - eid, serr := strconv.Atoi(eid) - if serr != nil { - err = rollback(tx, serr) - return - } - eids = append(eids, eid) + if nodes := uu.removedChildren; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: true, + Table: user.ChildrenTable, + Columns: []string{user.ChildrenColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: user.FieldID, + }, + }, } - query, args := builder.Update(user.ChildrenTable). - SetNull(user.ChildrenColumn). - Where(sql.InInts(user.ChildrenColumn, ids...)). - Where(sql.InInts(user.FieldID, eids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } - } - if len(uu.children) > 0 { - for _, id := range ids { - p := sql.P() - for eid := range uu.children { - eid, serr := strconv.Atoi(eid) - if serr != nil { - err = rollback(tx, serr) - return - } - p.Or().EQ(user.FieldID, eid) - } - query, args := builder.Update(user.ChildrenTable). - Set(user.ChildrenColumn, id). - Where(sql.And(p, sql.IsNull(user.ChildrenColumn))). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } - affected, err := res.RowsAffected() + for k, _ := range nodes { + k, err := strconv.Atoi(k) if err != nil { - return 0, rollback(tx, err) - } - if int(affected) < len(uu.children) { - return 0, rollback(tx, &ConstraintError{msg: fmt.Sprintf("one of \"children\" %v already connected to a different \"User\"", keys(uu.children))}) + return 0, err } + edge.Target.Nodes = append(edge.Target.Nodes, k) } + spec.Edges.Clear = append(spec.Edges.Clear, edge) + } + if nodes := uu.children; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: true, + Table: user.ChildrenTable, + Columns: []string{user.ChildrenColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: user.FieldID, + }, + }, + } + for k, _ := range nodes { + k, err := strconv.Atoi(k) + if err != nil { + return 0, err + } + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + spec.Edges.Add = append(spec.Edges.Add, edge) } if uu.clearedParent { - query, args := builder.Update(user.ParentTable). - SetNull(user.ParentColumn). - Where(sql.InInts(user.FieldID, ids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: false, + Table: user.ParentTable, + Columns: []string{user.ParentColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: user.FieldID, + }, + }, } + spec.Edges.Clear = append(spec.Edges.Clear, edge) } - if len(uu.parent) > 0 { - for eid := range uu.parent { - eid, serr := strconv.Atoi(eid) - if serr != nil { - err = rollback(tx, serr) - return - } - query, args := builder.Update(user.ParentTable). - Set(user.ParentColumn, eid). - Where(sql.InInts(user.FieldID, ids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } + if nodes := uu.parent; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: false, + Table: user.ParentTable, + Columns: []string{user.ParentColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: user.FieldID, + }, + }, } + for k, _ := range nodes { + k, err := strconv.Atoi(k) + if err != nil { + return 0, err + } + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + spec.Edges.Add = append(spec.Edges.Add, edge) } - if err = tx.Commit(); err != nil { + if n, err = sqlgraph.UpdateNodes(ctx, uu.driver, spec); err != nil { + if cerr, ok := isSQLConstraintError(err); ok { + err = cerr + } return 0, err } - return len(ids), nil + return n, nil } // UserUpdateOne is the builder for updating a single User entity. @@ -1682,533 +1740,618 @@ func (uuo *UserUpdateOne) ExecX(ctx context.Context) { } func (uuo *UserUpdateOne) sqlSave(ctx context.Context) (u *User, err error) { - var ( - builder = sql.Dialect(uuo.driver.Dialect()) - selector = builder.Select(user.Columns...).From(builder.Table(user.Table)) - ) - user.ID(uuo.id)(selector) - rows := &sql.Rows{} - query, args := selector.Query() - if err = uuo.driver.Query(ctx, query, args, rows); err != nil { - return nil, err + spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: user.Table, + Columns: user.Columns, + ID: &sqlgraph.FieldSpec{ + Value: uuo.id, + Type: field.TypeString, + Column: user.FieldID, + }, + }, } - defer rows.Close() - - var ids []int - for rows.Next() { - var id int - u = &User{config: uuo.config} - if err := u.FromRows(rows); err != nil { - return nil, fmt.Errorf("ent: failed scanning row into User: %v", err) - } - id = u.id() - ids = append(ids, id) - } - switch n := len(ids); { - case n == 0: - return nil, &ErrNotFound{fmt.Sprintf("User with id: %v", uuo.id)} - case n > 1: - return nil, fmt.Errorf("ent: more than one User with the same id: %v", uuo.id) - } - - tx, err := uuo.driver.Tx(ctx) - if err != nil { - return nil, err - } - var ( - res sql.Result - updater = builder.Update(user.Table) - ) - updater = updater.Where(sql.InInts(user.FieldID, ids...)) if value := uuo.age; value != nil { - updater.Set(user.FieldAge, *value) - u.Age = *value + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: *value, + Column: user.FieldAge, + }) } if value := uuo.addage; value != nil { - updater.Add(user.FieldAge, *value) - u.Age += *value + spec.Fields.Add = append(spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: *value, + Column: user.FieldAge, + }) } if value := uuo.name; value != nil { - updater.Set(user.FieldName, *value) - u.Name = *value + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: *value, + Column: user.FieldName, + }) } if value := uuo.last; value != nil { - updater.Set(user.FieldLast, *value) - u.Last = *value + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: *value, + Column: user.FieldLast, + }) } if value := uuo.nickname; value != nil { - updater.Set(user.FieldNickname, *value) - u.Nickname = *value + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: *value, + Column: user.FieldNickname, + }) } if uuo.clearnickname { - var value string - u.Nickname = value - updater.SetNull(user.FieldNickname) + spec.Fields.Clear = append(spec.Fields.Clear, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: user.FieldNickname, + }) } if value := uuo.phone; value != nil { - updater.Set(user.FieldPhone, *value) - u.Phone = *value + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: *value, + Column: user.FieldPhone, + }) } if uuo.clearphone { - var value string - u.Phone = value - updater.SetNull(user.FieldPhone) + spec.Fields.Clear = append(spec.Fields.Clear, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: user.FieldPhone, + }) } if value := uuo.password; value != nil { - updater.Set(user.FieldPassword, *value) - u.Password = *value + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: *value, + Column: user.FieldPassword, + }) } if uuo.clearpassword { - var value string - u.Password = value - updater.SetNull(user.FieldPassword) - } - if !updater.Empty() { - query, args := updater.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) - } + spec.Fields.Clear = append(spec.Fields.Clear, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: user.FieldPassword, + }) } if uuo.clearedCard { - query, args := builder.Update(user.CardTable). - SetNull(user.CardColumn). - Where(sql.InInts(card.FieldID, ids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2O, + Inverse: false, + Table: user.CardTable, + Columns: []string{user.CardColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: card.FieldID, + }, + }, } + spec.Edges.Clear = append(spec.Edges.Clear, edge) } - if len(uuo.card) > 0 { - for _, id := range ids { - eid, serr := strconv.Atoi(keys(uuo.card)[0]) - if serr != nil { - return nil, rollback(tx, err) - } - query, args := builder.Update(user.CardTable). - Set(user.CardColumn, id). - Where(sql.EQ(card.FieldID, eid).And().IsNull(user.CardColumn)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) - } - affected, err := res.RowsAffected() + if nodes := uuo.card; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2O, + Inverse: false, + Table: user.CardTable, + Columns: []string{user.CardColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: card.FieldID, + }, + }, + } + for k, _ := range nodes { + k, err := strconv.Atoi(k) if err != nil { - return nil, rollback(tx, err) - } - if int(affected) < len(uuo.card) { - return nil, rollback(tx, &ConstraintError{msg: fmt.Sprintf("one of \"card\" %v already connected to a different \"User\"", keys(uuo.card))}) + return nil, err } + edge.Target.Nodes = append(edge.Target.Nodes, k) } + spec.Edges.Add = append(spec.Edges.Add, edge) } - if len(uuo.removedPets) > 0 { - eids := make([]int, len(uuo.removedPets)) - for eid := range uuo.removedPets { - eid, serr := strconv.Atoi(eid) - if serr != nil { - err = rollback(tx, serr) - return - } - eids = append(eids, eid) + if nodes := uuo.removedPets; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: user.PetsTable, + Columns: []string{user.PetsColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: pet.FieldID, + }, + }, } - query, args := builder.Update(user.PetsTable). - SetNull(user.PetsColumn). - Where(sql.InInts(user.PetsColumn, ids...)). - Where(sql.InInts(pet.FieldID, eids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) - } - } - if len(uuo.pets) > 0 { - for _, id := range ids { - p := sql.P() - for eid := range uuo.pets { - eid, serr := strconv.Atoi(eid) - if serr != nil { - err = rollback(tx, serr) - return - } - p.Or().EQ(pet.FieldID, eid) - } - query, args := builder.Update(user.PetsTable). - Set(user.PetsColumn, id). - Where(sql.And(p, sql.IsNull(user.PetsColumn))). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) - } - affected, err := res.RowsAffected() + for k, _ := range nodes { + k, err := strconv.Atoi(k) if err != nil { - return nil, rollback(tx, err) - } - if int(affected) < len(uuo.pets) { - return nil, rollback(tx, &ConstraintError{msg: fmt.Sprintf("one of \"pets\" %v already connected to a different \"User\"", keys(uuo.pets))}) + return nil, err } + edge.Target.Nodes = append(edge.Target.Nodes, k) } + spec.Edges.Clear = append(spec.Edges.Clear, edge) } - if len(uuo.removedFiles) > 0 { - eids := make([]int, len(uuo.removedFiles)) - for eid := range uuo.removedFiles { - eid, serr := strconv.Atoi(eid) - if serr != nil { - err = rollback(tx, serr) - return - } - eids = append(eids, eid) + if nodes := uuo.pets; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: user.PetsTable, + Columns: []string{user.PetsColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: pet.FieldID, + }, + }, } - query, args := builder.Update(user.FilesTable). - SetNull(user.FilesColumn). - Where(sql.InInts(user.FilesColumn, ids...)). - Where(sql.InInts(file.FieldID, eids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) - } - } - if len(uuo.files) > 0 { - for _, id := range ids { - p := sql.P() - for eid := range uuo.files { - eid, serr := strconv.Atoi(eid) - if serr != nil { - err = rollback(tx, serr) - return - } - p.Or().EQ(file.FieldID, eid) - } - query, args := builder.Update(user.FilesTable). - Set(user.FilesColumn, id). - Where(sql.And(p, sql.IsNull(user.FilesColumn))). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) - } - affected, err := res.RowsAffected() + for k, _ := range nodes { + k, err := strconv.Atoi(k) if err != nil { - return nil, rollback(tx, err) - } - if int(affected) < len(uuo.files) { - return nil, rollback(tx, &ConstraintError{msg: fmt.Sprintf("one of \"files\" %v already connected to a different \"User\"", keys(uuo.files))}) + return nil, err } + edge.Target.Nodes = append(edge.Target.Nodes, k) } + spec.Edges.Add = append(spec.Edges.Add, edge) } - if len(uuo.removedGroups) > 0 { - eids := make([]int, len(uuo.removedGroups)) - for eid := range uuo.removedGroups { - eid, serr := strconv.Atoi(eid) - if serr != nil { - err = rollback(tx, serr) - return + if nodes := uuo.removedFiles; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: user.FilesTable, + Columns: []string{user.FilesColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: file.FieldID, + }, + }, + } + for k, _ := range nodes { + k, err := strconv.Atoi(k) + if err != nil { + return nil, err } - eids = append(eids, eid) - } - query, args := builder.Delete(user.GroupsTable). - Where(sql.InInts(user.GroupsPrimaryKey[0], ids...)). - Where(sql.InInts(user.GroupsPrimaryKey[1], eids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) + edge.Target.Nodes = append(edge.Target.Nodes, k) } + spec.Edges.Clear = append(spec.Edges.Clear, edge) } - if len(uuo.groups) > 0 { - values := make([][]int, 0, len(ids)) - for _, id := range ids { - for eid := range uuo.groups { - eid, serr := strconv.Atoi(eid) - if serr != nil { - err = rollback(tx, serr) - return - } - values = append(values, []int{id, eid}) + if nodes := uuo.files; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: user.FilesTable, + Columns: []string{user.FilesColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: file.FieldID, + }, + }, + } + for k, _ := range nodes { + k, err := strconv.Atoi(k) + if err != nil { + return nil, err } + edge.Target.Nodes = append(edge.Target.Nodes, k) } - builder := builder.Insert(user.GroupsTable). - Columns(user.GroupsPrimaryKey[0], user.GroupsPrimaryKey[1]) - for _, v := range values { - builder.Values(v[0], v[1]) - } - query, args := builder.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) - } + spec.Edges.Add = append(spec.Edges.Add, edge) } - if len(uuo.removedFriends) > 0 { - eids := make([]int, len(uuo.removedFriends)) - for eid := range uuo.removedFriends { - eid, serr := strconv.Atoi(eid) - if serr != nil { - err = rollback(tx, serr) - return + if nodes := uuo.removedGroups; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: false, + Table: user.GroupsTable, + Columns: user.GroupsPrimaryKey, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: group.FieldID, + }, + }, + } + for k, _ := range nodes { + k, err := strconv.Atoi(k) + if err != nil { + return nil, err } - eids = append(eids, eid) - } - query, args := builder.Delete(user.FriendsTable). - Where(sql.InInts(user.FriendsPrimaryKey[0], ids...)). - Where(sql.InInts(user.FriendsPrimaryKey[1], eids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) - } - query, args = builder.Delete(user.FriendsTable). - Where(sql.InInts(user.FriendsPrimaryKey[1], ids...)). - Where(sql.InInts(user.FriendsPrimaryKey[0], eids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) + edge.Target.Nodes = append(edge.Target.Nodes, k) } + spec.Edges.Clear = append(spec.Edges.Clear, edge) } - if len(uuo.friends) > 0 { - values := make([][]int, 0, len(ids)) - for _, id := range ids { - for eid := range uuo.friends { - eid, serr := strconv.Atoi(eid) - if serr != nil { - err = rollback(tx, serr) - return - } - values = append(values, []int{id, eid}, []int{eid, id}) + if nodes := uuo.groups; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: false, + Table: user.GroupsTable, + Columns: user.GroupsPrimaryKey, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: group.FieldID, + }, + }, + } + for k, _ := range nodes { + k, err := strconv.Atoi(k) + if err != nil { + return nil, err } + edge.Target.Nodes = append(edge.Target.Nodes, k) } - builder := builder.Insert(user.FriendsTable). - Columns(user.FriendsPrimaryKey[0], user.FriendsPrimaryKey[1]) - for _, v := range values { - builder.Values(v[0], v[1]) - } - query, args := builder.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) - } + spec.Edges.Add = append(spec.Edges.Add, edge) } - if len(uuo.removedFollowers) > 0 { - eids := make([]int, len(uuo.removedFollowers)) - for eid := range uuo.removedFollowers { - eid, serr := strconv.Atoi(eid) - if serr != nil { - err = rollback(tx, serr) - return + if nodes := uuo.removedFriends; 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.TypeString, + Column: user.FieldID, + }, + }, + } + for k, _ := range nodes { + k, err := strconv.Atoi(k) + if err != nil { + return nil, err } - eids = append(eids, eid) - } - query, args := builder.Delete(user.FollowersTable). - Where(sql.InInts(user.FollowersPrimaryKey[1], ids...)). - Where(sql.InInts(user.FollowersPrimaryKey[0], eids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) + edge.Target.Nodes = append(edge.Target.Nodes, k) } + spec.Edges.Clear = append(spec.Edges.Clear, edge) } - if len(uuo.followers) > 0 { - values := make([][]int, 0, len(ids)) - for _, id := range ids { - for eid := range uuo.followers { - eid, serr := strconv.Atoi(eid) - if serr != nil { - err = rollback(tx, serr) - return - } - values = append(values, []int{id, eid}) + if nodes := uuo.friends; 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.TypeString, + Column: user.FieldID, + }, + }, + } + for k, _ := range nodes { + k, err := strconv.Atoi(k) + if err != nil { + return nil, err } + edge.Target.Nodes = append(edge.Target.Nodes, k) } - builder := builder.Insert(user.FollowersTable). - Columns(user.FollowersPrimaryKey[1], user.FollowersPrimaryKey[0]) - for _, v := range values { - builder.Values(v[0], v[1]) - } - query, args := builder.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) - } + spec.Edges.Add = append(spec.Edges.Add, edge) } - if len(uuo.removedFollowing) > 0 { - eids := make([]int, len(uuo.removedFollowing)) - for eid := range uuo.removedFollowing { - eid, serr := strconv.Atoi(eid) - if serr != nil { - err = rollback(tx, serr) - return + if nodes := uuo.removedFollowers; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: true, + Table: user.FollowersTable, + Columns: user.FollowersPrimaryKey, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: user.FieldID, + }, + }, + } + for k, _ := range nodes { + k, err := strconv.Atoi(k) + if err != nil { + return nil, err } - eids = append(eids, eid) - } - query, args := builder.Delete(user.FollowingTable). - Where(sql.InInts(user.FollowingPrimaryKey[0], ids...)). - Where(sql.InInts(user.FollowingPrimaryKey[1], eids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) + edge.Target.Nodes = append(edge.Target.Nodes, k) } + spec.Edges.Clear = append(spec.Edges.Clear, edge) } - if len(uuo.following) > 0 { - values := make([][]int, 0, len(ids)) - for _, id := range ids { - for eid := range uuo.following { - eid, serr := strconv.Atoi(eid) - if serr != nil { - err = rollback(tx, serr) - return - } - values = append(values, []int{id, eid}) + if nodes := uuo.followers; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: true, + Table: user.FollowersTable, + Columns: user.FollowersPrimaryKey, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: user.FieldID, + }, + }, + } + for k, _ := range nodes { + k, err := strconv.Atoi(k) + if err != nil { + return nil, err } + edge.Target.Nodes = append(edge.Target.Nodes, k) } - builder := builder.Insert(user.FollowingTable). - Columns(user.FollowingPrimaryKey[0], user.FollowingPrimaryKey[1]) - for _, v := range values { - builder.Values(v[0], v[1]) + spec.Edges.Add = append(spec.Edges.Add, edge) + } + if nodes := uuo.removedFollowing; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: false, + Table: user.FollowingTable, + Columns: user.FollowingPrimaryKey, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: user.FieldID, + }, + }, } - query, args := builder.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) + for k, _ := range nodes { + k, err := strconv.Atoi(k) + if err != nil { + return nil, err + } + edge.Target.Nodes = append(edge.Target.Nodes, k) } + spec.Edges.Clear = append(spec.Edges.Clear, edge) + } + if nodes := uuo.following; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: false, + Table: user.FollowingTable, + Columns: user.FollowingPrimaryKey, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: user.FieldID, + }, + }, + } + for k, _ := range nodes { + k, err := strconv.Atoi(k) + if err != nil { + return nil, err + } + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + spec.Edges.Add = append(spec.Edges.Add, edge) } if uuo.clearedTeam { - query, args := builder.Update(user.TeamTable). - SetNull(user.TeamColumn). - Where(sql.InInts(pet.FieldID, ids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2O, + Inverse: false, + Table: user.TeamTable, + Columns: []string{user.TeamColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: pet.FieldID, + }, + }, } + spec.Edges.Clear = append(spec.Edges.Clear, edge) } - if len(uuo.team) > 0 { - for _, id := range ids { - eid, serr := strconv.Atoi(keys(uuo.team)[0]) - if serr != nil { - return nil, rollback(tx, err) - } - query, args := builder.Update(user.TeamTable). - Set(user.TeamColumn, id). - Where(sql.EQ(pet.FieldID, eid).And().IsNull(user.TeamColumn)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) - } - affected, err := res.RowsAffected() - if err != nil { - return nil, rollback(tx, err) - } - if int(affected) < len(uuo.team) { - return nil, rollback(tx, &ConstraintError{msg: fmt.Sprintf("one of \"team\" %v already connected to a different \"User\"", keys(uuo.team))}) - } + if nodes := uuo.team; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2O, + Inverse: false, + Table: user.TeamTable, + Columns: []string{user.TeamColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: pet.FieldID, + }, + }, } + for k, _ := range nodes { + k, err := strconv.Atoi(k) + if err != nil { + return nil, err + } + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + spec.Edges.Add = append(spec.Edges.Add, edge) } if uuo.clearedSpouse { - query, args := builder.Update(user.SpouseTable). - SetNull(user.SpouseColumn). - Where(sql.InInts(user.FieldID, ids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) - } - query, args = builder.Update(user.SpouseTable). - SetNull(user.SpouseColumn). - Where(sql.InInts(user.SpouseColumn, ids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2O, + Inverse: false, + Table: user.SpouseTable, + Columns: []string{user.SpouseColumn}, + Bidi: true, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: user.FieldID, + }, + }, } + spec.Edges.Clear = append(spec.Edges.Clear, edge) } - if len(uuo.spouse) > 0 { - if n := len(ids); n > 1 { - return nil, rollback(tx, fmt.Errorf("ent: can't link O2O edge \"spouse\" to %d vertices (> 1)", n)) + if nodes := uuo.spouse; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2O, + Inverse: false, + Table: user.SpouseTable, + Columns: []string{user.SpouseColumn}, + Bidi: true, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: user.FieldID, + }, + }, } - for eid := range uuo.spouse { - eid, serr := strconv.Atoi(eid) - if serr != nil { - err = rollback(tx, serr) - return - } - query, args := builder.Update(user.SpouseTable). - Set(user.SpouseColumn, eid). - Where(sql.EQ(user.FieldID, ids[0])).Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) - } - query, args = builder.Update(user.SpouseTable). - Set(user.SpouseColumn, ids[0]). - Where(sql.EQ(user.FieldID, eid).And().IsNull(user.SpouseColumn)).Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) - } - affected, err := res.RowsAffected() + for k, _ := range nodes { + k, err := strconv.Atoi(k) if err != nil { - return nil, rollback(tx, err) - } - if int(affected) < len(uuo.spouse) { - return nil, rollback(tx, &ConstraintError{msg: fmt.Sprintf("\"spouse\" (%v) already connected to a different \"User\"", eid)}) + return nil, err } + edge.Target.Nodes = append(edge.Target.Nodes, k) } + spec.Edges.Add = append(spec.Edges.Add, edge) } - if len(uuo.removedChildren) > 0 { - eids := make([]int, len(uuo.removedChildren)) - for eid := range uuo.removedChildren { - eid, serr := strconv.Atoi(eid) - if serr != nil { - err = rollback(tx, serr) - return - } - eids = append(eids, eid) + if nodes := uuo.removedChildren; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: true, + Table: user.ChildrenTable, + Columns: []string{user.ChildrenColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: user.FieldID, + }, + }, } - query, args := builder.Update(user.ChildrenTable). - SetNull(user.ChildrenColumn). - Where(sql.InInts(user.ChildrenColumn, ids...)). - Where(sql.InInts(user.FieldID, eids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) - } - } - if len(uuo.children) > 0 { - for _, id := range ids { - p := sql.P() - for eid := range uuo.children { - eid, serr := strconv.Atoi(eid) - if serr != nil { - err = rollback(tx, serr) - return - } - p.Or().EQ(user.FieldID, eid) - } - query, args := builder.Update(user.ChildrenTable). - Set(user.ChildrenColumn, id). - Where(sql.And(p, sql.IsNull(user.ChildrenColumn))). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) - } - affected, err := res.RowsAffected() + for k, _ := range nodes { + k, err := strconv.Atoi(k) if err != nil { - return nil, rollback(tx, err) - } - if int(affected) < len(uuo.children) { - return nil, rollback(tx, &ConstraintError{msg: fmt.Sprintf("one of \"children\" %v already connected to a different \"User\"", keys(uuo.children))}) + return nil, err } + edge.Target.Nodes = append(edge.Target.Nodes, k) } + spec.Edges.Clear = append(spec.Edges.Clear, edge) + } + if nodes := uuo.children; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: true, + Table: user.ChildrenTable, + Columns: []string{user.ChildrenColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: user.FieldID, + }, + }, + } + for k, _ := range nodes { + k, err := strconv.Atoi(k) + if err != nil { + return nil, err + } + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + spec.Edges.Add = append(spec.Edges.Add, edge) } if uuo.clearedParent { - query, args := builder.Update(user.ParentTable). - SetNull(user.ParentColumn). - Where(sql.InInts(user.FieldID, ids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: false, + Table: user.ParentTable, + Columns: []string{user.ParentColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: user.FieldID, + }, + }, } + spec.Edges.Clear = append(spec.Edges.Clear, edge) } - if len(uuo.parent) > 0 { - for eid := range uuo.parent { - eid, serr := strconv.Atoi(eid) - if serr != nil { - err = rollback(tx, serr) - return - } - query, args := builder.Update(user.ParentTable). - Set(user.ParentColumn, eid). - Where(sql.InInts(user.FieldID, ids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) - } + if nodes := uuo.parent; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: false, + Table: user.ParentTable, + Columns: []string{user.ParentColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: user.FieldID, + }, + }, } + for k, _ := range nodes { + k, err := strconv.Atoi(k) + if err != nil { + return nil, err + } + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + spec.Edges.Add = append(spec.Edges.Add, edge) } - if err = tx.Commit(); err != nil { + u = &User{config: uuo.config} + spec.ScanTypes = []interface{}{ + &sql.NullInt64{}, + &sql.NullInt64{}, + &sql.NullString{}, + &sql.NullString{}, + &sql.NullString{}, + &sql.NullString{}, + &sql.NullString{}, + } + spec.Assign = func(values ...interface{}) error { + if m, n := len(values), len(spec.ScanTypes); m != n { + return fmt.Errorf("mismatch number of scan values: %d != %d", m, n) + } + value, ok := values[0].(*sql.NullInt64) + if !ok { + return fmt.Errorf("unexpected type %T for field id", value) + } + u.ID = strconv.FormatInt(value.Int64, 10) + values = values[1:] + if value, ok := values[0].(*sql.NullInt64); !ok { + return fmt.Errorf("unexpected type %T for field age", values[0]) + } else if value.Valid { + u.Age = int(value.Int64) + } + if value, ok := values[1].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field name", values[1]) + } else if value.Valid { + u.Name = value.String + } + if value, ok := values[2].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field last", values[2]) + } else if value.Valid { + u.Last = value.String + } + if value, ok := values[3].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field nickname", values[3]) + } else if value.Valid { + u.Nickname = value.String + } + if value, ok := values[4].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field phone", values[4]) + } else if value.Valid { + u.Phone = value.String + } + if value, ok := values[5].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field password", values[5]) + } else if value.Valid { + u.Password = value.String + } + return nil + } + if err = sqlgraph.UpdateNode(ctx, uuo.driver, spec); err != nil { + if cerr, ok := isSQLConstraintError(err); ok { + err = cerr + } return nil, err } return u, nil diff --git a/entc/integration/idtype/ent/user_update.go b/entc/integration/idtype/ent/user_update.go index 1820ae9bc..51b7908b5 100644 --- a/entc/integration/idtype/ent/user_update.go +++ b/entc/integration/idtype/ent/user_update.go @@ -12,8 +12,10 @@ import ( "fmt" "github.com/facebookincubator/ent/dialect/sql" + "github.com/facebookincubator/ent/dialect/sql/sqlgraph" "github.com/facebookincubator/ent/entc/integration/idtype/ent/predicate" "github.com/facebookincubator/ent/entc/integration/idtype/ent/user" + "github.com/facebookincubator/ent/schema/field" ) // UserUpdate is the builder for updating User entities. @@ -180,161 +182,148 @@ func (uu *UserUpdate) ExecX(ctx context.Context) { } func (uu *UserUpdate) sqlSave(ctx context.Context) (n int, err error) { - var ( - builder = sql.Dialect(uu.driver.Dialect()) - selector = builder.Select(user.FieldID).From(builder.Table(user.Table)) - ) - for _, p := range uu.predicates { - p(selector) + spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: user.Table, + Columns: user.Columns, + ID: &sqlgraph.FieldSpec{ + Type: field.TypeUint64, + Column: user.FieldID, + }, + }, } - rows := &sql.Rows{} - query, args := selector.Query() - if err = uu.driver.Query(ctx, query, args, rows); err != nil { - return 0, err - } - defer rows.Close() - - var ids []int - for rows.Next() { - var id int - if err := rows.Scan(&id); err != nil { - return 0, fmt.Errorf("ent: failed reading id: %v", err) + if ps := uu.predicates; len(ps) > 0 { + spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } } - ids = append(ids, id) } - if len(ids) == 0 { - return 0, nil - } - - tx, err := uu.driver.Tx(ctx) - if err != nil { - return 0, err - } - var ( - res sql.Result - updater = builder.Update(user.Table) - ) - updater = updater.Where(sql.InInts(user.FieldID, ids...)) if value := uu.name; value != nil { - updater.Set(user.FieldName, *value) - } - if !updater.Empty() { - query, args := updater.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: *value, + Column: user.FieldName, + }) } if uu.clearedSpouse { - query, args := builder.Update(user.SpouseTable). - SetNull(user.SpouseColumn). - Where(sql.InInts(user.FieldID, ids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } - query, args = builder.Update(user.SpouseTable). - SetNull(user.SpouseColumn). - Where(sql.InInts(user.SpouseColumn, ids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2O, + Inverse: false, + Table: user.SpouseTable, + Columns: []string{user.SpouseColumn}, + Bidi: true, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeUint64, + Column: user.FieldID, + }, + }, } + spec.Edges.Clear = append(spec.Edges.Clear, edge) } - if len(uu.spouse) > 0 { - if n := len(ids); n > 1 { - return 0, rollback(tx, fmt.Errorf("ent: can't link O2O edge \"spouse\" to %d vertices (> 1)", n)) + if nodes := uu.spouse; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2O, + Inverse: false, + Table: user.SpouseTable, + Columns: []string{user.SpouseColumn}, + Bidi: true, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeUint64, + Column: user.FieldID, + }, + }, } - for eid := range uu.spouse { - eid := int(eid) - query, args := builder.Update(user.SpouseTable). - Set(user.SpouseColumn, eid). - Where(sql.EQ(user.FieldID, ids[0])).Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } - query, args = builder.Update(user.SpouseTable). - Set(user.SpouseColumn, ids[0]). - Where(sql.EQ(user.FieldID, eid).And().IsNull(user.SpouseColumn)).Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } - affected, err := res.RowsAffected() - if err != nil { - return 0, rollback(tx, err) - } - if int(affected) < len(uu.spouse) { - return 0, rollback(tx, &ConstraintError{msg: fmt.Sprintf("\"spouse\" (%v) already connected to a different \"User\"", eid)}) - } + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) } + spec.Edges.Add = append(spec.Edges.Add, edge) } - if len(uu.removedFollowers) > 0 { - eids := make([]int, len(uu.removedFollowers)) - for eid := range uu.removedFollowers { - eid := int(eid) - eids = append(eids, eid) + if nodes := uu.removedFollowers; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: true, + Table: user.FollowersTable, + Columns: user.FollowersPrimaryKey, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeUint64, + Column: user.FieldID, + }, + }, } - query, args := builder.Delete(user.FollowersTable). - Where(sql.InInts(user.FollowersPrimaryKey[1], ids...)). - Where(sql.InInts(user.FollowersPrimaryKey[0], eids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) } + spec.Edges.Clear = append(spec.Edges.Clear, edge) } - if len(uu.followers) > 0 { - values := make([][]int, 0, len(ids)) - for _, id := range ids { - for eid := range uu.followers { - eid := int(eid) - values = append(values, []int{id, eid}) - } + if nodes := uu.followers; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: true, + Table: user.FollowersTable, + Columns: user.FollowersPrimaryKey, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeUint64, + Column: user.FieldID, + }, + }, } - builder := builder.Insert(user.FollowersTable). - Columns(user.FollowersPrimaryKey[1], user.FollowersPrimaryKey[0]) - for _, v := range values { - builder.Values(v[0], v[1]) - } - query, args := builder.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) } + spec.Edges.Add = append(spec.Edges.Add, edge) } - if len(uu.removedFollowing) > 0 { - eids := make([]int, len(uu.removedFollowing)) - for eid := range uu.removedFollowing { - eid := int(eid) - eids = append(eids, eid) + if nodes := uu.removedFollowing; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: false, + Table: user.FollowingTable, + Columns: user.FollowingPrimaryKey, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeUint64, + Column: user.FieldID, + }, + }, } - query, args := builder.Delete(user.FollowingTable). - Where(sql.InInts(user.FollowingPrimaryKey[0], ids...)). - Where(sql.InInts(user.FollowingPrimaryKey[1], eids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) } + spec.Edges.Clear = append(spec.Edges.Clear, edge) } - if len(uu.following) > 0 { - values := make([][]int, 0, len(ids)) - for _, id := range ids { - for eid := range uu.following { - eid := int(eid) - values = append(values, []int{id, eid}) - } + if nodes := uu.following; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: false, + Table: user.FollowingTable, + Columns: user.FollowingPrimaryKey, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeUint64, + Column: user.FieldID, + }, + }, } - builder := builder.Insert(user.FollowingTable). - Columns(user.FollowingPrimaryKey[0], user.FollowingPrimaryKey[1]) - for _, v := range values { - builder.Values(v[0], v[1]) - } - query, args := builder.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) } + spec.Edges.Add = append(spec.Edges.Add, edge) } - if err = tx.Commit(); err != nil { + if n, err = sqlgraph.UpdateNodes(ctx, uu.driver, spec); err != nil { + if cerr, ok := isSQLConstraintError(err); ok { + err = cerr + } return 0, err } - return len(ids), nil + return n, nil } // UserUpdateOne is the builder for updating a single User entity. @@ -495,162 +484,161 @@ func (uuo *UserUpdateOne) ExecX(ctx context.Context) { } func (uuo *UserUpdateOne) sqlSave(ctx context.Context) (u *User, err error) { - var ( - builder = sql.Dialect(uuo.driver.Dialect()) - selector = builder.Select(user.Columns...).From(builder.Table(user.Table)) - ) - user.ID(uuo.id)(selector) - rows := &sql.Rows{} - query, args := selector.Query() - if err = uuo.driver.Query(ctx, query, args, rows); err != nil { - return nil, err + spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: user.Table, + Columns: user.Columns, + ID: &sqlgraph.FieldSpec{ + Value: uuo.id, + Type: field.TypeUint64, + Column: user.FieldID, + }, + }, } - defer rows.Close() - - var ids []int - for rows.Next() { - var id int - u = &User{config: uuo.config} - if err := u.FromRows(rows); err != nil { - return nil, fmt.Errorf("ent: failed scanning row into User: %v", err) - } - id = int(u.ID) - ids = append(ids, id) - } - switch n := len(ids); { - case n == 0: - return nil, &ErrNotFound{fmt.Sprintf("User with id: %v", uuo.id)} - case n > 1: - return nil, fmt.Errorf("ent: more than one User with the same id: %v", uuo.id) - } - - tx, err := uuo.driver.Tx(ctx) - if err != nil { - return nil, err - } - var ( - res sql.Result - updater = builder.Update(user.Table) - ) - updater = updater.Where(sql.InInts(user.FieldID, ids...)) if value := uuo.name; value != nil { - updater.Set(user.FieldName, *value) - u.Name = *value - } - if !updater.Empty() { - query, args := updater.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) - } + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: *value, + Column: user.FieldName, + }) } if uuo.clearedSpouse { - query, args := builder.Update(user.SpouseTable). - SetNull(user.SpouseColumn). - Where(sql.InInts(user.FieldID, ids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) - } - query, args = builder.Update(user.SpouseTable). - SetNull(user.SpouseColumn). - Where(sql.InInts(user.SpouseColumn, ids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2O, + Inverse: false, + Table: user.SpouseTable, + Columns: []string{user.SpouseColumn}, + Bidi: true, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeUint64, + Column: user.FieldID, + }, + }, } + spec.Edges.Clear = append(spec.Edges.Clear, edge) } - if len(uuo.spouse) > 0 { - if n := len(ids); n > 1 { - return nil, rollback(tx, fmt.Errorf("ent: can't link O2O edge \"spouse\" to %d vertices (> 1)", n)) + if nodes := uuo.spouse; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2O, + Inverse: false, + Table: user.SpouseTable, + Columns: []string{user.SpouseColumn}, + Bidi: true, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeUint64, + Column: user.FieldID, + }, + }, } - for eid := range uuo.spouse { - eid := int(eid) - query, args := builder.Update(user.SpouseTable). - Set(user.SpouseColumn, eid). - Where(sql.EQ(user.FieldID, ids[0])).Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) - } - query, args = builder.Update(user.SpouseTable). - Set(user.SpouseColumn, ids[0]). - Where(sql.EQ(user.FieldID, eid).And().IsNull(user.SpouseColumn)).Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) - } - affected, err := res.RowsAffected() - if err != nil { - return nil, rollback(tx, err) - } - if int(affected) < len(uuo.spouse) { - return nil, rollback(tx, &ConstraintError{msg: fmt.Sprintf("\"spouse\" (%v) already connected to a different \"User\"", eid)}) - } + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) } + spec.Edges.Add = append(spec.Edges.Add, edge) } - if len(uuo.removedFollowers) > 0 { - eids := make([]int, len(uuo.removedFollowers)) - for eid := range uuo.removedFollowers { - eid := int(eid) - eids = append(eids, eid) + if nodes := uuo.removedFollowers; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: true, + Table: user.FollowersTable, + Columns: user.FollowersPrimaryKey, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeUint64, + Column: user.FieldID, + }, + }, } - query, args := builder.Delete(user.FollowersTable). - Where(sql.InInts(user.FollowersPrimaryKey[1], ids...)). - Where(sql.InInts(user.FollowersPrimaryKey[0], eids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) } + spec.Edges.Clear = append(spec.Edges.Clear, edge) } - if len(uuo.followers) > 0 { - values := make([][]int, 0, len(ids)) - for _, id := range ids { - for eid := range uuo.followers { - eid := int(eid) - values = append(values, []int{id, eid}) - } + if nodes := uuo.followers; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: true, + Table: user.FollowersTable, + Columns: user.FollowersPrimaryKey, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeUint64, + Column: user.FieldID, + }, + }, } - builder := builder.Insert(user.FollowersTable). - Columns(user.FollowersPrimaryKey[1], user.FollowersPrimaryKey[0]) - for _, v := range values { - builder.Values(v[0], v[1]) - } - query, args := builder.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) } + spec.Edges.Add = append(spec.Edges.Add, edge) } - if len(uuo.removedFollowing) > 0 { - eids := make([]int, len(uuo.removedFollowing)) - for eid := range uuo.removedFollowing { - eid := int(eid) - eids = append(eids, eid) + if nodes := uuo.removedFollowing; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: false, + Table: user.FollowingTable, + Columns: user.FollowingPrimaryKey, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeUint64, + Column: user.FieldID, + }, + }, } - query, args := builder.Delete(user.FollowingTable). - Where(sql.InInts(user.FollowingPrimaryKey[0], ids...)). - Where(sql.InInts(user.FollowingPrimaryKey[1], eids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) } + spec.Edges.Clear = append(spec.Edges.Clear, edge) } - if len(uuo.following) > 0 { - values := make([][]int, 0, len(ids)) - for _, id := range ids { - for eid := range uuo.following { - eid := int(eid) - values = append(values, []int{id, eid}) - } + if nodes := uuo.following; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: false, + Table: user.FollowingTable, + Columns: user.FollowingPrimaryKey, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeUint64, + Column: user.FieldID, + }, + }, } - builder := builder.Insert(user.FollowingTable). - Columns(user.FollowingPrimaryKey[0], user.FollowingPrimaryKey[1]) - for _, v := range values { - builder.Values(v[0], v[1]) - } - query, args := builder.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) } + spec.Edges.Add = append(spec.Edges.Add, edge) } - if err = tx.Commit(); err != nil { + u = &User{config: uuo.config} + spec.ScanTypes = []interface{}{ + &sql.NullInt64{}, + &sql.NullString{}, + } + spec.Assign = func(values ...interface{}) error { + if m, n := len(values), len(spec.ScanTypes); m != n { + return fmt.Errorf("mismatch number of scan values: %d != %d", m, n) + } + value, ok := values[0].(*sql.NullInt64) + if !ok { + return fmt.Errorf("unexpected type %T for field id", value) + } + u.ID = uint64(value.Int64) + values = values[1:] + if value, ok := values[0].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field name", values[0]) + } else if value.Valid { + u.Name = value.String + } + return nil + } + if err = sqlgraph.UpdateNode(ctx, uuo.driver, spec); err != nil { + if cerr, ok := isSQLConstraintError(err); ok { + err = cerr + } return nil, err } return u, nil diff --git a/entc/integration/integration_test.go b/entc/integration/integration_test.go index a2691a447..635aa02dc 100644 --- a/entc/integration/integration_test.go +++ b/entc/integration/integration_test.go @@ -38,7 +38,7 @@ func TestSQLite(t *testing.T) { client, err := ent.Open("sqlite3", "file:ent?mode=memory&cache=shared&_fk=1") require.NoError(t, err) defer client.Close() - require.NoError(t, client.Schema.Create(context.Background()), migrate.WithDropColumn(true), migrate.WithDropIndex(true)) + require.NoError(t, client.Schema.Create(context.Background(), migrate.WithDropColumn(true), migrate.WithDropIndex(true))) for _, tt := range tests { name := runtime.FuncForPC(reflect.ValueOf(tt).Pointer()).Name() t.Run(name[strings.LastIndex(name, ".")+1:], func(t *testing.T) { @@ -49,6 +49,7 @@ func TestSQLite(t *testing.T) { } func TestMySQL(t *testing.T) { + t.Parallel() for version, port := range map[string]int{"56": 3306, "57": 3307, "8": 3308} { addr := net.JoinHostPort("localhost", strconv.Itoa(port)) t.Run(version, func(t *testing.T) { @@ -58,7 +59,7 @@ func TestMySQL(t *testing.T) { }).FormatDSN()) require.NoError(t, err) defer client.Close() - require.NoError(t, client.Schema.Create(context.Background()), migrate.WithDropColumn(true), migrate.WithDropIndex(true)) + require.NoError(t, client.Schema.Create(context.Background(), migrate.WithDropColumn(true), migrate.WithDropIndex(true))) for _, tt := range tests { name := runtime.FuncForPC(reflect.ValueOf(tt).Pointer()).Name() t.Run(name[strings.LastIndex(name, ".")+1:], func(t *testing.T) { @@ -76,7 +77,7 @@ func TestPostgres(t *testing.T) { client, err := ent.Open(dialect.Postgres, fmt.Sprintf("host=localhost port=%d user=postgres dbname=test password=pass sslmode=disable", port)) require.NoError(t, err) defer client.Close() - require.NoError(t, client.Schema.Create(context.Background()), migrate.WithDropColumn(true), migrate.WithDropIndex(true)) + require.NoError(t, client.Schema.Create(context.Background(), migrate.WithDropColumn(true), migrate.WithDropIndex(true))) for _, tt := range tests { name := runtime.FuncForPC(reflect.ValueOf(tt).Pointer()).Name() t.Run(name[strings.LastIndex(name, ".")+1:], func(t *testing.T) { diff --git a/entc/integration/json/ent/user_update.go b/entc/integration/json/ent/user_update.go index 14b50d565..c18a41108 100644 --- a/entc/integration/json/ent/user_update.go +++ b/entc/integration/json/ent/user_update.go @@ -14,8 +14,10 @@ import ( "net/url" "github.com/facebookincubator/ent/dialect/sql" + "github.com/facebookincubator/ent/dialect/sql/sqlgraph" "github.com/facebookincubator/ent/entc/integration/json/ent/predicate" "github.com/facebookincubator/ent/entc/integration/json/ent/user" + "github.com/facebookincubator/ent/schema/field" ) // UserUpdate is the builder for updating User entities. @@ -148,111 +150,108 @@ func (uu *UserUpdate) ExecX(ctx context.Context) { } func (uu *UserUpdate) sqlSave(ctx context.Context) (n int, err error) { - var ( - builder = sql.Dialect(uu.driver.Dialect()) - selector = builder.Select(user.FieldID).From(builder.Table(user.Table)) - ) - for _, p := range uu.predicates { - p(selector) + spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: user.Table, + Columns: user.Columns, + ID: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: user.FieldID, + }, + }, } - rows := &sql.Rows{} - query, args := selector.Query() - if err = uu.driver.Query(ctx, query, args, rows); err != nil { - return 0, err - } - defer rows.Close() - - var ids []int - for rows.Next() { - var id int - if err := rows.Scan(&id); err != nil { - return 0, fmt.Errorf("ent: failed reading id: %v", err) + if ps := uu.predicates; len(ps) > 0 { + spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } } - ids = append(ids, id) } - if len(ids) == 0 { - return 0, nil - } - - tx, err := uu.driver.Tx(ctx) - if err != nil { - return 0, err - } - var ( - res sql.Result - updater = builder.Update(user.Table) - ) - updater = updater.Where(sql.InInts(user.FieldID, ids...)) if value := uu.url; value != nil { - buf, err := json.Marshal(*value) - if err != nil { - return 0, err - } - updater.Set(user.FieldURL, buf) + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeJSON, + Value: *value, + Column: user.FieldURL, + }) } if uu.clearurl { - updater.SetNull(user.FieldURL) + spec.Fields.Clear = append(spec.Fields.Clear, &sqlgraph.FieldSpec{ + Type: field.TypeJSON, + Column: user.FieldURL, + }) } if value := uu.raw; value != nil { - buf, err := json.Marshal(*value) - if err != nil { - return 0, err - } - updater.Set(user.FieldRaw, buf) + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeJSON, + Value: *value, + Column: user.FieldRaw, + }) } if uu.clearraw { - updater.SetNull(user.FieldRaw) + spec.Fields.Clear = append(spec.Fields.Clear, &sqlgraph.FieldSpec{ + Type: field.TypeJSON, + Column: user.FieldRaw, + }) } if value := uu.dirs; value != nil { - buf, err := json.Marshal(*value) - if err != nil { - return 0, err - } - updater.Set(user.FieldDirs, buf) + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeJSON, + Value: *value, + Column: user.FieldDirs, + }) } if uu.cleardirs { - updater.SetNull(user.FieldDirs) + spec.Fields.Clear = append(spec.Fields.Clear, &sqlgraph.FieldSpec{ + Type: field.TypeJSON, + Column: user.FieldDirs, + }) } if value := uu.ints; value != nil { - buf, err := json.Marshal(*value) - if err != nil { - return 0, err - } - updater.Set(user.FieldInts, buf) + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeJSON, + Value: *value, + Column: user.FieldInts, + }) } if uu.clearints { - updater.SetNull(user.FieldInts) + spec.Fields.Clear = append(spec.Fields.Clear, &sqlgraph.FieldSpec{ + Type: field.TypeJSON, + Column: user.FieldInts, + }) } if value := uu.floats; value != nil { - buf, err := json.Marshal(*value) - if err != nil { - return 0, err - } - updater.Set(user.FieldFloats, buf) + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeJSON, + Value: *value, + Column: user.FieldFloats, + }) } if uu.clearfloats { - updater.SetNull(user.FieldFloats) + spec.Fields.Clear = append(spec.Fields.Clear, &sqlgraph.FieldSpec{ + Type: field.TypeJSON, + Column: user.FieldFloats, + }) } if value := uu.strings; value != nil { - buf, err := json.Marshal(*value) - if err != nil { - return 0, err - } - updater.Set(user.FieldStrings, buf) + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeJSON, + Value: *value, + Column: user.FieldStrings, + }) } if uu.clearstrings { - updater.SetNull(user.FieldStrings) + spec.Fields.Clear = append(spec.Fields.Clear, &sqlgraph.FieldSpec{ + Type: field.TypeJSON, + Column: user.FieldStrings, + }) } - if !updater.Empty() { - query, args := updater.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) + if n, err = sqlgraph.UpdateNodes(ctx, uu.driver, spec); err != nil { + if cerr, ok := isSQLConstraintError(err); ok { + err = cerr } - } - if err = tx.Commit(); err != nil { return 0, err } - return len(ids), nil + return n, nil } // UserUpdateOne is the builder for updating a single User entity. @@ -379,129 +378,169 @@ func (uuo *UserUpdateOne) ExecX(ctx context.Context) { } func (uuo *UserUpdateOne) sqlSave(ctx context.Context) (u *User, err error) { - var ( - builder = sql.Dialect(uuo.driver.Dialect()) - selector = builder.Select(user.Columns...).From(builder.Table(user.Table)) - ) - user.ID(uuo.id)(selector) - rows := &sql.Rows{} - query, args := selector.Query() - if err = uuo.driver.Query(ctx, query, args, rows); err != nil { - return nil, err + spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: user.Table, + Columns: user.Columns, + ID: &sqlgraph.FieldSpec{ + Value: uuo.id, + Type: field.TypeInt, + Column: user.FieldID, + }, + }, } - defer rows.Close() - - var ids []int - for rows.Next() { - var id int - u = &User{config: uuo.config} - if err := u.FromRows(rows); err != nil { - return nil, fmt.Errorf("ent: failed scanning row into User: %v", err) - } - id = u.ID - ids = append(ids, id) - } - switch n := len(ids); { - case n == 0: - return nil, &ErrNotFound{fmt.Sprintf("User with id: %v", uuo.id)} - case n > 1: - return nil, fmt.Errorf("ent: more than one User with the same id: %v", uuo.id) - } - - tx, err := uuo.driver.Tx(ctx) - if err != nil { - return nil, err - } - var ( - res sql.Result - updater = builder.Update(user.Table) - ) - updater = updater.Where(sql.InInts(user.FieldID, ids...)) if value := uuo.url; value != nil { - buf, err := json.Marshal(*value) - if err != nil { - return nil, err - } - updater.Set(user.FieldURL, buf) - u.URL = *value + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeJSON, + Value: *value, + Column: user.FieldURL, + }) } if uuo.clearurl { - var value *url.URL - u.URL = value - updater.SetNull(user.FieldURL) + spec.Fields.Clear = append(spec.Fields.Clear, &sqlgraph.FieldSpec{ + Type: field.TypeJSON, + Column: user.FieldURL, + }) } if value := uuo.raw; value != nil { - buf, err := json.Marshal(*value) - if err != nil { - return nil, err - } - updater.Set(user.FieldRaw, buf) - u.Raw = *value + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeJSON, + Value: *value, + Column: user.FieldRaw, + }) } if uuo.clearraw { - var value json.RawMessage - u.Raw = value - updater.SetNull(user.FieldRaw) + spec.Fields.Clear = append(spec.Fields.Clear, &sqlgraph.FieldSpec{ + Type: field.TypeJSON, + Column: user.FieldRaw, + }) } if value := uuo.dirs; value != nil { - buf, err := json.Marshal(*value) - if err != nil { - return nil, err - } - updater.Set(user.FieldDirs, buf) - u.Dirs = *value + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeJSON, + Value: *value, + Column: user.FieldDirs, + }) } if uuo.cleardirs { - var value []http.Dir - u.Dirs = value - updater.SetNull(user.FieldDirs) + spec.Fields.Clear = append(spec.Fields.Clear, &sqlgraph.FieldSpec{ + Type: field.TypeJSON, + Column: user.FieldDirs, + }) } if value := uuo.ints; value != nil { - buf, err := json.Marshal(*value) - if err != nil { - return nil, err - } - updater.Set(user.FieldInts, buf) - u.Ints = *value + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeJSON, + Value: *value, + Column: user.FieldInts, + }) } if uuo.clearints { - var value []int - u.Ints = value - updater.SetNull(user.FieldInts) + spec.Fields.Clear = append(spec.Fields.Clear, &sqlgraph.FieldSpec{ + Type: field.TypeJSON, + Column: user.FieldInts, + }) } if value := uuo.floats; value != nil { - buf, err := json.Marshal(*value) - if err != nil { - return nil, err - } - updater.Set(user.FieldFloats, buf) - u.Floats = *value + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeJSON, + Value: *value, + Column: user.FieldFloats, + }) } if uuo.clearfloats { - var value []float64 - u.Floats = value - updater.SetNull(user.FieldFloats) + spec.Fields.Clear = append(spec.Fields.Clear, &sqlgraph.FieldSpec{ + Type: field.TypeJSON, + Column: user.FieldFloats, + }) } if value := uuo.strings; value != nil { - buf, err := json.Marshal(*value) - if err != nil { - return nil, err - } - updater.Set(user.FieldStrings, buf) - u.Strings = *value + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeJSON, + Value: *value, + Column: user.FieldStrings, + }) } if uuo.clearstrings { - var value []string - u.Strings = value - updater.SetNull(user.FieldStrings) + spec.Fields.Clear = append(spec.Fields.Clear, &sqlgraph.FieldSpec{ + Type: field.TypeJSON, + Column: user.FieldStrings, + }) } - if !updater.Empty() { - query, args := updater.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) + u = &User{config: uuo.config} + spec.ScanTypes = []interface{}{ + &sql.NullInt64{}, + &[]byte{}, + &[]byte{}, + &[]byte{}, + &[]byte{}, + &[]byte{}, + &[]byte{}, + } + spec.Assign = func(values ...interface{}) error { + if m, n := len(values), len(spec.ScanTypes); m != n { + return fmt.Errorf("mismatch number of scan values: %d != %d", m, n) } + value, ok := values[0].(*sql.NullInt64) + if !ok { + return fmt.Errorf("unexpected type %T for field id", value) + } + u.ID = int(value.Int64) + values = values[1:] + + if value, ok := values[0].(*[]byte); !ok { + return fmt.Errorf("unexpected type %T for field url", values[0]) + } else if value != nil && len(*value) > 0 { + if err := json.Unmarshal(*value, &u.URL); err != nil { + return fmt.Errorf("unmarshal field url: %v", err) + } + } + + if value, ok := values[1].(*[]byte); !ok { + return fmt.Errorf("unexpected type %T for field raw", values[1]) + } else if value != nil && len(*value) > 0 { + if err := json.Unmarshal(*value, &u.Raw); err != nil { + return fmt.Errorf("unmarshal field raw: %v", err) + } + } + + if value, ok := values[2].(*[]byte); !ok { + return fmt.Errorf("unexpected type %T for field dirs", values[2]) + } else if value != nil && len(*value) > 0 { + if err := json.Unmarshal(*value, &u.Dirs); err != nil { + return fmt.Errorf("unmarshal field dirs: %v", err) + } + } + + if value, ok := values[3].(*[]byte); !ok { + return fmt.Errorf("unexpected type %T for field ints", values[3]) + } else if value != nil && len(*value) > 0 { + if err := json.Unmarshal(*value, &u.Ints); err != nil { + return fmt.Errorf("unmarshal field ints: %v", err) + } + } + + if value, ok := values[4].(*[]byte); !ok { + return fmt.Errorf("unexpected type %T for field floats", values[4]) + } else if value != nil && len(*value) > 0 { + if err := json.Unmarshal(*value, &u.Floats); err != nil { + return fmt.Errorf("unmarshal field floats: %v", err) + } + } + + if value, ok := values[5].(*[]byte); !ok { + return fmt.Errorf("unexpected type %T for field strings", values[5]) + } else if value != nil && len(*value) > 0 { + if err := json.Unmarshal(*value, &u.Strings); err != nil { + return fmt.Errorf("unmarshal field strings: %v", err) + } + } + return nil } - if err = tx.Commit(); err != nil { + if err = sqlgraph.UpdateNode(ctx, uuo.driver, spec); err != nil { + if cerr, ok := isSQLConstraintError(err); ok { + err = cerr + } return nil, err } return u, nil diff --git a/entc/integration/migrate/entv1/user_update.go b/entc/integration/migrate/entv1/user_update.go index a3bad0f01..453ad5129 100644 --- a/entc/integration/migrate/entv1/user_update.go +++ b/entc/integration/migrate/entv1/user_update.go @@ -11,8 +11,10 @@ import ( "fmt" "github.com/facebookincubator/ent/dialect/sql" + "github.com/facebookincubator/ent/dialect/sql/sqlgraph" "github.com/facebookincubator/ent/entc/integration/migrate/entv1/predicate" "github.com/facebookincubator/ent/entc/integration/migrate/entv1/user" + "github.com/facebookincubator/ent/schema/field" ) // UserUpdate is the builder for updating User entities. @@ -182,87 +184,110 @@ func (uu *UserUpdate) ExecX(ctx context.Context) { } func (uu *UserUpdate) sqlSave(ctx context.Context) (n int, err error) { - var ( - builder = sql.Dialect(uu.driver.Dialect()) - selector = builder.Select(user.FieldID).From(builder.Table(user.Table)) - ) - for _, p := range uu.predicates { - p(selector) + spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: user.Table, + Columns: user.Columns, + ID: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: user.FieldID, + }, + }, } - rows := &sql.Rows{} - query, args := selector.Query() - if err = uu.driver.Query(ctx, query, args, rows); err != nil { - return 0, err - } - defer rows.Close() - - var ids []int - for rows.Next() { - var id int - if err := rows.Scan(&id); err != nil { - return 0, fmt.Errorf("entv1: failed reading id: %v", err) + if ps := uu.predicates; len(ps) > 0 { + spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } } - ids = append(ids, id) } - if len(ids) == 0 { - return 0, nil - } - - tx, err := uu.driver.Tx(ctx) - if err != nil { - return 0, err - } - var ( - res sql.Result - updater = builder.Update(user.Table) - ) - updater = updater.Where(sql.InInts(user.FieldID, ids...)) if value := uu.age; value != nil { - updater.Set(user.FieldAge, *value) + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeInt32, + Value: *value, + Column: user.FieldAge, + }) } if value := uu.addage; value != nil { - updater.Add(user.FieldAge, *value) + spec.Fields.Add = append(spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.TypeInt32, + Value: *value, + Column: user.FieldAge, + }) } if value := uu.name; value != nil { - updater.Set(user.FieldName, *value) + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: *value, + Column: user.FieldName, + }) } if value := uu.nickname; value != nil { - updater.Set(user.FieldNickname, *value) + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: *value, + Column: user.FieldNickname, + }) } if value := uu.address; value != nil { - updater.Set(user.FieldAddress, *value) + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: *value, + Column: user.FieldAddress, + }) } if uu.clearaddress { - updater.SetNull(user.FieldAddress) + spec.Fields.Clear = append(spec.Fields.Clear, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: user.FieldAddress, + }) } if value := uu.renamed; value != nil { - updater.Set(user.FieldRenamed, *value) + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: *value, + Column: user.FieldRenamed, + }) } if uu.clearrenamed { - updater.SetNull(user.FieldRenamed) + spec.Fields.Clear = append(spec.Fields.Clear, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: user.FieldRenamed, + }) } if value := uu.blob; value != nil { - updater.Set(user.FieldBlob, *value) + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeBytes, + Value: *value, + Column: user.FieldBlob, + }) } if uu.clearblob { - updater.SetNull(user.FieldBlob) + spec.Fields.Clear = append(spec.Fields.Clear, &sqlgraph.FieldSpec{ + Type: field.TypeBytes, + Column: user.FieldBlob, + }) } if value := uu.state; value != nil { - updater.Set(user.FieldState, *value) + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeEnum, + Value: *value, + Column: user.FieldState, + }) } if uu.clearstate { - updater.SetNull(user.FieldState) + spec.Fields.Clear = append(spec.Fields.Clear, &sqlgraph.FieldSpec{ + Type: field.TypeEnum, + Column: user.FieldState, + }) } - if !updater.Empty() { - query, args := updater.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) + if n, err = sqlgraph.UpdateNodes(ctx, uu.driver, spec); err != nil { + if cerr, ok := isSQLConstraintError(err); ok { + err = cerr } - } - if err = tx.Commit(); err != nil { return 0, err } - return len(ids), nil + return n, nil } // UserUpdateOne is the builder for updating a single User entity. @@ -426,103 +451,159 @@ func (uuo *UserUpdateOne) ExecX(ctx context.Context) { } func (uuo *UserUpdateOne) sqlSave(ctx context.Context) (u *User, err error) { - var ( - builder = sql.Dialect(uuo.driver.Dialect()) - selector = builder.Select(user.Columns...).From(builder.Table(user.Table)) - ) - user.ID(uuo.id)(selector) - rows := &sql.Rows{} - query, args := selector.Query() - if err = uuo.driver.Query(ctx, query, args, rows); err != nil { - return nil, err + spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: user.Table, + Columns: user.Columns, + ID: &sqlgraph.FieldSpec{ + Value: uuo.id, + Type: field.TypeInt, + Column: user.FieldID, + }, + }, } - defer rows.Close() - - var ids []int - for rows.Next() { - var id int - u = &User{config: uuo.config} - if err := u.FromRows(rows); err != nil { - return nil, fmt.Errorf("entv1: failed scanning row into User: %v", err) - } - id = u.ID - ids = append(ids, id) - } - switch n := len(ids); { - case n == 0: - return nil, &ErrNotFound{fmt.Sprintf("User with id: %v", uuo.id)} - case n > 1: - return nil, fmt.Errorf("entv1: more than one User with the same id: %v", uuo.id) - } - - tx, err := uuo.driver.Tx(ctx) - if err != nil { - return nil, err - } - var ( - res sql.Result - updater = builder.Update(user.Table) - ) - updater = updater.Where(sql.InInts(user.FieldID, ids...)) if value := uuo.age; value != nil { - updater.Set(user.FieldAge, *value) - u.Age = *value + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeInt32, + Value: *value, + Column: user.FieldAge, + }) } if value := uuo.addage; value != nil { - updater.Add(user.FieldAge, *value) - u.Age += *value + spec.Fields.Add = append(spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.TypeInt32, + Value: *value, + Column: user.FieldAge, + }) } if value := uuo.name; value != nil { - updater.Set(user.FieldName, *value) - u.Name = *value + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: *value, + Column: user.FieldName, + }) } if value := uuo.nickname; value != nil { - updater.Set(user.FieldNickname, *value) - u.Nickname = *value + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: *value, + Column: user.FieldNickname, + }) } if value := uuo.address; value != nil { - updater.Set(user.FieldAddress, *value) - u.Address = *value + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: *value, + Column: user.FieldAddress, + }) } if uuo.clearaddress { - var value string - u.Address = value - updater.SetNull(user.FieldAddress) + spec.Fields.Clear = append(spec.Fields.Clear, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: user.FieldAddress, + }) } if value := uuo.renamed; value != nil { - updater.Set(user.FieldRenamed, *value) - u.Renamed = *value + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: *value, + Column: user.FieldRenamed, + }) } if uuo.clearrenamed { - var value string - u.Renamed = value - updater.SetNull(user.FieldRenamed) + spec.Fields.Clear = append(spec.Fields.Clear, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: user.FieldRenamed, + }) } if value := uuo.blob; value != nil { - updater.Set(user.FieldBlob, *value) - u.Blob = *value + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeBytes, + Value: *value, + Column: user.FieldBlob, + }) } if uuo.clearblob { - var value []byte - u.Blob = value - updater.SetNull(user.FieldBlob) + spec.Fields.Clear = append(spec.Fields.Clear, &sqlgraph.FieldSpec{ + Type: field.TypeBytes, + Column: user.FieldBlob, + }) } if value := uuo.state; value != nil { - updater.Set(user.FieldState, *value) - u.State = *value + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeEnum, + Value: *value, + Column: user.FieldState, + }) } if uuo.clearstate { - var value user.State - u.State = value - updater.SetNull(user.FieldState) + spec.Fields.Clear = append(spec.Fields.Clear, &sqlgraph.FieldSpec{ + Type: field.TypeEnum, + Column: user.FieldState, + }) } - if !updater.Empty() { - query, args := updater.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) + u = &User{config: uuo.config} + spec.ScanTypes = []interface{}{ + &sql.NullInt64{}, + &sql.NullInt64{}, + &sql.NullString{}, + &sql.NullString{}, + &sql.NullString{}, + &sql.NullString{}, + &[]byte{}, + &sql.NullString{}, + } + spec.Assign = func(values ...interface{}) error { + if m, n := len(values), len(spec.ScanTypes); m != n { + return fmt.Errorf("mismatch number of scan values: %d != %d", m, n) } + value, ok := values[0].(*sql.NullInt64) + if !ok { + return fmt.Errorf("unexpected type %T for field id", value) + } + u.ID = int(value.Int64) + values = values[1:] + if value, ok := values[0].(*sql.NullInt64); !ok { + return fmt.Errorf("unexpected type %T for field age", values[0]) + } else if value.Valid { + u.Age = int32(value.Int64) + } + if value, ok := values[1].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field name", values[1]) + } else if value.Valid { + u.Name = value.String + } + if value, ok := values[2].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field nickname", values[2]) + } else if value.Valid { + u.Nickname = value.String + } + if value, ok := values[3].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field address", values[3]) + } else if value.Valid { + u.Address = value.String + } + if value, ok := values[4].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field renamed", values[4]) + } else if value.Valid { + u.Renamed = value.String + } + if value, ok := values[5].(*[]byte); !ok { + return fmt.Errorf("unexpected type %T for field blob", values[5]) + } else if value != nil { + u.Blob = *value + } + if value, ok := values[6].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field state", values[6]) + } else if value.Valid { + u.State = user.State(value.String) + } + return nil } - if err = tx.Commit(); err != nil { + if err = sqlgraph.UpdateNode(ctx, uuo.driver, spec); err != nil { + if cerr, ok := isSQLConstraintError(err); ok { + err = cerr + } return nil, err } return u, nil diff --git a/entc/integration/migrate/entv2/group_update.go b/entc/integration/migrate/entv2/group_update.go index 6f431b056..fe7f986de 100644 --- a/entc/integration/migrate/entv2/group_update.go +++ b/entc/integration/migrate/entv2/group_update.go @@ -11,8 +11,10 @@ import ( "fmt" "github.com/facebookincubator/ent/dialect/sql" + "github.com/facebookincubator/ent/dialect/sql/sqlgraph" "github.com/facebookincubator/ent/entc/integration/migrate/entv2/group" "github.com/facebookincubator/ent/entc/integration/migrate/entv2/predicate" + "github.com/facebookincubator/ent/schema/field" ) // GroupUpdate is the builder for updating Group entities. @@ -55,40 +57,30 @@ func (gu *GroupUpdate) ExecX(ctx context.Context) { } func (gu *GroupUpdate) sqlSave(ctx context.Context) (n int, err error) { - var ( - builder = sql.Dialect(gu.driver.Dialect()) - selector = builder.Select(group.FieldID).From(builder.Table(group.Table)) - ) - for _, p := range gu.predicates { - p(selector) + spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: group.Table, + Columns: group.Columns, + ID: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: group.FieldID, + }, + }, } - rows := &sql.Rows{} - query, args := selector.Query() - if err = gu.driver.Query(ctx, query, args, rows); err != nil { - return 0, err - } - defer rows.Close() - - var ids []int - for rows.Next() { - var id int - if err := rows.Scan(&id); err != nil { - return 0, fmt.Errorf("entv2: failed reading id: %v", err) + if ps := gu.predicates; len(ps) > 0 { + spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } } - ids = append(ids, id) } - if len(ids) == 0 { - return 0, nil - } - - tx, err := gu.driver.Tx(ctx) - if err != nil { + if n, err = sqlgraph.UpdateNodes(ctx, gu.driver, spec); err != nil { + if cerr, ok := isSQLConstraintError(err); ok { + err = cerr + } return 0, err } - if err = tx.Commit(); err != nil { - return 0, err - } - return len(ids), nil + return n, nil } // GroupUpdateOne is the builder for updating a single Group entity. @@ -125,40 +117,37 @@ func (guo *GroupUpdateOne) ExecX(ctx context.Context) { } func (guo *GroupUpdateOne) sqlSave(ctx context.Context) (gr *Group, err error) { - var ( - builder = sql.Dialect(guo.driver.Dialect()) - selector = builder.Select(group.Columns...).From(builder.Table(group.Table)) - ) - group.ID(guo.id)(selector) - rows := &sql.Rows{} - query, args := selector.Query() - if err = guo.driver.Query(ctx, query, args, rows); err != nil { - return nil, err + spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: group.Table, + Columns: group.Columns, + ID: &sqlgraph.FieldSpec{ + Value: guo.id, + Type: field.TypeInt, + Column: group.FieldID, + }, + }, } - defer rows.Close() - - var ids []int - for rows.Next() { - var id int - gr = &Group{config: guo.config} - if err := gr.FromRows(rows); err != nil { - return nil, fmt.Errorf("entv2: failed scanning row into Group: %v", err) + gr = &Group{config: guo.config} + spec.ScanTypes = []interface{}{ + &sql.NullInt64{}, + } + spec.Assign = func(values ...interface{}) error { + if m, n := len(values), len(spec.ScanTypes); m != n { + return fmt.Errorf("mismatch number of scan values: %d != %d", m, n) } - id = gr.ID - ids = append(ids, id) + value, ok := values[0].(*sql.NullInt64) + if !ok { + return fmt.Errorf("unexpected type %T for field id", value) + } + gr.ID = int(value.Int64) + values = values[1:] + return nil } - switch n := len(ids); { - case n == 0: - return nil, &ErrNotFound{fmt.Sprintf("Group with id: %v", guo.id)} - case n > 1: - return nil, fmt.Errorf("entv2: more than one Group with the same id: %v", guo.id) - } - - tx, err := guo.driver.Tx(ctx) - if err != nil { - return nil, err - } - if err = tx.Commit(); err != nil { + if err = sqlgraph.UpdateNode(ctx, guo.driver, spec); err != nil { + if cerr, ok := isSQLConstraintError(err); ok { + err = cerr + } return nil, err } return gr, nil diff --git a/entc/integration/migrate/entv2/pet_update.go b/entc/integration/migrate/entv2/pet_update.go index c02b759b6..bcf346909 100644 --- a/entc/integration/migrate/entv2/pet_update.go +++ b/entc/integration/migrate/entv2/pet_update.go @@ -11,8 +11,10 @@ import ( "fmt" "github.com/facebookincubator/ent/dialect/sql" + "github.com/facebookincubator/ent/dialect/sql/sqlgraph" "github.com/facebookincubator/ent/entc/integration/migrate/entv2/pet" "github.com/facebookincubator/ent/entc/integration/migrate/entv2/predicate" + "github.com/facebookincubator/ent/schema/field" ) // PetUpdate is the builder for updating Pet entities. @@ -55,40 +57,30 @@ func (pu *PetUpdate) ExecX(ctx context.Context) { } func (pu *PetUpdate) sqlSave(ctx context.Context) (n int, err error) { - var ( - builder = sql.Dialect(pu.driver.Dialect()) - selector = builder.Select(pet.FieldID).From(builder.Table(pet.Table)) - ) - for _, p := range pu.predicates { - p(selector) + spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: pet.Table, + Columns: pet.Columns, + ID: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: pet.FieldID, + }, + }, } - rows := &sql.Rows{} - query, args := selector.Query() - if err = pu.driver.Query(ctx, query, args, rows); err != nil { - return 0, err - } - defer rows.Close() - - var ids []int - for rows.Next() { - var id int - if err := rows.Scan(&id); err != nil { - return 0, fmt.Errorf("entv2: failed reading id: %v", err) + if ps := pu.predicates; len(ps) > 0 { + spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } } - ids = append(ids, id) } - if len(ids) == 0 { - return 0, nil - } - - tx, err := pu.driver.Tx(ctx) - if err != nil { + if n, err = sqlgraph.UpdateNodes(ctx, pu.driver, spec); err != nil { + if cerr, ok := isSQLConstraintError(err); ok { + err = cerr + } return 0, err } - if err = tx.Commit(); err != nil { - return 0, err - } - return len(ids), nil + return n, nil } // PetUpdateOne is the builder for updating a single Pet entity. @@ -125,40 +117,37 @@ func (puo *PetUpdateOne) ExecX(ctx context.Context) { } func (puo *PetUpdateOne) sqlSave(ctx context.Context) (pe *Pet, err error) { - var ( - builder = sql.Dialect(puo.driver.Dialect()) - selector = builder.Select(pet.Columns...).From(builder.Table(pet.Table)) - ) - pet.ID(puo.id)(selector) - rows := &sql.Rows{} - query, args := selector.Query() - if err = puo.driver.Query(ctx, query, args, rows); err != nil { - return nil, err + spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: pet.Table, + Columns: pet.Columns, + ID: &sqlgraph.FieldSpec{ + Value: puo.id, + Type: field.TypeInt, + Column: pet.FieldID, + }, + }, } - defer rows.Close() - - var ids []int - for rows.Next() { - var id int - pe = &Pet{config: puo.config} - if err := pe.FromRows(rows); err != nil { - return nil, fmt.Errorf("entv2: failed scanning row into Pet: %v", err) + pe = &Pet{config: puo.config} + spec.ScanTypes = []interface{}{ + &sql.NullInt64{}, + } + spec.Assign = func(values ...interface{}) error { + if m, n := len(values), len(spec.ScanTypes); m != n { + return fmt.Errorf("mismatch number of scan values: %d != %d", m, n) } - id = pe.ID - ids = append(ids, id) + value, ok := values[0].(*sql.NullInt64) + if !ok { + return fmt.Errorf("unexpected type %T for field id", value) + } + pe.ID = int(value.Int64) + values = values[1:] + return nil } - switch n := len(ids); { - case n == 0: - return nil, &ErrNotFound{fmt.Sprintf("Pet with id: %v", puo.id)} - case n > 1: - return nil, fmt.Errorf("entv2: more than one Pet with the same id: %v", puo.id) - } - - tx, err := puo.driver.Tx(ctx) - if err != nil { - return nil, err - } - if err = tx.Commit(); err != nil { + if err = sqlgraph.UpdateNode(ctx, puo.driver, spec); err != nil { + if cerr, ok := isSQLConstraintError(err); ok { + err = cerr + } return nil, err } return pe, nil diff --git a/entc/integration/migrate/entv2/user_update.go b/entc/integration/migrate/entv2/user_update.go index c969f27da..c4876b34e 100644 --- a/entc/integration/migrate/entv2/user_update.go +++ b/entc/integration/migrate/entv2/user_update.go @@ -11,8 +11,10 @@ import ( "fmt" "github.com/facebookincubator/ent/dialect/sql" + "github.com/facebookincubator/ent/dialect/sql/sqlgraph" "github.com/facebookincubator/ent/entc/integration/migrate/entv2/predicate" "github.com/facebookincubator/ent/entc/integration/migrate/entv2/user" + "github.com/facebookincubator/ent/schema/field" ) // UserUpdate is the builder for updating User entities. @@ -199,93 +201,124 @@ func (uu *UserUpdate) ExecX(ctx context.Context) { } func (uu *UserUpdate) sqlSave(ctx context.Context) (n int, err error) { - var ( - builder = sql.Dialect(uu.driver.Dialect()) - selector = builder.Select(user.FieldID).From(builder.Table(user.Table)) - ) - for _, p := range uu.predicates { - p(selector) + spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: user.Table, + Columns: user.Columns, + ID: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: user.FieldID, + }, + }, } - rows := &sql.Rows{} - query, args := selector.Query() - if err = uu.driver.Query(ctx, query, args, rows); err != nil { - return 0, err - } - defer rows.Close() - - var ids []int - for rows.Next() { - var id int - if err := rows.Scan(&id); err != nil { - return 0, fmt.Errorf("entv2: failed reading id: %v", err) + if ps := uu.predicates; len(ps) > 0 { + spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } } - ids = append(ids, id) } - if len(ids) == 0 { - return 0, nil - } - - tx, err := uu.driver.Tx(ctx) - if err != nil { - return 0, err - } - var ( - res sql.Result - updater = builder.Update(user.Table) - ) - updater = updater.Where(sql.InInts(user.FieldID, ids...)) if value := uu.age; value != nil { - updater.Set(user.FieldAge, *value) + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: *value, + Column: user.FieldAge, + }) } if value := uu.addage; value != nil { - updater.Add(user.FieldAge, *value) + spec.Fields.Add = append(spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: *value, + Column: user.FieldAge, + }) } if value := uu.name; value != nil { - updater.Set(user.FieldName, *value) + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: *value, + Column: user.FieldName, + }) } if value := uu.nickname; value != nil { - updater.Set(user.FieldNickname, *value) + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: *value, + Column: user.FieldNickname, + }) } if value := uu.phone; value != nil { - updater.Set(user.FieldPhone, *value) + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: *value, + Column: user.FieldPhone, + }) } if value := uu.buffer; value != nil { - updater.Set(user.FieldBuffer, *value) + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeBytes, + Value: *value, + Column: user.FieldBuffer, + }) } if uu.clearbuffer { - updater.SetNull(user.FieldBuffer) + spec.Fields.Clear = append(spec.Fields.Clear, &sqlgraph.FieldSpec{ + Type: field.TypeBytes, + Column: user.FieldBuffer, + }) } if value := uu.title; value != nil { - updater.Set(user.FieldTitle, *value) + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: *value, + Column: user.FieldTitle, + }) } if value := uu.new_name; value != nil { - updater.Set(user.FieldNewName, *value) + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: *value, + Column: user.FieldNewName, + }) } if uu.clearnew_name { - updater.SetNull(user.FieldNewName) + spec.Fields.Clear = append(spec.Fields.Clear, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: user.FieldNewName, + }) } if value := uu.blob; value != nil { - updater.Set(user.FieldBlob, *value) + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeBytes, + Value: *value, + Column: user.FieldBlob, + }) } if uu.clearblob { - updater.SetNull(user.FieldBlob) + spec.Fields.Clear = append(spec.Fields.Clear, &sqlgraph.FieldSpec{ + Type: field.TypeBytes, + Column: user.FieldBlob, + }) } if value := uu.state; value != nil { - updater.Set(user.FieldState, *value) + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeEnum, + Value: *value, + Column: user.FieldState, + }) } if uu.clearstate { - updater.SetNull(user.FieldState) + spec.Fields.Clear = append(spec.Fields.Clear, &sqlgraph.FieldSpec{ + Type: field.TypeEnum, + Column: user.FieldState, + }) } - if !updater.Empty() { - query, args := updater.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) + if n, err = sqlgraph.UpdateNodes(ctx, uu.driver, spec); err != nil { + if cerr, ok := isSQLConstraintError(err); ok { + err = cerr } - } - if err = tx.Commit(); err != nil { return 0, err } - return len(ids), nil + return n, nil } // UserUpdateOne is the builder for updating a single User entity. @@ -466,111 +499,185 @@ func (uuo *UserUpdateOne) ExecX(ctx context.Context) { } func (uuo *UserUpdateOne) sqlSave(ctx context.Context) (u *User, err error) { - var ( - builder = sql.Dialect(uuo.driver.Dialect()) - selector = builder.Select(user.Columns...).From(builder.Table(user.Table)) - ) - user.ID(uuo.id)(selector) - rows := &sql.Rows{} - query, args := selector.Query() - if err = uuo.driver.Query(ctx, query, args, rows); err != nil { - return nil, err + spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: user.Table, + Columns: user.Columns, + ID: &sqlgraph.FieldSpec{ + Value: uuo.id, + Type: field.TypeInt, + Column: user.FieldID, + }, + }, } - defer rows.Close() - - var ids []int - for rows.Next() { - var id int - u = &User{config: uuo.config} - if err := u.FromRows(rows); err != nil { - return nil, fmt.Errorf("entv2: failed scanning row into User: %v", err) - } - id = u.ID - ids = append(ids, id) - } - switch n := len(ids); { - case n == 0: - return nil, &ErrNotFound{fmt.Sprintf("User with id: %v", uuo.id)} - case n > 1: - return nil, fmt.Errorf("entv2: more than one User with the same id: %v", uuo.id) - } - - tx, err := uuo.driver.Tx(ctx) - if err != nil { - return nil, err - } - var ( - res sql.Result - updater = builder.Update(user.Table) - ) - updater = updater.Where(sql.InInts(user.FieldID, ids...)) if value := uuo.age; value != nil { - updater.Set(user.FieldAge, *value) - u.Age = *value + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: *value, + Column: user.FieldAge, + }) } if value := uuo.addage; value != nil { - updater.Add(user.FieldAge, *value) - u.Age += *value + spec.Fields.Add = append(spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: *value, + Column: user.FieldAge, + }) } if value := uuo.name; value != nil { - updater.Set(user.FieldName, *value) - u.Name = *value + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: *value, + Column: user.FieldName, + }) } if value := uuo.nickname; value != nil { - updater.Set(user.FieldNickname, *value) - u.Nickname = *value + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: *value, + Column: user.FieldNickname, + }) } if value := uuo.phone; value != nil { - updater.Set(user.FieldPhone, *value) - u.Phone = *value + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: *value, + Column: user.FieldPhone, + }) } if value := uuo.buffer; value != nil { - updater.Set(user.FieldBuffer, *value) - u.Buffer = *value + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeBytes, + Value: *value, + Column: user.FieldBuffer, + }) } if uuo.clearbuffer { - var value []byte - u.Buffer = value - updater.SetNull(user.FieldBuffer) + spec.Fields.Clear = append(spec.Fields.Clear, &sqlgraph.FieldSpec{ + Type: field.TypeBytes, + Column: user.FieldBuffer, + }) } if value := uuo.title; value != nil { - updater.Set(user.FieldTitle, *value) - u.Title = *value + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: *value, + Column: user.FieldTitle, + }) } if value := uuo.new_name; value != nil { - updater.Set(user.FieldNewName, *value) - u.NewName = *value + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: *value, + Column: user.FieldNewName, + }) } if uuo.clearnew_name { - var value string - u.NewName = value - updater.SetNull(user.FieldNewName) + spec.Fields.Clear = append(spec.Fields.Clear, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: user.FieldNewName, + }) } if value := uuo.blob; value != nil { - updater.Set(user.FieldBlob, *value) - u.Blob = *value + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeBytes, + Value: *value, + Column: user.FieldBlob, + }) } if uuo.clearblob { - var value []byte - u.Blob = value - updater.SetNull(user.FieldBlob) + spec.Fields.Clear = append(spec.Fields.Clear, &sqlgraph.FieldSpec{ + Type: field.TypeBytes, + Column: user.FieldBlob, + }) } if value := uuo.state; value != nil { - updater.Set(user.FieldState, *value) - u.State = *value + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeEnum, + Value: *value, + Column: user.FieldState, + }) } if uuo.clearstate { - var value user.State - u.State = value - updater.SetNull(user.FieldState) + spec.Fields.Clear = append(spec.Fields.Clear, &sqlgraph.FieldSpec{ + Type: field.TypeEnum, + Column: user.FieldState, + }) } - if !updater.Empty() { - query, args := updater.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) + u = &User{config: uuo.config} + spec.ScanTypes = []interface{}{ + &sql.NullInt64{}, + &sql.NullInt64{}, + &sql.NullString{}, + &sql.NullString{}, + &sql.NullString{}, + &[]byte{}, + &sql.NullString{}, + &sql.NullString{}, + &[]byte{}, + &sql.NullString{}, + } + spec.Assign = func(values ...interface{}) error { + if m, n := len(values), len(spec.ScanTypes); m != n { + return fmt.Errorf("mismatch number of scan values: %d != %d", m, n) } + value, ok := values[0].(*sql.NullInt64) + if !ok { + return fmt.Errorf("unexpected type %T for field id", value) + } + u.ID = int(value.Int64) + values = values[1:] + if value, ok := values[0].(*sql.NullInt64); !ok { + return fmt.Errorf("unexpected type %T for field age", values[0]) + } else if value.Valid { + u.Age = int(value.Int64) + } + if value, ok := values[1].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field name", values[1]) + } else if value.Valid { + u.Name = value.String + } + if value, ok := values[2].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field nickname", values[2]) + } else if value.Valid { + u.Nickname = value.String + } + if value, ok := values[3].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field phone", values[3]) + } else if value.Valid { + u.Phone = value.String + } + if value, ok := values[4].(*[]byte); !ok { + return fmt.Errorf("unexpected type %T for field buffer", values[4]) + } else if value != nil { + u.Buffer = *value + } + if value, ok := values[5].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field title", values[5]) + } else if value.Valid { + u.Title = value.String + } + if value, ok := values[6].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field new_name", values[6]) + } else if value.Valid { + u.NewName = value.String + } + if value, ok := values[7].(*[]byte); !ok { + return fmt.Errorf("unexpected type %T for field blob", values[7]) + } else if value != nil { + u.Blob = *value + } + if value, ok := values[8].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field state", values[8]) + } else if value.Valid { + u.State = user.State(value.String) + } + return nil } - if err = tx.Commit(); err != nil { + if err = sqlgraph.UpdateNode(ctx, uuo.driver, spec); err != nil { + if cerr, ok := isSQLConstraintError(err); ok { + err = cerr + } return nil, err } return u, nil diff --git a/entc/integration/template/ent/group_update.go b/entc/integration/template/ent/group_update.go index 9e1327431..c40e3c40a 100644 --- a/entc/integration/template/ent/group_update.go +++ b/entc/integration/template/ent/group_update.go @@ -11,8 +11,10 @@ import ( "fmt" "github.com/facebookincubator/ent/dialect/sql" + "github.com/facebookincubator/ent/dialect/sql/sqlgraph" "github.com/facebookincubator/ent/entc/integration/template/ent/group" "github.com/facebookincubator/ent/entc/integration/template/ent/predicate" + "github.com/facebookincubator/ent/schema/field" ) // GroupUpdate is the builder for updating Group entities. @@ -74,57 +76,44 @@ func (gu *GroupUpdate) ExecX(ctx context.Context) { } func (gu *GroupUpdate) sqlSave(ctx context.Context) (n int, err error) { - var ( - builder = sql.Dialect(gu.driver.Dialect()) - selector = builder.Select(group.FieldID).From(builder.Table(group.Table)) - ) - for _, p := range gu.predicates { - p(selector) + spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: group.Table, + Columns: group.Columns, + ID: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: group.FieldID, + }, + }, } - rows := &sql.Rows{} - query, args := selector.Query() - if err = gu.driver.Query(ctx, query, args, rows); err != nil { - return 0, err - } - defer rows.Close() - - var ids []int - for rows.Next() { - var id int - if err := rows.Scan(&id); err != nil { - return 0, fmt.Errorf("ent: failed reading id: %v", err) + if ps := gu.predicates; len(ps) > 0 { + spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } } - ids = append(ids, id) } - if len(ids) == 0 { - return 0, nil - } - - tx, err := gu.driver.Tx(ctx) - if err != nil { - return 0, err - } - var ( - res sql.Result - updater = builder.Update(group.Table) - ) - updater = updater.Where(sql.InInts(group.FieldID, ids...)) if value := gu.max_users; value != nil { - updater.Set(group.FieldMaxUsers, *value) + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: *value, + Column: group.FieldMaxUsers, + }) } if value := gu.addmax_users; value != nil { - updater.Add(group.FieldMaxUsers, *value) + spec.Fields.Add = append(spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: *value, + Column: group.FieldMaxUsers, + }) } - if !updater.Empty() { - query, args := updater.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) + if n, err = sqlgraph.UpdateNodes(ctx, gu.driver, spec); err != nil { + if cerr, ok := isSQLConstraintError(err); ok { + err = cerr } - } - if err = tx.Commit(); err != nil { return 0, err } - return len(ids), nil + return n, nil } // GroupUpdateOne is the builder for updating a single Group entity. @@ -180,59 +169,57 @@ func (guo *GroupUpdateOne) ExecX(ctx context.Context) { } func (guo *GroupUpdateOne) sqlSave(ctx context.Context) (gr *Group, err error) { - var ( - builder = sql.Dialect(guo.driver.Dialect()) - selector = builder.Select(group.Columns...).From(builder.Table(group.Table)) - ) - group.ID(guo.id)(selector) - rows := &sql.Rows{} - query, args := selector.Query() - if err = guo.driver.Query(ctx, query, args, rows); err != nil { - return nil, err + spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: group.Table, + Columns: group.Columns, + ID: &sqlgraph.FieldSpec{ + Value: guo.id, + Type: field.TypeInt, + Column: group.FieldID, + }, + }, } - defer rows.Close() - - var ids []int - for rows.Next() { - var id int - gr = &Group{config: guo.config} - if err := gr.FromRows(rows); err != nil { - return nil, fmt.Errorf("ent: failed scanning row into Group: %v", err) - } - id = gr.ID - ids = append(ids, id) - } - switch n := len(ids); { - case n == 0: - return nil, &ErrNotFound{fmt.Sprintf("Group with id: %v", guo.id)} - case n > 1: - return nil, fmt.Errorf("ent: more than one Group with the same id: %v", guo.id) - } - - tx, err := guo.driver.Tx(ctx) - if err != nil { - return nil, err - } - var ( - res sql.Result - updater = builder.Update(group.Table) - ) - updater = updater.Where(sql.InInts(group.FieldID, ids...)) if value := guo.max_users; value != nil { - updater.Set(group.FieldMaxUsers, *value) - gr.MaxUsers = *value + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: *value, + Column: group.FieldMaxUsers, + }) } if value := guo.addmax_users; value != nil { - updater.Add(group.FieldMaxUsers, *value) - gr.MaxUsers += *value + spec.Fields.Add = append(spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: *value, + Column: group.FieldMaxUsers, + }) } - if !updater.Empty() { - query, args := updater.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) + gr = &Group{config: guo.config} + spec.ScanTypes = []interface{}{ + &sql.NullInt64{}, + &sql.NullInt64{}, + } + spec.Assign = func(values ...interface{}) error { + if m, n := len(values), len(spec.ScanTypes); m != n { + return fmt.Errorf("mismatch number of scan values: %d != %d", m, n) } + value, ok := values[0].(*sql.NullInt64) + if !ok { + return fmt.Errorf("unexpected type %T for field id", value) + } + gr.ID = int(value.Int64) + values = values[1:] + if value, ok := values[0].(*sql.NullInt64); !ok { + return fmt.Errorf("unexpected type %T for field max_users", values[0]) + } else if value.Valid { + gr.MaxUsers = int(value.Int64) + } + return nil } - if err = tx.Commit(); err != nil { + if err = sqlgraph.UpdateNode(ctx, guo.driver, spec); err != nil { + if cerr, ok := isSQLConstraintError(err); ok { + err = cerr + } return nil, err } return gr, nil diff --git a/entc/integration/template/ent/pet_update.go b/entc/integration/template/ent/pet_update.go index 2a9ecdeda..5a618e825 100644 --- a/entc/integration/template/ent/pet_update.go +++ b/entc/integration/template/ent/pet_update.go @@ -13,9 +13,11 @@ import ( "time" "github.com/facebookincubator/ent/dialect/sql" + "github.com/facebookincubator/ent/dialect/sql/sqlgraph" "github.com/facebookincubator/ent/entc/integration/template/ent/pet" "github.com/facebookincubator/ent/entc/integration/template/ent/predicate" "github.com/facebookincubator/ent/entc/integration/template/ent/user" + "github.com/facebookincubator/ent/schema/field" ) // PetUpdate is the builder for updating Pet entities. @@ -133,83 +135,92 @@ func (pu *PetUpdate) ExecX(ctx context.Context) { } func (pu *PetUpdate) sqlSave(ctx context.Context) (n int, err error) { - var ( - builder = sql.Dialect(pu.driver.Dialect()) - selector = builder.Select(pet.FieldID).From(builder.Table(pet.Table)) - ) - for _, p := range pu.predicates { - p(selector) + spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: pet.Table, + Columns: pet.Columns, + ID: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: pet.FieldID, + }, + }, } - rows := &sql.Rows{} - query, args := selector.Query() - if err = pu.driver.Query(ctx, query, args, rows); err != nil { - return 0, err - } - defer rows.Close() - - var ids []int - for rows.Next() { - var id int - if err := rows.Scan(&id); err != nil { - return 0, fmt.Errorf("ent: failed reading id: %v", err) - } - ids = append(ids, id) - } - if len(ids) == 0 { - return 0, nil - } - - tx, err := pu.driver.Tx(ctx) - if err != nil { - return 0, err - } - var ( - res sql.Result - updater = builder.Update(pet.Table) - ) - updater = updater.Where(sql.InInts(pet.FieldID, ids...)) - if value := pu.age; value != nil { - updater.Set(pet.FieldAge, *value) - } - if value := pu.addage; value != nil { - updater.Add(pet.FieldAge, *value) - } - if value := pu.licensed_at; value != nil { - updater.Set(pet.FieldLicensedAt, *value) - } - if pu.clearlicensed_at { - updater.SetNull(pet.FieldLicensedAt) - } - if !updater.Empty() { - query, args := updater.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } - } - if pu.clearedOwner { - query, args := builder.Update(pet.OwnerTable). - SetNull(pet.OwnerColumn). - Where(sql.InInts(user.FieldID, ids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } - } - if len(pu.owner) > 0 { - for eid := range pu.owner { - query, args := builder.Update(pet.OwnerTable). - Set(pet.OwnerColumn, eid). - Where(sql.InInts(pet.FieldID, ids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) + if ps := pu.predicates; len(ps) > 0 { + spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) } } } - if err = tx.Commit(); err != nil { + if value := pu.age; value != nil { + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: *value, + Column: pet.FieldAge, + }) + } + if value := pu.addage; value != nil { + spec.Fields.Add = append(spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: *value, + Column: pet.FieldAge, + }) + } + if value := pu.licensed_at; value != nil { + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeTime, + Value: *value, + Column: pet.FieldLicensedAt, + }) + } + if pu.clearlicensed_at { + spec.Fields.Clear = append(spec.Fields.Clear, &sqlgraph.FieldSpec{ + Type: field.TypeTime, + Column: pet.FieldLicensedAt, + }) + } + if pu.clearedOwner { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: pet.OwnerTable, + Columns: []string{pet.OwnerColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: user.FieldID, + }, + }, + } + spec.Edges.Clear = append(spec.Edges.Clear, edge) + } + if nodes := pu.owner; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: pet.OwnerTable, + Columns: []string{pet.OwnerColumn}, + Bidi: false, + 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, pu.driver, spec); err != nil { + if cerr, ok := isSQLConstraintError(err); ok { + err = cerr + } return 0, err } - return len(ids), nil + return n, nil } // PetUpdateOne is the builder for updating a single Pet entity. @@ -321,87 +332,112 @@ func (puo *PetUpdateOne) ExecX(ctx context.Context) { } func (puo *PetUpdateOne) sqlSave(ctx context.Context) (pe *Pet, err error) { - var ( - builder = sql.Dialect(puo.driver.Dialect()) - selector = builder.Select(pet.Columns...).From(builder.Table(pet.Table)) - ) - pet.ID(puo.id)(selector) - rows := &sql.Rows{} - query, args := selector.Query() - if err = puo.driver.Query(ctx, query, args, rows); err != nil { - return nil, err + spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: pet.Table, + Columns: pet.Columns, + ID: &sqlgraph.FieldSpec{ + Value: puo.id, + Type: field.TypeInt, + Column: pet.FieldID, + }, + }, } - defer rows.Close() - - var ids []int - for rows.Next() { - var id int - pe = &Pet{config: puo.config} - if err := pe.FromRows(rows); err != nil { - return nil, fmt.Errorf("ent: failed scanning row into Pet: %v", err) - } - id = pe.ID - ids = append(ids, id) - } - switch n := len(ids); { - case n == 0: - return nil, &ErrNotFound{fmt.Sprintf("Pet with id: %v", puo.id)} - case n > 1: - return nil, fmt.Errorf("ent: more than one Pet with the same id: %v", puo.id) - } - - tx, err := puo.driver.Tx(ctx) - if err != nil { - return nil, err - } - var ( - res sql.Result - updater = builder.Update(pet.Table) - ) - updater = updater.Where(sql.InInts(pet.FieldID, ids...)) if value := puo.age; value != nil { - updater.Set(pet.FieldAge, *value) - pe.Age = *value + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: *value, + Column: pet.FieldAge, + }) } if value := puo.addage; value != nil { - updater.Add(pet.FieldAge, *value) - pe.Age += *value + spec.Fields.Add = append(spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: *value, + Column: pet.FieldAge, + }) } if value := puo.licensed_at; value != nil { - updater.Set(pet.FieldLicensedAt, *value) - pe.LicensedAt = value + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeTime, + Value: *value, + Column: pet.FieldLicensedAt, + }) } if puo.clearlicensed_at { - pe.LicensedAt = nil - updater.SetNull(pet.FieldLicensedAt) - } - if !updater.Empty() { - query, args := updater.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) - } + spec.Fields.Clear = append(spec.Fields.Clear, &sqlgraph.FieldSpec{ + Type: field.TypeTime, + Column: pet.FieldLicensedAt, + }) } if puo.clearedOwner { - query, args := builder.Update(pet.OwnerTable). - SetNull(pet.OwnerColumn). - Where(sql.InInts(user.FieldID, ids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: pet.OwnerTable, + Columns: []string{pet.OwnerColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: user.FieldID, + }, + }, } + spec.Edges.Clear = append(spec.Edges.Clear, edge) } - if len(puo.owner) > 0 { - for eid := range puo.owner { - query, args := builder.Update(pet.OwnerTable). - Set(pet.OwnerColumn, eid). - Where(sql.InInts(pet.FieldID, ids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) - } + if nodes := puo.owner; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: pet.OwnerTable, + Columns: []string{pet.OwnerColumn}, + Bidi: false, + 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 err = tx.Commit(); err != nil { + pe = &Pet{config: puo.config} + spec.ScanTypes = []interface{}{ + &sql.NullInt64{}, + &sql.NullInt64{}, + &sql.NullTime{}, + } + spec.Assign = func(values ...interface{}) error { + if m, n := len(values), len(spec.ScanTypes); m != n { + return fmt.Errorf("mismatch number of scan values: %d != %d", m, n) + } + value, ok := values[0].(*sql.NullInt64) + if !ok { + return fmt.Errorf("unexpected type %T for field id", value) + } + pe.ID = int(value.Int64) + values = values[1:] + if value, ok := values[0].(*sql.NullInt64); !ok { + return fmt.Errorf("unexpected type %T for field age", values[0]) + } else if value.Valid { + pe.Age = int(value.Int64) + } + if value, ok := values[1].(*sql.NullTime); !ok { + return fmt.Errorf("unexpected type %T for field licensed_at", values[1]) + } else if value.Valid { + pe.LicensedAt = new(time.Time) + *pe.LicensedAt = value.Time + } + return nil + } + if err = sqlgraph.UpdateNode(ctx, puo.driver, spec); err != nil { + if cerr, ok := isSQLConstraintError(err); ok { + err = cerr + } return nil, err } return pe, nil diff --git a/entc/integration/template/ent/user_update.go b/entc/integration/template/ent/user_update.go index b6c09c75a..7eca452ae 100644 --- a/entc/integration/template/ent/user_update.go +++ b/entc/integration/template/ent/user_update.go @@ -11,9 +11,11 @@ import ( "fmt" "github.com/facebookincubator/ent/dialect/sql" + "github.com/facebookincubator/ent/dialect/sql/sqlgraph" "github.com/facebookincubator/ent/entc/integration/template/ent/pet" "github.com/facebookincubator/ent/entc/integration/template/ent/predicate" "github.com/facebookincubator/ent/entc/integration/template/ent/user" + "github.com/facebookincubator/ent/schema/field" ) // UserUpdate is the builder for updating User entities. @@ -147,127 +149,113 @@ func (uu *UserUpdate) ExecX(ctx context.Context) { } func (uu *UserUpdate) sqlSave(ctx context.Context) (n int, err error) { - var ( - builder = sql.Dialect(uu.driver.Dialect()) - selector = builder.Select(user.FieldID).From(builder.Table(user.Table)) - ) - for _, p := range uu.predicates { - p(selector) + spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: user.Table, + Columns: user.Columns, + ID: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: user.FieldID, + }, + }, } - rows := &sql.Rows{} - query, args := selector.Query() - if err = uu.driver.Query(ctx, query, args, rows); err != nil { - return 0, err - } - defer rows.Close() - - var ids []int - for rows.Next() { - var id int - if err := rows.Scan(&id); err != nil { - return 0, fmt.Errorf("ent: failed reading id: %v", err) + if ps := uu.predicates; len(ps) > 0 { + spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } } - ids = append(ids, id) } - if len(ids) == 0 { - return 0, nil - } - - tx, err := uu.driver.Tx(ctx) - if err != nil { - return 0, err - } - var ( - res sql.Result - updater = builder.Update(user.Table) - ) - updater = updater.Where(sql.InInts(user.FieldID, ids...)) if value := uu.name; value != nil { - updater.Set(user.FieldName, *value) + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: *value, + Column: user.FieldName, + }) } - if !updater.Empty() { - query, args := updater.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) + if nodes := uu.removedPets; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: user.PetsTable, + Columns: []string{user.PetsColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: pet.FieldID, + }, + }, } + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + spec.Edges.Clear = append(spec.Edges.Clear, edge) } - if len(uu.removedPets) > 0 { - eids := make([]int, len(uu.removedPets)) - for eid := range uu.removedPets { - eids = append(eids, eid) + if nodes := uu.pets; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: user.PetsTable, + Columns: []string{user.PetsColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: pet.FieldID, + }, + }, } - query, args := builder.Update(user.PetsTable). - SetNull(user.PetsColumn). - Where(sql.InInts(user.PetsColumn, ids...)). - Where(sql.InInts(pet.FieldID, eids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) } + spec.Edges.Add = append(spec.Edges.Add, edge) } - if len(uu.pets) > 0 { - for _, id := range ids { - p := sql.P() - for eid := range uu.pets { - p.Or().EQ(pet.FieldID, eid) - } - query, args := builder.Update(user.PetsTable). - Set(user.PetsColumn, id). - Where(sql.And(p, sql.IsNull(user.PetsColumn))). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } - affected, err := res.RowsAffected() - if err != nil { - return 0, rollback(tx, err) - } - if int(affected) < len(uu.pets) { - return 0, rollback(tx, &ConstraintError{msg: fmt.Sprintf("one of \"pets\" %v already connected to a different \"User\"", keys(uu.pets))}) - } + if nodes := uu.removedFriends; 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 len(uu.removedFriends) > 0 { - eids := make([]int, len(uu.removedFriends)) - for eid := range uu.removedFriends { - eids = append(eids, eid) + if nodes := uu.friends; 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, + }, + }, } - query, args := builder.Delete(user.FriendsTable). - Where(sql.InInts(user.FriendsPrimaryKey[0], ids...)). - Where(sql.InInts(user.FriendsPrimaryKey[1], eids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } - query, args = builder.Delete(user.FriendsTable). - Where(sql.InInts(user.FriendsPrimaryKey[1], ids...)). - Where(sql.InInts(user.FriendsPrimaryKey[0], eids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) } + spec.Edges.Add = append(spec.Edges.Add, edge) } - if len(uu.friends) > 0 { - values := make([][]int, 0, len(ids)) - for _, id := range ids { - for eid := range uu.friends { - values = append(values, []int{id, eid}, []int{eid, id}) - } + if n, err = sqlgraph.UpdateNodes(ctx, uu.driver, spec); err != nil { + if cerr, ok := isSQLConstraintError(err); ok { + err = cerr } - builder := builder.Insert(user.FriendsTable). - Columns(user.FriendsPrimaryKey[0], user.FriendsPrimaryKey[1]) - for _, v := range values { - builder.Values(v[0], v[1]) - } - query, args := builder.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } - } - if err = tx.Commit(); err != nil { return 0, err } - return len(ids), nil + return n, nil } // UserUpdateOne is the builder for updating a single User entity. @@ -395,128 +383,126 @@ func (uuo *UserUpdateOne) ExecX(ctx context.Context) { } func (uuo *UserUpdateOne) sqlSave(ctx context.Context) (u *User, err error) { - var ( - builder = sql.Dialect(uuo.driver.Dialect()) - selector = builder.Select(user.Columns...).From(builder.Table(user.Table)) - ) - user.ID(uuo.id)(selector) - rows := &sql.Rows{} - query, args := selector.Query() - if err = uuo.driver.Query(ctx, query, args, rows); err != nil { - return nil, err + spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: user.Table, + Columns: user.Columns, + ID: &sqlgraph.FieldSpec{ + Value: uuo.id, + Type: field.TypeInt, + Column: user.FieldID, + }, + }, } - defer rows.Close() - - var ids []int - for rows.Next() { - var id int - u = &User{config: uuo.config} - if err := u.FromRows(rows); err != nil { - return nil, fmt.Errorf("ent: failed scanning row into User: %v", err) - } - id = u.ID - ids = append(ids, id) - } - switch n := len(ids); { - case n == 0: - return nil, &ErrNotFound{fmt.Sprintf("User with id: %v", uuo.id)} - case n > 1: - return nil, fmt.Errorf("ent: more than one User with the same id: %v", uuo.id) - } - - tx, err := uuo.driver.Tx(ctx) - if err != nil { - return nil, err - } - var ( - res sql.Result - updater = builder.Update(user.Table) - ) - updater = updater.Where(sql.InInts(user.FieldID, ids...)) if value := uuo.name; value != nil { - updater.Set(user.FieldName, *value) - u.Name = *value + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: *value, + Column: user.FieldName, + }) } - if !updater.Empty() { - query, args := updater.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) + if nodes := uuo.removedPets; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: user.PetsTable, + Columns: []string{user.PetsColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: pet.FieldID, + }, + }, } + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + spec.Edges.Clear = append(spec.Edges.Clear, edge) } - if len(uuo.removedPets) > 0 { - eids := make([]int, len(uuo.removedPets)) - for eid := range uuo.removedPets { - eids = append(eids, eid) + if nodes := uuo.pets; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: user.PetsTable, + Columns: []string{user.PetsColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: pet.FieldID, + }, + }, } - query, args := builder.Update(user.PetsTable). - SetNull(user.PetsColumn). - Where(sql.InInts(user.PetsColumn, ids...)). - Where(sql.InInts(pet.FieldID, eids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) } + spec.Edges.Add = append(spec.Edges.Add, edge) } - if len(uuo.pets) > 0 { - for _, id := range ids { - p := sql.P() - for eid := range uuo.pets { - p.Or().EQ(pet.FieldID, eid) - } - query, args := builder.Update(user.PetsTable). - Set(user.PetsColumn, id). - Where(sql.And(p, sql.IsNull(user.PetsColumn))). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) - } - affected, err := res.RowsAffected() - if err != nil { - return nil, rollback(tx, err) - } - if int(affected) < len(uuo.pets) { - return nil, rollback(tx, &ConstraintError{msg: fmt.Sprintf("one of \"pets\" %v already connected to a different \"User\"", keys(uuo.pets))}) - } + if nodes := uuo.removedFriends; 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 len(uuo.removedFriends) > 0 { - eids := make([]int, len(uuo.removedFriends)) - for eid := range uuo.removedFriends { - eids = append(eids, eid) + if nodes := uuo.friends; 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, + }, + }, } - query, args := builder.Delete(user.FriendsTable). - Where(sql.InInts(user.FriendsPrimaryKey[0], ids...)). - Where(sql.InInts(user.FriendsPrimaryKey[1], eids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) - } - query, args = builder.Delete(user.FriendsTable). - Where(sql.InInts(user.FriendsPrimaryKey[1], ids...)). - Where(sql.InInts(user.FriendsPrimaryKey[0], eids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) } + spec.Edges.Add = append(spec.Edges.Add, edge) } - if len(uuo.friends) > 0 { - values := make([][]int, 0, len(ids)) - for _, id := range ids { - for eid := range uuo.friends { - values = append(values, []int{id, eid}, []int{eid, id}) - } - } - builder := builder.Insert(user.FriendsTable). - Columns(user.FriendsPrimaryKey[0], user.FriendsPrimaryKey[1]) - for _, v := range values { - builder.Values(v[0], v[1]) - } - query, args := builder.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) - } + u = &User{config: uuo.config} + spec.ScanTypes = []interface{}{ + &sql.NullInt64{}, + &sql.NullString{}, } - if err = tx.Commit(); err != nil { + spec.Assign = func(values ...interface{}) error { + if m, n := len(values), len(spec.ScanTypes); m != n { + return fmt.Errorf("mismatch number of scan values: %d != %d", m, n) + } + value, ok := values[0].(*sql.NullInt64) + if !ok { + return fmt.Errorf("unexpected type %T for field id", value) + } + u.ID = int(value.Int64) + values = values[1:] + if value, ok := values[0].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field name", values[0]) + } else if value.Valid { + u.Name = value.String + } + return nil + } + if err = sqlgraph.UpdateNode(ctx, uuo.driver, spec); err != nil { + if cerr, ok := isSQLConstraintError(err); ok { + err = cerr + } return nil, err } return u, nil diff --git a/entc/integration/type_test.go b/entc/integration/type_test.go index 734dc53b2..3fbd77bcb 100644 --- a/entc/integration/type_test.go +++ b/entc/integration/type_test.go @@ -35,30 +35,30 @@ func Types(t *testing.T, client *ent.Client) { ft = client.FieldType.Create(). SetInt(1). - SetInt8(math.MaxInt8). - SetInt16(math.MaxInt16). - SetInt32(math.MaxInt16). - SetInt64(math.MaxInt16). - SetOptionalInt8(math.MaxInt8). - SetOptionalInt16(math.MaxInt16). - SetOptionalInt32(math.MaxInt32). - SetOptionalInt64(math.MaxInt64). - SetNillableInt8(math.MaxInt8). - SetNillableInt16(math.MaxInt16). - SetNillableInt32(math.MaxInt32). - SetNillableInt64(math.MaxInt64). + SetInt8(math.MinInt8). + SetInt16(math.MinInt16). + SetInt32(math.MinInt16). + SetInt64(math.MinInt16). + SetOptionalInt8(math.MinInt8). + SetOptionalInt16(math.MinInt16). + SetOptionalInt32(math.MinInt32). + SetOptionalInt64(math.MinInt64). + SetNillableInt8(math.MinInt8). + SetNillableInt16(math.MinInt16). + SetNillableInt32(math.MinInt32). + SetNillableInt64(math.MinInt64). SaveX(ctx) - require.Equal(int8(math.MaxInt8), ft.OptionalInt8) - require.Equal(int16(math.MaxInt16), ft.OptionalInt16) - require.Equal(int32(math.MaxInt32), ft.OptionalInt32) - require.Equal(int64(math.MaxInt64), ft.OptionalInt64) - require.Equal(int8(math.MaxInt8), *ft.NillableInt8) - require.Equal(int16(math.MaxInt16), *ft.NillableInt16) - require.Equal(int32(math.MaxInt32), *ft.NillableInt32) - require.Equal(int64(math.MaxInt64), *ft.NillableInt64) + require.Equal(int8(math.MinInt8), ft.OptionalInt8) + require.Equal(int16(math.MinInt16), ft.OptionalInt16) + require.Equal(int32(math.MinInt32), ft.OptionalInt32) + require.Equal(int64(math.MinInt64), ft.OptionalInt64) + require.Equal(int8(math.MinInt8), *ft.NillableInt8) + require.Equal(int16(math.MinInt16), *ft.NillableInt16) + require.Equal(int32(math.MinInt32), *ft.NillableInt32) + require.Equal(int64(math.MinInt64), *ft.NillableInt64) - ft = client.FieldType.UpdateOne(ft). + ft = ft.Update(). SetInt(1). SetInt8(math.MaxInt8). SetInt16(math.MaxInt16). diff --git a/examples/edgeindex/ent/city_update.go b/examples/edgeindex/ent/city_update.go index 712ba87a4..6b4c7e629 100644 --- a/examples/edgeindex/ent/city_update.go +++ b/examples/edgeindex/ent/city_update.go @@ -11,9 +11,11 @@ import ( "fmt" "github.com/facebookincubator/ent/dialect/sql" + "github.com/facebookincubator/ent/dialect/sql/sqlgraph" "github.com/facebookincubator/ent/examples/edgeindex/ent/city" "github.com/facebookincubator/ent/examples/edgeindex/ent/predicate" "github.com/facebookincubator/ent/examples/edgeindex/ent/street" + "github.com/facebookincubator/ent/schema/field" ) // CityUpdate is the builder for updating City entities. @@ -105,90 +107,75 @@ func (cu *CityUpdate) ExecX(ctx context.Context) { } func (cu *CityUpdate) sqlSave(ctx context.Context) (n int, err error) { - var ( - builder = sql.Dialect(cu.driver.Dialect()) - selector = builder.Select(city.FieldID).From(builder.Table(city.Table)) - ) - for _, p := range cu.predicates { - p(selector) + spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: city.Table, + Columns: city.Columns, + ID: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: city.FieldID, + }, + }, } - rows := &sql.Rows{} - query, args := selector.Query() - if err = cu.driver.Query(ctx, query, args, rows); err != nil { - return 0, err - } - defer rows.Close() - - var ids []int - for rows.Next() { - var id int - if err := rows.Scan(&id); err != nil { - return 0, fmt.Errorf("ent: failed reading id: %v", err) + if ps := cu.predicates; len(ps) > 0 { + spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } } - ids = append(ids, id) } - if len(ids) == 0 { - return 0, nil - } - - tx, err := cu.driver.Tx(ctx) - if err != nil { - return 0, err - } - var ( - res sql.Result - updater = builder.Update(city.Table) - ) - updater = updater.Where(sql.InInts(city.FieldID, ids...)) if value := cu.name; value != nil { - updater.Set(city.FieldName, *value) + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: *value, + Column: city.FieldName, + }) } - if !updater.Empty() { - query, args := updater.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) + if nodes := cu.removedStreets; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: city.StreetsTable, + Columns: []string{city.StreetsColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: street.FieldID, + }, + }, } + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + spec.Edges.Clear = append(spec.Edges.Clear, edge) } - if len(cu.removedStreets) > 0 { - eids := make([]int, len(cu.removedStreets)) - for eid := range cu.removedStreets { - eids = append(eids, eid) + if nodes := cu.streets; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: city.StreetsTable, + Columns: []string{city.StreetsColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: street.FieldID, + }, + }, } - query, args := builder.Update(city.StreetsTable). - SetNull(city.StreetsColumn). - Where(sql.InInts(city.StreetsColumn, ids...)). - Where(sql.InInts(street.FieldID, eids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) } + spec.Edges.Add = append(spec.Edges.Add, edge) } - if len(cu.streets) > 0 { - for _, id := range ids { - p := sql.P() - for eid := range cu.streets { - p.Or().EQ(street.FieldID, eid) - } - query, args := builder.Update(city.StreetsTable). - Set(city.StreetsColumn, id). - Where(sql.And(p, sql.IsNull(city.StreetsColumn))). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } - affected, err := res.RowsAffected() - if err != nil { - return 0, rollback(tx, err) - } - if int(affected) < len(cu.streets) { - return 0, rollback(tx, &ConstraintError{msg: fmt.Sprintf("one of \"streets\" %v already connected to a different \"City\"", keys(cu.streets))}) - } + if n, err = sqlgraph.UpdateNodes(ctx, cu.driver, spec); err != nil { + if cerr, ok := isSQLConstraintError(err); ok { + err = cerr } - } - if err = tx.Commit(); err != nil { return 0, err } - return len(ids), nil + return n, nil } // CityUpdateOne is the builder for updating a single City entity. @@ -274,91 +261,88 @@ func (cuo *CityUpdateOne) ExecX(ctx context.Context) { } func (cuo *CityUpdateOne) sqlSave(ctx context.Context) (c *City, err error) { - var ( - builder = sql.Dialect(cuo.driver.Dialect()) - selector = builder.Select(city.Columns...).From(builder.Table(city.Table)) - ) - city.ID(cuo.id)(selector) - rows := &sql.Rows{} - query, args := selector.Query() - if err = cuo.driver.Query(ctx, query, args, rows); err != nil { - return nil, err + spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: city.Table, + Columns: city.Columns, + ID: &sqlgraph.FieldSpec{ + Value: cuo.id, + Type: field.TypeInt, + Column: city.FieldID, + }, + }, } - defer rows.Close() - - var ids []int - for rows.Next() { - var id int - c = &City{config: cuo.config} - if err := c.FromRows(rows); err != nil { - return nil, fmt.Errorf("ent: failed scanning row into City: %v", err) - } - id = c.ID - ids = append(ids, id) - } - switch n := len(ids); { - case n == 0: - return nil, &ErrNotFound{fmt.Sprintf("City with id: %v", cuo.id)} - case n > 1: - return nil, fmt.Errorf("ent: more than one City with the same id: %v", cuo.id) - } - - tx, err := cuo.driver.Tx(ctx) - if err != nil { - return nil, err - } - var ( - res sql.Result - updater = builder.Update(city.Table) - ) - updater = updater.Where(sql.InInts(city.FieldID, ids...)) if value := cuo.name; value != nil { - updater.Set(city.FieldName, *value) - c.Name = *value + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: *value, + Column: city.FieldName, + }) } - if !updater.Empty() { - query, args := updater.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) + if nodes := cuo.removedStreets; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: city.StreetsTable, + Columns: []string{city.StreetsColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: street.FieldID, + }, + }, } + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + spec.Edges.Clear = append(spec.Edges.Clear, edge) } - if len(cuo.removedStreets) > 0 { - eids := make([]int, len(cuo.removedStreets)) - for eid := range cuo.removedStreets { - eids = append(eids, eid) + if nodes := cuo.streets; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: city.StreetsTable, + Columns: []string{city.StreetsColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: street.FieldID, + }, + }, } - query, args := builder.Update(city.StreetsTable). - SetNull(city.StreetsColumn). - Where(sql.InInts(city.StreetsColumn, ids...)). - Where(sql.InInts(street.FieldID, eids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) } + spec.Edges.Add = append(spec.Edges.Add, edge) } - if len(cuo.streets) > 0 { - for _, id := range ids { - p := sql.P() - for eid := range cuo.streets { - p.Or().EQ(street.FieldID, eid) - } - query, args := builder.Update(city.StreetsTable). - Set(city.StreetsColumn, id). - Where(sql.And(p, sql.IsNull(city.StreetsColumn))). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) - } - affected, err := res.RowsAffected() - if err != nil { - return nil, rollback(tx, err) - } - if int(affected) < len(cuo.streets) { - return nil, rollback(tx, &ConstraintError{msg: fmt.Sprintf("one of \"streets\" %v already connected to a different \"City\"", keys(cuo.streets))}) - } - } + c = &City{config: cuo.config} + spec.ScanTypes = []interface{}{ + &sql.NullInt64{}, + &sql.NullString{}, } - if err = tx.Commit(); err != nil { + spec.Assign = func(values ...interface{}) error { + if m, n := len(values), len(spec.ScanTypes); m != n { + return fmt.Errorf("mismatch number of scan values: %d != %d", m, n) + } + value, ok := values[0].(*sql.NullInt64) + if !ok { + return fmt.Errorf("unexpected type %T for field id", value) + } + c.ID = int(value.Int64) + values = values[1:] + if value, ok := values[0].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field name", values[0]) + } else if value.Valid { + c.Name = value.String + } + return nil + } + if err = sqlgraph.UpdateNode(ctx, cuo.driver, spec); err != nil { + if cerr, ok := isSQLConstraintError(err); ok { + err = cerr + } return nil, err } return c, nil diff --git a/examples/edgeindex/ent/street_update.go b/examples/edgeindex/ent/street_update.go index e79ebc7fc..4d255bd9a 100644 --- a/examples/edgeindex/ent/street_update.go +++ b/examples/edgeindex/ent/street_update.go @@ -12,9 +12,11 @@ import ( "fmt" "github.com/facebookincubator/ent/dialect/sql" + "github.com/facebookincubator/ent/dialect/sql/sqlgraph" "github.com/facebookincubator/ent/examples/edgeindex/ent/city" "github.com/facebookincubator/ent/examples/edgeindex/ent/predicate" "github.com/facebookincubator/ent/examples/edgeindex/ent/street" + "github.com/facebookincubator/ent/schema/field" ) // StreetUpdate is the builder for updating Street entities. @@ -97,74 +99,72 @@ func (su *StreetUpdate) ExecX(ctx context.Context) { } func (su *StreetUpdate) sqlSave(ctx context.Context) (n int, err error) { - var ( - builder = sql.Dialect(su.driver.Dialect()) - selector = builder.Select(street.FieldID).From(builder.Table(street.Table)) - ) - for _, p := range su.predicates { - p(selector) + spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: street.Table, + Columns: street.Columns, + ID: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: street.FieldID, + }, + }, } - rows := &sql.Rows{} - query, args := selector.Query() - if err = su.driver.Query(ctx, query, args, rows); err != nil { - return 0, err - } - defer rows.Close() - - var ids []int - for rows.Next() { - var id int - if err := rows.Scan(&id); err != nil { - return 0, fmt.Errorf("ent: failed reading id: %v", err) - } - ids = append(ids, id) - } - if len(ids) == 0 { - return 0, nil - } - - tx, err := su.driver.Tx(ctx) - if err != nil { - return 0, err - } - var ( - res sql.Result - updater = builder.Update(street.Table) - ) - updater = updater.Where(sql.InInts(street.FieldID, ids...)) - if value := su.name; value != nil { - updater.Set(street.FieldName, *value) - } - if !updater.Empty() { - query, args := updater.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } - } - if su.clearedCity { - query, args := builder.Update(street.CityTable). - SetNull(street.CityColumn). - Where(sql.InInts(city.FieldID, ids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } - } - if len(su.city) > 0 { - for eid := range su.city { - query, args := builder.Update(street.CityTable). - Set(street.CityColumn, eid). - Where(sql.InInts(street.FieldID, ids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) + if ps := su.predicates; len(ps) > 0 { + spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) } } } - if err = tx.Commit(); err != nil { + if value := su.name; value != nil { + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: *value, + Column: street.FieldName, + }) + } + if su.clearedCity { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: street.CityTable, + Columns: []string{street.CityColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: city.FieldID, + }, + }, + } + spec.Edges.Clear = append(spec.Edges.Clear, edge) + } + if nodes := su.city; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: street.CityTable, + Columns: []string{street.CityColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: city.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, su.driver, spec); err != nil { + if cerr, ok := isSQLConstraintError(err); ok { + err = cerr + } return 0, err } - return len(ids), nil + return n, nil } // StreetUpdateOne is the builder for updating a single Street entity. @@ -241,75 +241,85 @@ func (suo *StreetUpdateOne) ExecX(ctx context.Context) { } func (suo *StreetUpdateOne) sqlSave(ctx context.Context) (s *Street, err error) { - var ( - builder = sql.Dialect(suo.driver.Dialect()) - selector = builder.Select(street.Columns...).From(builder.Table(street.Table)) - ) - street.ID(suo.id)(selector) - rows := &sql.Rows{} - query, args := selector.Query() - if err = suo.driver.Query(ctx, query, args, rows); err != nil { - return nil, err + spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: street.Table, + Columns: street.Columns, + ID: &sqlgraph.FieldSpec{ + Value: suo.id, + Type: field.TypeInt, + Column: street.FieldID, + }, + }, } - defer rows.Close() - - var ids []int - for rows.Next() { - var id int - s = &Street{config: suo.config} - if err := s.FromRows(rows); err != nil { - return nil, fmt.Errorf("ent: failed scanning row into Street: %v", err) - } - id = s.ID - ids = append(ids, id) - } - switch n := len(ids); { - case n == 0: - return nil, &ErrNotFound{fmt.Sprintf("Street with id: %v", suo.id)} - case n > 1: - return nil, fmt.Errorf("ent: more than one Street with the same id: %v", suo.id) - } - - tx, err := suo.driver.Tx(ctx) - if err != nil { - return nil, err - } - var ( - res sql.Result - updater = builder.Update(street.Table) - ) - updater = updater.Where(sql.InInts(street.FieldID, ids...)) if value := suo.name; value != nil { - updater.Set(street.FieldName, *value) - s.Name = *value - } - if !updater.Empty() { - query, args := updater.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) - } + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: *value, + Column: street.FieldName, + }) } if suo.clearedCity { - query, args := builder.Update(street.CityTable). - SetNull(street.CityColumn). - Where(sql.InInts(city.FieldID, ids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: street.CityTable, + Columns: []string{street.CityColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: city.FieldID, + }, + }, } + spec.Edges.Clear = append(spec.Edges.Clear, edge) } - if len(suo.city) > 0 { - for eid := range suo.city { - query, args := builder.Update(street.CityTable). - Set(street.CityColumn, eid). - Where(sql.InInts(street.FieldID, ids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) - } + if nodes := suo.city; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: street.CityTable, + Columns: []string{street.CityColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: city.FieldID, + }, + }, } + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + spec.Edges.Add = append(spec.Edges.Add, edge) } - if err = tx.Commit(); err != nil { + s = &Street{config: suo.config} + spec.ScanTypes = []interface{}{ + &sql.NullInt64{}, + &sql.NullString{}, + } + spec.Assign = func(values ...interface{}) error { + if m, n := len(values), len(spec.ScanTypes); m != n { + return fmt.Errorf("mismatch number of scan values: %d != %d", m, n) + } + value, ok := values[0].(*sql.NullInt64) + if !ok { + return fmt.Errorf("unexpected type %T for field id", value) + } + s.ID = int(value.Int64) + values = values[1:] + if value, ok := values[0].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field name", values[0]) + } else if value.Valid { + s.Name = value.String + } + return nil + } + if err = sqlgraph.UpdateNode(ctx, suo.driver, spec); err != nil { + if cerr, ok := isSQLConstraintError(err); ok { + err = cerr + } return nil, err } return s, nil diff --git a/examples/entcpkg/ent/user_update.go b/examples/entcpkg/ent/user_update.go index cf2e05911..1b704c07f 100644 --- a/examples/entcpkg/ent/user_update.go +++ b/examples/entcpkg/ent/user_update.go @@ -11,8 +11,10 @@ import ( "fmt" "github.com/facebookincubator/ent/dialect/sql" + "github.com/facebookincubator/ent/dialect/sql/sqlgraph" "github.com/facebookincubator/ent/examples/entcpkg/ent/predicate" "github.com/facebookincubator/ent/examples/entcpkg/ent/user" + "github.com/facebookincubator/ent/schema/field" ) // UserUpdate is the builder for updating User entities. @@ -55,40 +57,30 @@ func (uu *UserUpdate) ExecX(ctx context.Context) { } func (uu *UserUpdate) sqlSave(ctx context.Context) (n int, err error) { - var ( - builder = sql.Dialect(uu.driver.Dialect()) - selector = builder.Select(user.FieldID).From(builder.Table(user.Table)) - ) - for _, p := range uu.predicates { - p(selector) + spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: user.Table, + Columns: user.Columns, + ID: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: user.FieldID, + }, + }, } - rows := &sql.Rows{} - query, args := selector.Query() - if err = uu.driver.Query(ctx, query, args, rows); err != nil { - return 0, err - } - defer rows.Close() - - var ids []int - for rows.Next() { - var id int - if err := rows.Scan(&id); err != nil { - return 0, fmt.Errorf("ent: failed reading id: %v", err) + if ps := uu.predicates; len(ps) > 0 { + spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } } - ids = append(ids, id) } - if len(ids) == 0 { - return 0, nil - } - - tx, err := uu.driver.Tx(ctx) - if err != nil { + if n, err = sqlgraph.UpdateNodes(ctx, uu.driver, spec); err != nil { + if cerr, ok := isSQLConstraintError(err); ok { + err = cerr + } return 0, err } - if err = tx.Commit(); err != nil { - return 0, err - } - return len(ids), nil + return n, nil } // UserUpdateOne is the builder for updating a single User entity. @@ -125,40 +117,37 @@ func (uuo *UserUpdateOne) ExecX(ctx context.Context) { } func (uuo *UserUpdateOne) sqlSave(ctx context.Context) (u *User, err error) { - var ( - builder = sql.Dialect(uuo.driver.Dialect()) - selector = builder.Select(user.Columns...).From(builder.Table(user.Table)) - ) - user.ID(uuo.id)(selector) - rows := &sql.Rows{} - query, args := selector.Query() - if err = uuo.driver.Query(ctx, query, args, rows); err != nil { - return nil, err + spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: user.Table, + Columns: user.Columns, + ID: &sqlgraph.FieldSpec{ + Value: uuo.id, + Type: field.TypeInt, + Column: user.FieldID, + }, + }, } - defer rows.Close() - - var ids []int - for rows.Next() { - var id int - u = &User{config: uuo.config} - if err := u.FromRows(rows); err != nil { - return nil, fmt.Errorf("ent: failed scanning row into User: %v", err) + u = &User{config: uuo.config} + spec.ScanTypes = []interface{}{ + &sql.NullInt64{}, + } + spec.Assign = func(values ...interface{}) error { + if m, n := len(values), len(spec.ScanTypes); m != n { + return fmt.Errorf("mismatch number of scan values: %d != %d", m, n) } - id = u.ID - ids = append(ids, id) + value, ok := values[0].(*sql.NullInt64) + if !ok { + return fmt.Errorf("unexpected type %T for field id", value) + } + u.ID = int(value.Int64) + values = values[1:] + return nil } - switch n := len(ids); { - case n == 0: - return nil, &ErrNotFound{fmt.Sprintf("User with id: %v", uuo.id)} - case n > 1: - return nil, fmt.Errorf("ent: more than one User with the same id: %v", uuo.id) - } - - tx, err := uuo.driver.Tx(ctx) - if err != nil { - return nil, err - } - if err = tx.Commit(); err != nil { + if err = sqlgraph.UpdateNode(ctx, uuo.driver, spec); err != nil { + if cerr, ok := isSQLConstraintError(err); ok { + err = cerr + } return nil, err } return u, nil diff --git a/examples/m2m2types/ent/group_update.go b/examples/m2m2types/ent/group_update.go index 05af5351b..a07dc7c9c 100644 --- a/examples/m2m2types/ent/group_update.go +++ b/examples/m2m2types/ent/group_update.go @@ -11,8 +11,11 @@ import ( "fmt" "github.com/facebookincubator/ent/dialect/sql" + "github.com/facebookincubator/ent/dialect/sql/sqlgraph" "github.com/facebookincubator/ent/examples/m2m2types/ent/group" "github.com/facebookincubator/ent/examples/m2m2types/ent/predicate" + "github.com/facebookincubator/ent/examples/m2m2types/ent/user" + "github.com/facebookincubator/ent/schema/field" ) // GroupUpdate is the builder for updating Group entities. @@ -104,84 +107,75 @@ func (gu *GroupUpdate) ExecX(ctx context.Context) { } func (gu *GroupUpdate) sqlSave(ctx context.Context) (n int, err error) { - var ( - builder = sql.Dialect(gu.driver.Dialect()) - selector = builder.Select(group.FieldID).From(builder.Table(group.Table)) - ) - for _, p := range gu.predicates { - p(selector) + spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: group.Table, + Columns: group.Columns, + ID: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: group.FieldID, + }, + }, } - rows := &sql.Rows{} - query, args := selector.Query() - if err = gu.driver.Query(ctx, query, args, rows); err != nil { - return 0, err - } - defer rows.Close() - - var ids []int - for rows.Next() { - var id int - if err := rows.Scan(&id); err != nil { - return 0, fmt.Errorf("ent: failed reading id: %v", err) - } - ids = append(ids, id) - } - if len(ids) == 0 { - return 0, nil - } - - tx, err := gu.driver.Tx(ctx) - if err != nil { - return 0, err - } - var ( - res sql.Result - updater = builder.Update(group.Table) - ) - updater = updater.Where(sql.InInts(group.FieldID, ids...)) - if value := gu.name; value != nil { - updater.Set(group.FieldName, *value) - } - if !updater.Empty() { - query, args := updater.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } - } - if len(gu.removedUsers) > 0 { - eids := make([]int, len(gu.removedUsers)) - for eid := range gu.removedUsers { - eids = append(eids, eid) - } - query, args := builder.Delete(group.UsersTable). - Where(sql.InInts(group.UsersPrimaryKey[0], ids...)). - Where(sql.InInts(group.UsersPrimaryKey[1], eids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } - } - if len(gu.users) > 0 { - values := make([][]int, 0, len(ids)) - for _, id := range ids { - for eid := range gu.users { - values = append(values, []int{id, eid}) + if ps := gu.predicates; len(ps) > 0 { + spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) } } - builder := builder.Insert(group.UsersTable). - Columns(group.UsersPrimaryKey[0], group.UsersPrimaryKey[1]) - for _, v := range values { - builder.Values(v[0], v[1]) - } - query, args := builder.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } } - if err = tx.Commit(); err != nil { + if value := gu.name; value != nil { + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: *value, + Column: group.FieldName, + }) + } + if nodes := gu.removedUsers; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: false, + Table: group.UsersTable, + Columns: group.UsersPrimaryKey, + Bidi: false, + 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 := gu.users; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: false, + Table: group.UsersTable, + Columns: group.UsersPrimaryKey, + Bidi: false, + 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, gu.driver, spec); err != nil { + if cerr, ok := isSQLConstraintError(err); ok { + err = cerr + } return 0, err } - return len(ids), nil + return n, nil } // GroupUpdateOne is the builder for updating a single Group entity. @@ -267,85 +261,88 @@ func (guo *GroupUpdateOne) ExecX(ctx context.Context) { } func (guo *GroupUpdateOne) sqlSave(ctx context.Context) (gr *Group, err error) { - var ( - builder = sql.Dialect(guo.driver.Dialect()) - selector = builder.Select(group.Columns...).From(builder.Table(group.Table)) - ) - group.ID(guo.id)(selector) - rows := &sql.Rows{} - query, args := selector.Query() - if err = guo.driver.Query(ctx, query, args, rows); err != nil { - return nil, err + spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: group.Table, + Columns: group.Columns, + ID: &sqlgraph.FieldSpec{ + Value: guo.id, + Type: field.TypeInt, + Column: group.FieldID, + }, + }, } - defer rows.Close() - - var ids []int - for rows.Next() { - var id int - gr = &Group{config: guo.config} - if err := gr.FromRows(rows); err != nil { - return nil, fmt.Errorf("ent: failed scanning row into Group: %v", err) - } - id = gr.ID - ids = append(ids, id) - } - switch n := len(ids); { - case n == 0: - return nil, &ErrNotFound{fmt.Sprintf("Group with id: %v", guo.id)} - case n > 1: - return nil, fmt.Errorf("ent: more than one Group with the same id: %v", guo.id) - } - - tx, err := guo.driver.Tx(ctx) - if err != nil { - return nil, err - } - var ( - res sql.Result - updater = builder.Update(group.Table) - ) - updater = updater.Where(sql.InInts(group.FieldID, ids...)) if value := guo.name; value != nil { - updater.Set(group.FieldName, *value) - gr.Name = *value + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: *value, + Column: group.FieldName, + }) } - if !updater.Empty() { - query, args := updater.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) + if nodes := guo.removedUsers; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: false, + Table: group.UsersTable, + Columns: group.UsersPrimaryKey, + Bidi: false, + 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 len(guo.removedUsers) > 0 { - eids := make([]int, len(guo.removedUsers)) - for eid := range guo.removedUsers { - eids = append(eids, eid) + if nodes := guo.users; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: false, + Table: group.UsersTable, + Columns: group.UsersPrimaryKey, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: user.FieldID, + }, + }, } - query, args := builder.Delete(group.UsersTable). - Where(sql.InInts(group.UsersPrimaryKey[0], ids...)). - Where(sql.InInts(group.UsersPrimaryKey[1], eids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) } + spec.Edges.Add = append(spec.Edges.Add, edge) } - if len(guo.users) > 0 { - values := make([][]int, 0, len(ids)) - for _, id := range ids { - for eid := range guo.users { - values = append(values, []int{id, eid}) - } - } - builder := builder.Insert(group.UsersTable). - Columns(group.UsersPrimaryKey[0], group.UsersPrimaryKey[1]) - for _, v := range values { - builder.Values(v[0], v[1]) - } - query, args := builder.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) - } + gr = &Group{config: guo.config} + spec.ScanTypes = []interface{}{ + &sql.NullInt64{}, + &sql.NullString{}, } - if err = tx.Commit(); err != nil { + spec.Assign = func(values ...interface{}) error { + if m, n := len(values), len(spec.ScanTypes); m != n { + return fmt.Errorf("mismatch number of scan values: %d != %d", m, n) + } + value, ok := values[0].(*sql.NullInt64) + if !ok { + return fmt.Errorf("unexpected type %T for field id", value) + } + gr.ID = int(value.Int64) + values = values[1:] + if value, ok := values[0].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field name", values[0]) + } else if value.Valid { + gr.Name = value.String + } + return nil + } + if err = sqlgraph.UpdateNode(ctx, guo.driver, spec); err != nil { + if cerr, ok := isSQLConstraintError(err); ok { + err = cerr + } return nil, err } return gr, nil diff --git a/examples/m2m2types/ent/user_update.go b/examples/m2m2types/ent/user_update.go index 924aac374..30990ea62 100644 --- a/examples/m2m2types/ent/user_update.go +++ b/examples/m2m2types/ent/user_update.go @@ -11,8 +11,11 @@ import ( "fmt" "github.com/facebookincubator/ent/dialect/sql" + "github.com/facebookincubator/ent/dialect/sql/sqlgraph" + "github.com/facebookincubator/ent/examples/m2m2types/ent/group" "github.com/facebookincubator/ent/examples/m2m2types/ent/predicate" "github.com/facebookincubator/ent/examples/m2m2types/ent/user" + "github.com/facebookincubator/ent/schema/field" ) // UserUpdate is the builder for updating User entities. @@ -123,90 +126,89 @@ func (uu *UserUpdate) ExecX(ctx context.Context) { } func (uu *UserUpdate) sqlSave(ctx context.Context) (n int, err error) { - var ( - builder = sql.Dialect(uu.driver.Dialect()) - selector = builder.Select(user.FieldID).From(builder.Table(user.Table)) - ) - for _, p := range uu.predicates { - p(selector) + spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: user.Table, + Columns: user.Columns, + ID: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: user.FieldID, + }, + }, } - rows := &sql.Rows{} - query, args := selector.Query() - if err = uu.driver.Query(ctx, query, args, rows); err != nil { - return 0, err - } - defer rows.Close() - - var ids []int - for rows.Next() { - var id int - if err := rows.Scan(&id); err != nil { - return 0, fmt.Errorf("ent: failed reading id: %v", err) - } - ids = append(ids, id) - } - if len(ids) == 0 { - return 0, nil - } - - tx, err := uu.driver.Tx(ctx) - if err != nil { - return 0, err - } - var ( - res sql.Result - updater = builder.Update(user.Table) - ) - updater = updater.Where(sql.InInts(user.FieldID, ids...)) - if value := uu.age; value != nil { - updater.Set(user.FieldAge, *value) - } - if value := uu.addage; value != nil { - updater.Add(user.FieldAge, *value) - } - if value := uu.name; value != nil { - updater.Set(user.FieldName, *value) - } - if !updater.Empty() { - query, args := updater.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } - } - if len(uu.removedGroups) > 0 { - eids := make([]int, len(uu.removedGroups)) - for eid := range uu.removedGroups { - eids = append(eids, eid) - } - query, args := builder.Delete(user.GroupsTable). - Where(sql.InInts(user.GroupsPrimaryKey[1], ids...)). - Where(sql.InInts(user.GroupsPrimaryKey[0], eids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } - } - if len(uu.groups) > 0 { - values := make([][]int, 0, len(ids)) - for _, id := range ids { - for eid := range uu.groups { - values = append(values, []int{id, eid}) + if ps := uu.predicates; len(ps) > 0 { + spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) } } - builder := builder.Insert(user.GroupsTable). - Columns(user.GroupsPrimaryKey[1], user.GroupsPrimaryKey[0]) - for _, v := range values { - builder.Values(v[0], v[1]) - } - query, args := builder.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } } - if err = tx.Commit(); err != nil { + if value := uu.age; value != nil { + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: *value, + Column: user.FieldAge, + }) + } + if value := uu.addage; value != nil { + spec.Fields.Add = append(spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: *value, + Column: user.FieldAge, + }) + } + if value := uu.name; value != nil { + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: *value, + Column: user.FieldName, + }) + } + if nodes := uu.removedGroups; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: true, + Table: user.GroupsTable, + Columns: user.GroupsPrimaryKey, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: group.FieldID, + }, + }, + } + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + spec.Edges.Clear = append(spec.Edges.Clear, edge) + } + if nodes := uu.groups; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: true, + Table: user.GroupsTable, + Columns: user.GroupsPrimaryKey, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: group.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 cerr, ok := isSQLConstraintError(err); ok { + err = cerr + } return 0, err } - return len(ids), nil + return n, nil } // UserUpdateOne is the builder for updating a single User entity. @@ -311,93 +313,108 @@ func (uuo *UserUpdateOne) ExecX(ctx context.Context) { } func (uuo *UserUpdateOne) sqlSave(ctx context.Context) (u *User, err error) { - var ( - builder = sql.Dialect(uuo.driver.Dialect()) - selector = builder.Select(user.Columns...).From(builder.Table(user.Table)) - ) - user.ID(uuo.id)(selector) - rows := &sql.Rows{} - query, args := selector.Query() - if err = uuo.driver.Query(ctx, query, args, rows); err != nil { - return nil, err + spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: user.Table, + Columns: user.Columns, + ID: &sqlgraph.FieldSpec{ + Value: uuo.id, + Type: field.TypeInt, + Column: user.FieldID, + }, + }, } - defer rows.Close() - - var ids []int - for rows.Next() { - var id int - u = &User{config: uuo.config} - if err := u.FromRows(rows); err != nil { - return nil, fmt.Errorf("ent: failed scanning row into User: %v", err) - } - id = u.ID - ids = append(ids, id) - } - switch n := len(ids); { - case n == 0: - return nil, &ErrNotFound{fmt.Sprintf("User with id: %v", uuo.id)} - case n > 1: - return nil, fmt.Errorf("ent: more than one User with the same id: %v", uuo.id) - } - - tx, err := uuo.driver.Tx(ctx) - if err != nil { - return nil, err - } - var ( - res sql.Result - updater = builder.Update(user.Table) - ) - updater = updater.Where(sql.InInts(user.FieldID, ids...)) if value := uuo.age; value != nil { - updater.Set(user.FieldAge, *value) - u.Age = *value + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: *value, + Column: user.FieldAge, + }) } if value := uuo.addage; value != nil { - updater.Add(user.FieldAge, *value) - u.Age += *value + spec.Fields.Add = append(spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: *value, + Column: user.FieldAge, + }) } if value := uuo.name; value != nil { - updater.Set(user.FieldName, *value) - u.Name = *value + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: *value, + Column: user.FieldName, + }) } - if !updater.Empty() { - query, args := updater.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) + if nodes := uuo.removedGroups; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: true, + Table: user.GroupsTable, + Columns: user.GroupsPrimaryKey, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: group.FieldID, + }, + }, } + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + spec.Edges.Clear = append(spec.Edges.Clear, edge) } - if len(uuo.removedGroups) > 0 { - eids := make([]int, len(uuo.removedGroups)) - for eid := range uuo.removedGroups { - eids = append(eids, eid) + if nodes := uuo.groups; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: true, + Table: user.GroupsTable, + Columns: user.GroupsPrimaryKey, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: group.FieldID, + }, + }, } - query, args := builder.Delete(user.GroupsTable). - Where(sql.InInts(user.GroupsPrimaryKey[1], ids...)). - Where(sql.InInts(user.GroupsPrimaryKey[0], eids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) } + spec.Edges.Add = append(spec.Edges.Add, edge) } - if len(uuo.groups) > 0 { - values := make([][]int, 0, len(ids)) - for _, id := range ids { - for eid := range uuo.groups { - values = append(values, []int{id, eid}) - } - } - builder := builder.Insert(user.GroupsTable). - Columns(user.GroupsPrimaryKey[1], user.GroupsPrimaryKey[0]) - for _, v := range values { - builder.Values(v[0], v[1]) - } - query, args := builder.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) - } + u = &User{config: uuo.config} + spec.ScanTypes = []interface{}{ + &sql.NullInt64{}, + &sql.NullInt64{}, + &sql.NullString{}, } - if err = tx.Commit(); err != nil { + spec.Assign = func(values ...interface{}) error { + if m, n := len(values), len(spec.ScanTypes); m != n { + return fmt.Errorf("mismatch number of scan values: %d != %d", m, n) + } + value, ok := values[0].(*sql.NullInt64) + if !ok { + return fmt.Errorf("unexpected type %T for field id", value) + } + u.ID = int(value.Int64) + values = values[1:] + if value, ok := values[0].(*sql.NullInt64); !ok { + return fmt.Errorf("unexpected type %T for field age", values[0]) + } else if value.Valid { + u.Age = int(value.Int64) + } + if value, ok := values[1].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field name", values[1]) + } else if value.Valid { + u.Name = value.String + } + return nil + } + if err = sqlgraph.UpdateNode(ctx, uuo.driver, spec); err != nil { + if cerr, ok := isSQLConstraintError(err); ok { + err = cerr + } return nil, err } return u, nil diff --git a/examples/m2mbidi/ent/user_update.go b/examples/m2mbidi/ent/user_update.go index e3f4f892d..e7e87a47b 100644 --- a/examples/m2mbidi/ent/user_update.go +++ b/examples/m2mbidi/ent/user_update.go @@ -11,8 +11,10 @@ import ( "fmt" "github.com/facebookincubator/ent/dialect/sql" + "github.com/facebookincubator/ent/dialect/sql/sqlgraph" "github.com/facebookincubator/ent/examples/m2mbidi/ent/predicate" "github.com/facebookincubator/ent/examples/m2mbidi/ent/user" + "github.com/facebookincubator/ent/schema/field" ) // UserUpdate is the builder for updating User entities. @@ -123,97 +125,89 @@ func (uu *UserUpdate) ExecX(ctx context.Context) { } func (uu *UserUpdate) sqlSave(ctx context.Context) (n int, err error) { - var ( - builder = sql.Dialect(uu.driver.Dialect()) - selector = builder.Select(user.FieldID).From(builder.Table(user.Table)) - ) - for _, p := range uu.predicates { - p(selector) + spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: user.Table, + Columns: user.Columns, + ID: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: user.FieldID, + }, + }, } - rows := &sql.Rows{} - query, args := selector.Query() - if err = uu.driver.Query(ctx, query, args, rows); err != nil { - return 0, err - } - defer rows.Close() - - var ids []int - for rows.Next() { - var id int - if err := rows.Scan(&id); err != nil { - return 0, fmt.Errorf("ent: failed reading id: %v", err) - } - ids = append(ids, id) - } - if len(ids) == 0 { - return 0, nil - } - - tx, err := uu.driver.Tx(ctx) - if err != nil { - return 0, err - } - var ( - res sql.Result - updater = builder.Update(user.Table) - ) - updater = updater.Where(sql.InInts(user.FieldID, ids...)) - if value := uu.age; value != nil { - updater.Set(user.FieldAge, *value) - } - if value := uu.addage; value != nil { - updater.Add(user.FieldAge, *value) - } - if value := uu.name; value != nil { - updater.Set(user.FieldName, *value) - } - if !updater.Empty() { - query, args := updater.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } - } - if len(uu.removedFriends) > 0 { - eids := make([]int, len(uu.removedFriends)) - for eid := range uu.removedFriends { - eids = append(eids, eid) - } - query, args := builder.Delete(user.FriendsTable). - Where(sql.InInts(user.FriendsPrimaryKey[0], ids...)). - Where(sql.InInts(user.FriendsPrimaryKey[1], eids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } - query, args = builder.Delete(user.FriendsTable). - Where(sql.InInts(user.FriendsPrimaryKey[1], ids...)). - Where(sql.InInts(user.FriendsPrimaryKey[0], eids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } - } - if len(uu.friends) > 0 { - values := make([][]int, 0, len(ids)) - for _, id := range ids { - for eid := range uu.friends { - values = append(values, []int{id, eid}, []int{eid, id}) + if ps := uu.predicates; len(ps) > 0 { + spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) } } - builder := builder.Insert(user.FriendsTable). - Columns(user.FriendsPrimaryKey[0], user.FriendsPrimaryKey[1]) - for _, v := range values { - builder.Values(v[0], v[1]) - } - query, args := builder.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } } - if err = tx.Commit(); err != nil { + if value := uu.age; value != nil { + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: *value, + Column: user.FieldAge, + }) + } + if value := uu.addage; value != nil { + spec.Fields.Add = append(spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: *value, + Column: user.FieldAge, + }) + } + if value := uu.name; value != nil { + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: *value, + Column: user.FieldName, + }) + } + if nodes := uu.removedFriends; 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.friends; 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 cerr, ok := isSQLConstraintError(err); ok { + err = cerr + } return 0, err } - return len(ids), nil + return n, nil } // UserUpdateOne is the builder for updating a single User entity. @@ -318,100 +312,108 @@ func (uuo *UserUpdateOne) ExecX(ctx context.Context) { } func (uuo *UserUpdateOne) sqlSave(ctx context.Context) (u *User, err error) { - var ( - builder = sql.Dialect(uuo.driver.Dialect()) - selector = builder.Select(user.Columns...).From(builder.Table(user.Table)) - ) - user.ID(uuo.id)(selector) - rows := &sql.Rows{} - query, args := selector.Query() - if err = uuo.driver.Query(ctx, query, args, rows); err != nil { - return nil, err + spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: user.Table, + Columns: user.Columns, + ID: &sqlgraph.FieldSpec{ + Value: uuo.id, + Type: field.TypeInt, + Column: user.FieldID, + }, + }, } - defer rows.Close() - - var ids []int - for rows.Next() { - var id int - u = &User{config: uuo.config} - if err := u.FromRows(rows); err != nil { - return nil, fmt.Errorf("ent: failed scanning row into User: %v", err) - } - id = u.ID - ids = append(ids, id) - } - switch n := len(ids); { - case n == 0: - return nil, &ErrNotFound{fmt.Sprintf("User with id: %v", uuo.id)} - case n > 1: - return nil, fmt.Errorf("ent: more than one User with the same id: %v", uuo.id) - } - - tx, err := uuo.driver.Tx(ctx) - if err != nil { - return nil, err - } - var ( - res sql.Result - updater = builder.Update(user.Table) - ) - updater = updater.Where(sql.InInts(user.FieldID, ids...)) if value := uuo.age; value != nil { - updater.Set(user.FieldAge, *value) - u.Age = *value + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: *value, + Column: user.FieldAge, + }) } if value := uuo.addage; value != nil { - updater.Add(user.FieldAge, *value) - u.Age += *value + spec.Fields.Add = append(spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: *value, + Column: user.FieldAge, + }) } if value := uuo.name; value != nil { - updater.Set(user.FieldName, *value) - u.Name = *value + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: *value, + Column: user.FieldName, + }) } - if !updater.Empty() { - query, args := updater.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) + if nodes := uuo.removedFriends; 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 len(uuo.removedFriends) > 0 { - eids := make([]int, len(uuo.removedFriends)) - for eid := range uuo.removedFriends { - eids = append(eids, eid) + if nodes := uuo.friends; 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, + }, + }, } - query, args := builder.Delete(user.FriendsTable). - Where(sql.InInts(user.FriendsPrimaryKey[0], ids...)). - Where(sql.InInts(user.FriendsPrimaryKey[1], eids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) - } - query, args = builder.Delete(user.FriendsTable). - Where(sql.InInts(user.FriendsPrimaryKey[1], ids...)). - Where(sql.InInts(user.FriendsPrimaryKey[0], eids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) } + spec.Edges.Add = append(spec.Edges.Add, edge) } - if len(uuo.friends) > 0 { - values := make([][]int, 0, len(ids)) - for _, id := range ids { - for eid := range uuo.friends { - values = append(values, []int{id, eid}, []int{eid, id}) - } - } - builder := builder.Insert(user.FriendsTable). - Columns(user.FriendsPrimaryKey[0], user.FriendsPrimaryKey[1]) - for _, v := range values { - builder.Values(v[0], v[1]) - } - query, args := builder.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) - } + u = &User{config: uuo.config} + spec.ScanTypes = []interface{}{ + &sql.NullInt64{}, + &sql.NullInt64{}, + &sql.NullString{}, } - if err = tx.Commit(); err != nil { + spec.Assign = func(values ...interface{}) error { + if m, n := len(values), len(spec.ScanTypes); m != n { + return fmt.Errorf("mismatch number of scan values: %d != %d", m, n) + } + value, ok := values[0].(*sql.NullInt64) + if !ok { + return fmt.Errorf("unexpected type %T for field id", value) + } + u.ID = int(value.Int64) + values = values[1:] + if value, ok := values[0].(*sql.NullInt64); !ok { + return fmt.Errorf("unexpected type %T for field age", values[0]) + } else if value.Valid { + u.Age = int(value.Int64) + } + if value, ok := values[1].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field name", values[1]) + } else if value.Valid { + u.Name = value.String + } + return nil + } + if err = sqlgraph.UpdateNode(ctx, uuo.driver, spec); err != nil { + if cerr, ok := isSQLConstraintError(err); ok { + err = cerr + } return nil, err } return u, nil diff --git a/examples/m2mrecur/ent/user_update.go b/examples/m2mrecur/ent/user_update.go index c19782b4e..80845fd14 100644 --- a/examples/m2mrecur/ent/user_update.go +++ b/examples/m2mrecur/ent/user_update.go @@ -11,8 +11,10 @@ import ( "fmt" "github.com/facebookincubator/ent/dialect/sql" + "github.com/facebookincubator/ent/dialect/sql/sqlgraph" "github.com/facebookincubator/ent/examples/m2mrecur/ent/predicate" "github.com/facebookincubator/ent/examples/m2mrecur/ent/user" + "github.com/facebookincubator/ent/schema/field" ) // UserUpdate is the builder for updating User entities. @@ -165,120 +167,127 @@ func (uu *UserUpdate) ExecX(ctx context.Context) { } func (uu *UserUpdate) sqlSave(ctx context.Context) (n int, err error) { - var ( - builder = sql.Dialect(uu.driver.Dialect()) - selector = builder.Select(user.FieldID).From(builder.Table(user.Table)) - ) - for _, p := range uu.predicates { - p(selector) + spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: user.Table, + Columns: user.Columns, + ID: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: user.FieldID, + }, + }, } - rows := &sql.Rows{} - query, args := selector.Query() - if err = uu.driver.Query(ctx, query, args, rows); err != nil { - return 0, err - } - defer rows.Close() - - var ids []int - for rows.Next() { - var id int - if err := rows.Scan(&id); err != nil { - return 0, fmt.Errorf("ent: failed reading id: %v", err) + if ps := uu.predicates; len(ps) > 0 { + spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } } - ids = append(ids, id) } - if len(ids) == 0 { - return 0, nil - } - - tx, err := uu.driver.Tx(ctx) - if err != nil { - return 0, err - } - var ( - res sql.Result - updater = builder.Update(user.Table) - ) - updater = updater.Where(sql.InInts(user.FieldID, ids...)) if value := uu.age; value != nil { - updater.Set(user.FieldAge, *value) + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: *value, + Column: user.FieldAge, + }) } if value := uu.addage; value != nil { - updater.Add(user.FieldAge, *value) + spec.Fields.Add = append(spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: *value, + Column: user.FieldAge, + }) } if value := uu.name; value != nil { - updater.Set(user.FieldName, *value) + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: *value, + Column: user.FieldName, + }) } - if !updater.Empty() { - query, args := updater.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) + if nodes := uu.removedFollowers; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: true, + Table: user.FollowersTable, + Columns: user.FollowersPrimaryKey, + Bidi: false, + 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 len(uu.removedFollowers) > 0 { - eids := make([]int, len(uu.removedFollowers)) - for eid := range uu.removedFollowers { - eids = append(eids, eid) + if nodes := uu.followers; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: true, + Table: user.FollowersTable, + Columns: user.FollowersPrimaryKey, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: user.FieldID, + }, + }, } - query, args := builder.Delete(user.FollowersTable). - Where(sql.InInts(user.FollowersPrimaryKey[1], ids...)). - Where(sql.InInts(user.FollowersPrimaryKey[0], eids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) } + spec.Edges.Add = append(spec.Edges.Add, edge) } - if len(uu.followers) > 0 { - values := make([][]int, 0, len(ids)) - for _, id := range ids { - for eid := range uu.followers { - values = append(values, []int{id, eid}) - } + if nodes := uu.removedFollowing; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: false, + Table: user.FollowingTable, + Columns: user.FollowingPrimaryKey, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: user.FieldID, + }, + }, } - builder := builder.Insert(user.FollowersTable). - Columns(user.FollowersPrimaryKey[1], user.FollowersPrimaryKey[0]) - for _, v := range values { - builder.Values(v[0], v[1]) - } - query, args := builder.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) } + spec.Edges.Clear = append(spec.Edges.Clear, edge) } - if len(uu.removedFollowing) > 0 { - eids := make([]int, len(uu.removedFollowing)) - for eid := range uu.removedFollowing { - eids = append(eids, eid) + if nodes := uu.following; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: false, + Table: user.FollowingTable, + Columns: user.FollowingPrimaryKey, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: user.FieldID, + }, + }, } - query, args := builder.Delete(user.FollowingTable). - Where(sql.InInts(user.FollowingPrimaryKey[0], ids...)). - Where(sql.InInts(user.FollowingPrimaryKey[1], eids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) } + spec.Edges.Add = append(spec.Edges.Add, edge) } - if len(uu.following) > 0 { - values := make([][]int, 0, len(ids)) - for _, id := range ids { - for eid := range uu.following { - values = append(values, []int{id, eid}) - } + if n, err = sqlgraph.UpdateNodes(ctx, uu.driver, spec); err != nil { + if cerr, ok := isSQLConstraintError(err); ok { + err = cerr } - builder := builder.Insert(user.FollowingTable). - Columns(user.FollowingPrimaryKey[0], user.FollowingPrimaryKey[1]) - for _, v := range values { - builder.Values(v[0], v[1]) - } - query, args := builder.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } - } - if err = tx.Commit(); err != nil { return 0, err } - return len(ids), nil + return n, nil } // UserUpdateOne is the builder for updating a single User entity. @@ -425,123 +434,146 @@ func (uuo *UserUpdateOne) ExecX(ctx context.Context) { } func (uuo *UserUpdateOne) sqlSave(ctx context.Context) (u *User, err error) { - var ( - builder = sql.Dialect(uuo.driver.Dialect()) - selector = builder.Select(user.Columns...).From(builder.Table(user.Table)) - ) - user.ID(uuo.id)(selector) - rows := &sql.Rows{} - query, args := selector.Query() - if err = uuo.driver.Query(ctx, query, args, rows); err != nil { - return nil, err + spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: user.Table, + Columns: user.Columns, + ID: &sqlgraph.FieldSpec{ + Value: uuo.id, + Type: field.TypeInt, + Column: user.FieldID, + }, + }, } - defer rows.Close() - - var ids []int - for rows.Next() { - var id int - u = &User{config: uuo.config} - if err := u.FromRows(rows); err != nil { - return nil, fmt.Errorf("ent: failed scanning row into User: %v", err) - } - id = u.ID - ids = append(ids, id) - } - switch n := len(ids); { - case n == 0: - return nil, &ErrNotFound{fmt.Sprintf("User with id: %v", uuo.id)} - case n > 1: - return nil, fmt.Errorf("ent: more than one User with the same id: %v", uuo.id) - } - - tx, err := uuo.driver.Tx(ctx) - if err != nil { - return nil, err - } - var ( - res sql.Result - updater = builder.Update(user.Table) - ) - updater = updater.Where(sql.InInts(user.FieldID, ids...)) if value := uuo.age; value != nil { - updater.Set(user.FieldAge, *value) - u.Age = *value + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: *value, + Column: user.FieldAge, + }) } if value := uuo.addage; value != nil { - updater.Add(user.FieldAge, *value) - u.Age += *value + spec.Fields.Add = append(spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: *value, + Column: user.FieldAge, + }) } if value := uuo.name; value != nil { - updater.Set(user.FieldName, *value) - u.Name = *value + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: *value, + Column: user.FieldName, + }) } - if !updater.Empty() { - query, args := updater.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) + if nodes := uuo.removedFollowers; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: true, + Table: user.FollowersTable, + Columns: user.FollowersPrimaryKey, + Bidi: false, + 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 len(uuo.removedFollowers) > 0 { - eids := make([]int, len(uuo.removedFollowers)) - for eid := range uuo.removedFollowers { - eids = append(eids, eid) + if nodes := uuo.followers; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: true, + Table: user.FollowersTable, + Columns: user.FollowersPrimaryKey, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: user.FieldID, + }, + }, } - query, args := builder.Delete(user.FollowersTable). - Where(sql.InInts(user.FollowersPrimaryKey[1], ids...)). - Where(sql.InInts(user.FollowersPrimaryKey[0], eids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) } + spec.Edges.Add = append(spec.Edges.Add, edge) } - if len(uuo.followers) > 0 { - values := make([][]int, 0, len(ids)) - for _, id := range ids { - for eid := range uuo.followers { - values = append(values, []int{id, eid}) - } + if nodes := uuo.removedFollowing; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: false, + Table: user.FollowingTable, + Columns: user.FollowingPrimaryKey, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: user.FieldID, + }, + }, } - builder := builder.Insert(user.FollowersTable). - Columns(user.FollowersPrimaryKey[1], user.FollowersPrimaryKey[0]) - for _, v := range values { - builder.Values(v[0], v[1]) - } - query, args := builder.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) } + spec.Edges.Clear = append(spec.Edges.Clear, edge) } - if len(uuo.removedFollowing) > 0 { - eids := make([]int, len(uuo.removedFollowing)) - for eid := range uuo.removedFollowing { - eids = append(eids, eid) + if nodes := uuo.following; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: false, + Table: user.FollowingTable, + Columns: user.FollowingPrimaryKey, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: user.FieldID, + }, + }, } - query, args := builder.Delete(user.FollowingTable). - Where(sql.InInts(user.FollowingPrimaryKey[0], ids...)). - Where(sql.InInts(user.FollowingPrimaryKey[1], eids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) } + spec.Edges.Add = append(spec.Edges.Add, edge) } - if len(uuo.following) > 0 { - values := make([][]int, 0, len(ids)) - for _, id := range ids { - for eid := range uuo.following { - values = append(values, []int{id, eid}) - } - } - builder := builder.Insert(user.FollowingTable). - Columns(user.FollowingPrimaryKey[0], user.FollowingPrimaryKey[1]) - for _, v := range values { - builder.Values(v[0], v[1]) - } - query, args := builder.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) - } + u = &User{config: uuo.config} + spec.ScanTypes = []interface{}{ + &sql.NullInt64{}, + &sql.NullInt64{}, + &sql.NullString{}, } - if err = tx.Commit(); err != nil { + spec.Assign = func(values ...interface{}) error { + if m, n := len(values), len(spec.ScanTypes); m != n { + return fmt.Errorf("mismatch number of scan values: %d != %d", m, n) + } + value, ok := values[0].(*sql.NullInt64) + if !ok { + return fmt.Errorf("unexpected type %T for field id", value) + } + u.ID = int(value.Int64) + values = values[1:] + if value, ok := values[0].(*sql.NullInt64); !ok { + return fmt.Errorf("unexpected type %T for field age", values[0]) + } else if value.Valid { + u.Age = int(value.Int64) + } + if value, ok := values[1].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field name", values[1]) + } else if value.Valid { + u.Name = value.String + } + return nil + } + if err = sqlgraph.UpdateNode(ctx, uuo.driver, spec); err != nil { + if cerr, ok := isSQLConstraintError(err); ok { + err = cerr + } return nil, err } return u, nil diff --git a/examples/o2m2types/ent/pet_update.go b/examples/o2m2types/ent/pet_update.go index c2e24a06e..a8683c024 100644 --- a/examples/o2m2types/ent/pet_update.go +++ b/examples/o2m2types/ent/pet_update.go @@ -12,9 +12,11 @@ import ( "fmt" "github.com/facebookincubator/ent/dialect/sql" + "github.com/facebookincubator/ent/dialect/sql/sqlgraph" "github.com/facebookincubator/ent/examples/o2m2types/ent/pet" "github.com/facebookincubator/ent/examples/o2m2types/ent/predicate" "github.com/facebookincubator/ent/examples/o2m2types/ent/user" + "github.com/facebookincubator/ent/schema/field" ) // PetUpdate is the builder for updating Pet entities. @@ -97,74 +99,72 @@ func (pu *PetUpdate) ExecX(ctx context.Context) { } func (pu *PetUpdate) sqlSave(ctx context.Context) (n int, err error) { - var ( - builder = sql.Dialect(pu.driver.Dialect()) - selector = builder.Select(pet.FieldID).From(builder.Table(pet.Table)) - ) - for _, p := range pu.predicates { - p(selector) + spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: pet.Table, + Columns: pet.Columns, + ID: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: pet.FieldID, + }, + }, } - rows := &sql.Rows{} - query, args := selector.Query() - if err = pu.driver.Query(ctx, query, args, rows); err != nil { - return 0, err - } - defer rows.Close() - - var ids []int - for rows.Next() { - var id int - if err := rows.Scan(&id); err != nil { - return 0, fmt.Errorf("ent: failed reading id: %v", err) - } - ids = append(ids, id) - } - if len(ids) == 0 { - return 0, nil - } - - tx, err := pu.driver.Tx(ctx) - if err != nil { - return 0, err - } - var ( - res sql.Result - updater = builder.Update(pet.Table) - ) - updater = updater.Where(sql.InInts(pet.FieldID, ids...)) - if value := pu.name; value != nil { - updater.Set(pet.FieldName, *value) - } - if !updater.Empty() { - query, args := updater.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } - } - if pu.clearedOwner { - query, args := builder.Update(pet.OwnerTable). - SetNull(pet.OwnerColumn). - Where(sql.InInts(user.FieldID, ids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } - } - if len(pu.owner) > 0 { - for eid := range pu.owner { - query, args := builder.Update(pet.OwnerTable). - Set(pet.OwnerColumn, eid). - Where(sql.InInts(pet.FieldID, ids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) + if ps := pu.predicates; len(ps) > 0 { + spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) } } } - if err = tx.Commit(); err != nil { + if value := pu.name; value != nil { + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: *value, + Column: pet.FieldName, + }) + } + if pu.clearedOwner { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: pet.OwnerTable, + Columns: []string{pet.OwnerColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: user.FieldID, + }, + }, + } + spec.Edges.Clear = append(spec.Edges.Clear, edge) + } + if nodes := pu.owner; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: pet.OwnerTable, + Columns: []string{pet.OwnerColumn}, + Bidi: false, + 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, pu.driver, spec); err != nil { + if cerr, ok := isSQLConstraintError(err); ok { + err = cerr + } return 0, err } - return len(ids), nil + return n, nil } // PetUpdateOne is the builder for updating a single Pet entity. @@ -241,75 +241,85 @@ func (puo *PetUpdateOne) ExecX(ctx context.Context) { } func (puo *PetUpdateOne) sqlSave(ctx context.Context) (pe *Pet, err error) { - var ( - builder = sql.Dialect(puo.driver.Dialect()) - selector = builder.Select(pet.Columns...).From(builder.Table(pet.Table)) - ) - pet.ID(puo.id)(selector) - rows := &sql.Rows{} - query, args := selector.Query() - if err = puo.driver.Query(ctx, query, args, rows); err != nil { - return nil, err + spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: pet.Table, + Columns: pet.Columns, + ID: &sqlgraph.FieldSpec{ + Value: puo.id, + Type: field.TypeInt, + Column: pet.FieldID, + }, + }, } - defer rows.Close() - - var ids []int - for rows.Next() { - var id int - pe = &Pet{config: puo.config} - if err := pe.FromRows(rows); err != nil { - return nil, fmt.Errorf("ent: failed scanning row into Pet: %v", err) - } - id = pe.ID - ids = append(ids, id) - } - switch n := len(ids); { - case n == 0: - return nil, &ErrNotFound{fmt.Sprintf("Pet with id: %v", puo.id)} - case n > 1: - return nil, fmt.Errorf("ent: more than one Pet with the same id: %v", puo.id) - } - - tx, err := puo.driver.Tx(ctx) - if err != nil { - return nil, err - } - var ( - res sql.Result - updater = builder.Update(pet.Table) - ) - updater = updater.Where(sql.InInts(pet.FieldID, ids...)) if value := puo.name; value != nil { - updater.Set(pet.FieldName, *value) - pe.Name = *value - } - if !updater.Empty() { - query, args := updater.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) - } + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: *value, + Column: pet.FieldName, + }) } if puo.clearedOwner { - query, args := builder.Update(pet.OwnerTable). - SetNull(pet.OwnerColumn). - Where(sql.InInts(user.FieldID, ids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: pet.OwnerTable, + Columns: []string{pet.OwnerColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: user.FieldID, + }, + }, } + spec.Edges.Clear = append(spec.Edges.Clear, edge) } - if len(puo.owner) > 0 { - for eid := range puo.owner { - query, args := builder.Update(pet.OwnerTable). - Set(pet.OwnerColumn, eid). - Where(sql.InInts(pet.FieldID, ids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) - } + if nodes := puo.owner; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: pet.OwnerTable, + Columns: []string{pet.OwnerColumn}, + Bidi: false, + 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 err = tx.Commit(); err != nil { + pe = &Pet{config: puo.config} + spec.ScanTypes = []interface{}{ + &sql.NullInt64{}, + &sql.NullString{}, + } + spec.Assign = func(values ...interface{}) error { + if m, n := len(values), len(spec.ScanTypes); m != n { + return fmt.Errorf("mismatch number of scan values: %d != %d", m, n) + } + value, ok := values[0].(*sql.NullInt64) + if !ok { + return fmt.Errorf("unexpected type %T for field id", value) + } + pe.ID = int(value.Int64) + values = values[1:] + if value, ok := values[0].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field name", values[0]) + } else if value.Valid { + pe.Name = value.String + } + return nil + } + if err = sqlgraph.UpdateNode(ctx, puo.driver, spec); err != nil { + if cerr, ok := isSQLConstraintError(err); ok { + err = cerr + } return nil, err } return pe, nil diff --git a/examples/o2m2types/ent/user_update.go b/examples/o2m2types/ent/user_update.go index 1c4ed8e3c..566c21930 100644 --- a/examples/o2m2types/ent/user_update.go +++ b/examples/o2m2types/ent/user_update.go @@ -11,9 +11,11 @@ import ( "fmt" "github.com/facebookincubator/ent/dialect/sql" + "github.com/facebookincubator/ent/dialect/sql/sqlgraph" "github.com/facebookincubator/ent/examples/o2m2types/ent/pet" "github.com/facebookincubator/ent/examples/o2m2types/ent/predicate" "github.com/facebookincubator/ent/examples/o2m2types/ent/user" + "github.com/facebookincubator/ent/schema/field" ) // UserUpdate is the builder for updating User entities. @@ -124,96 +126,89 @@ func (uu *UserUpdate) ExecX(ctx context.Context) { } func (uu *UserUpdate) sqlSave(ctx context.Context) (n int, err error) { - var ( - builder = sql.Dialect(uu.driver.Dialect()) - selector = builder.Select(user.FieldID).From(builder.Table(user.Table)) - ) - for _, p := range uu.predicates { - p(selector) + spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: user.Table, + Columns: user.Columns, + ID: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: user.FieldID, + }, + }, } - rows := &sql.Rows{} - query, args := selector.Query() - if err = uu.driver.Query(ctx, query, args, rows); err != nil { - return 0, err - } - defer rows.Close() - - var ids []int - for rows.Next() { - var id int - if err := rows.Scan(&id); err != nil { - return 0, fmt.Errorf("ent: failed reading id: %v", err) + if ps := uu.predicates; len(ps) > 0 { + spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } } - ids = append(ids, id) } - if len(ids) == 0 { - return 0, nil - } - - tx, err := uu.driver.Tx(ctx) - if err != nil { - return 0, err - } - var ( - res sql.Result - updater = builder.Update(user.Table) - ) - updater = updater.Where(sql.InInts(user.FieldID, ids...)) if value := uu.age; value != nil { - updater.Set(user.FieldAge, *value) + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: *value, + Column: user.FieldAge, + }) } if value := uu.addage; value != nil { - updater.Add(user.FieldAge, *value) + spec.Fields.Add = append(spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: *value, + Column: user.FieldAge, + }) } if value := uu.name; value != nil { - updater.Set(user.FieldName, *value) + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: *value, + Column: user.FieldName, + }) } - if !updater.Empty() { - query, args := updater.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) + if nodes := uu.removedPets; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: user.PetsTable, + Columns: []string{user.PetsColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: pet.FieldID, + }, + }, } + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + spec.Edges.Clear = append(spec.Edges.Clear, edge) } - if len(uu.removedPets) > 0 { - eids := make([]int, len(uu.removedPets)) - for eid := range uu.removedPets { - eids = append(eids, eid) + if nodes := uu.pets; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: user.PetsTable, + Columns: []string{user.PetsColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: pet.FieldID, + }, + }, } - query, args := builder.Update(user.PetsTable). - SetNull(user.PetsColumn). - Where(sql.InInts(user.PetsColumn, ids...)). - Where(sql.InInts(pet.FieldID, eids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) } + spec.Edges.Add = append(spec.Edges.Add, edge) } - if len(uu.pets) > 0 { - for _, id := range ids { - p := sql.P() - for eid := range uu.pets { - p.Or().EQ(pet.FieldID, eid) - } - query, args := builder.Update(user.PetsTable). - Set(user.PetsColumn, id). - Where(sql.And(p, sql.IsNull(user.PetsColumn))). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } - affected, err := res.RowsAffected() - if err != nil { - return 0, rollback(tx, err) - } - if int(affected) < len(uu.pets) { - return 0, rollback(tx, &ConstraintError{msg: fmt.Sprintf("one of \"pets\" %v already connected to a different \"User\"", keys(uu.pets))}) - } + if n, err = sqlgraph.UpdateNodes(ctx, uu.driver, spec); err != nil { + if cerr, ok := isSQLConstraintError(err); ok { + err = cerr } - } - if err = tx.Commit(); err != nil { return 0, err } - return len(ids), nil + return n, nil } // UserUpdateOne is the builder for updating a single User entity. @@ -318,99 +313,108 @@ func (uuo *UserUpdateOne) ExecX(ctx context.Context) { } func (uuo *UserUpdateOne) sqlSave(ctx context.Context) (u *User, err error) { - var ( - builder = sql.Dialect(uuo.driver.Dialect()) - selector = builder.Select(user.Columns...).From(builder.Table(user.Table)) - ) - user.ID(uuo.id)(selector) - rows := &sql.Rows{} - query, args := selector.Query() - if err = uuo.driver.Query(ctx, query, args, rows); err != nil { - return nil, err + spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: user.Table, + Columns: user.Columns, + ID: &sqlgraph.FieldSpec{ + Value: uuo.id, + Type: field.TypeInt, + Column: user.FieldID, + }, + }, } - defer rows.Close() - - var ids []int - for rows.Next() { - var id int - u = &User{config: uuo.config} - if err := u.FromRows(rows); err != nil { - return nil, fmt.Errorf("ent: failed scanning row into User: %v", err) - } - id = u.ID - ids = append(ids, id) - } - switch n := len(ids); { - case n == 0: - return nil, &ErrNotFound{fmt.Sprintf("User with id: %v", uuo.id)} - case n > 1: - return nil, fmt.Errorf("ent: more than one User with the same id: %v", uuo.id) - } - - tx, err := uuo.driver.Tx(ctx) - if err != nil { - return nil, err - } - var ( - res sql.Result - updater = builder.Update(user.Table) - ) - updater = updater.Where(sql.InInts(user.FieldID, ids...)) if value := uuo.age; value != nil { - updater.Set(user.FieldAge, *value) - u.Age = *value + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: *value, + Column: user.FieldAge, + }) } if value := uuo.addage; value != nil { - updater.Add(user.FieldAge, *value) - u.Age += *value + spec.Fields.Add = append(spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: *value, + Column: user.FieldAge, + }) } if value := uuo.name; value != nil { - updater.Set(user.FieldName, *value) - u.Name = *value + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: *value, + Column: user.FieldName, + }) } - if !updater.Empty() { - query, args := updater.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) + if nodes := uuo.removedPets; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: user.PetsTable, + Columns: []string{user.PetsColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: pet.FieldID, + }, + }, } + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + spec.Edges.Clear = append(spec.Edges.Clear, edge) } - if len(uuo.removedPets) > 0 { - eids := make([]int, len(uuo.removedPets)) - for eid := range uuo.removedPets { - eids = append(eids, eid) + if nodes := uuo.pets; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: user.PetsTable, + Columns: []string{user.PetsColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: pet.FieldID, + }, + }, } - query, args := builder.Update(user.PetsTable). - SetNull(user.PetsColumn). - Where(sql.InInts(user.PetsColumn, ids...)). - Where(sql.InInts(pet.FieldID, eids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) } + spec.Edges.Add = append(spec.Edges.Add, edge) } - if len(uuo.pets) > 0 { - for _, id := range ids { - p := sql.P() - for eid := range uuo.pets { - p.Or().EQ(pet.FieldID, eid) - } - query, args := builder.Update(user.PetsTable). - Set(user.PetsColumn, id). - Where(sql.And(p, sql.IsNull(user.PetsColumn))). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) - } - affected, err := res.RowsAffected() - if err != nil { - return nil, rollback(tx, err) - } - if int(affected) < len(uuo.pets) { - return nil, rollback(tx, &ConstraintError{msg: fmt.Sprintf("one of \"pets\" %v already connected to a different \"User\"", keys(uuo.pets))}) - } - } + u = &User{config: uuo.config} + spec.ScanTypes = []interface{}{ + &sql.NullInt64{}, + &sql.NullInt64{}, + &sql.NullString{}, } - if err = tx.Commit(); err != nil { + spec.Assign = func(values ...interface{}) error { + if m, n := len(values), len(spec.ScanTypes); m != n { + return fmt.Errorf("mismatch number of scan values: %d != %d", m, n) + } + value, ok := values[0].(*sql.NullInt64) + if !ok { + return fmt.Errorf("unexpected type %T for field id", value) + } + u.ID = int(value.Int64) + values = values[1:] + if value, ok := values[0].(*sql.NullInt64); !ok { + return fmt.Errorf("unexpected type %T for field age", values[0]) + } else if value.Valid { + u.Age = int(value.Int64) + } + if value, ok := values[1].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field name", values[1]) + } else if value.Valid { + u.Name = value.String + } + return nil + } + if err = sqlgraph.UpdateNode(ctx, uuo.driver, spec); err != nil { + if cerr, ok := isSQLConstraintError(err); ok { + err = cerr + } return nil, err } return u, nil diff --git a/examples/o2mrecur/ent/node_update.go b/examples/o2mrecur/ent/node_update.go index 752f33a35..67cdac708 100644 --- a/examples/o2mrecur/ent/node_update.go +++ b/examples/o2mrecur/ent/node_update.go @@ -12,8 +12,10 @@ import ( "fmt" "github.com/facebookincubator/ent/dialect/sql" + "github.com/facebookincubator/ent/dialect/sql/sqlgraph" "github.com/facebookincubator/ent/examples/o2mrecur/ent/node" "github.com/facebookincubator/ent/examples/o2mrecur/ent/predicate" + "github.com/facebookincubator/ent/schema/field" ) // NodeUpdate is the builder for updating Node entities. @@ -150,113 +152,117 @@ func (nu *NodeUpdate) ExecX(ctx context.Context) { } func (nu *NodeUpdate) sqlSave(ctx context.Context) (n int, err error) { - var ( - builder = sql.Dialect(nu.driver.Dialect()) - selector = builder.Select(node.FieldID).From(builder.Table(node.Table)) - ) - for _, p := range nu.predicates { - p(selector) + spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: node.Table, + Columns: node.Columns, + ID: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: node.FieldID, + }, + }, } - rows := &sql.Rows{} - query, args := selector.Query() - if err = nu.driver.Query(ctx, query, args, rows); err != nil { - return 0, err - } - defer rows.Close() - - var ids []int - for rows.Next() { - var id int - if err := rows.Scan(&id); err != nil { - return 0, fmt.Errorf("ent: failed reading id: %v", err) + if ps := nu.predicates; len(ps) > 0 { + spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } } - ids = append(ids, id) } - if len(ids) == 0 { - return 0, nil - } - - tx, err := nu.driver.Tx(ctx) - if err != nil { - return 0, err - } - var ( - res sql.Result - updater = builder.Update(node.Table) - ) - updater = updater.Where(sql.InInts(node.FieldID, ids...)) if value := nu.value; value != nil { - updater.Set(node.FieldValue, *value) + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: *value, + Column: node.FieldValue, + }) } if value := nu.addvalue; value != nil { - updater.Add(node.FieldValue, *value) - } - if !updater.Empty() { - query, args := updater.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } + spec.Fields.Add = append(spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: *value, + Column: node.FieldValue, + }) } if nu.clearedParent { - query, args := builder.Update(node.ParentTable). - SetNull(node.ParentColumn). - Where(sql.InInts(node.FieldID, ids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: node.ParentTable, + Columns: []string{node.ParentColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: node.FieldID, + }, + }, } + spec.Edges.Clear = append(spec.Edges.Clear, edge) } - if len(nu.parent) > 0 { - for eid := range nu.parent { - query, args := builder.Update(node.ParentTable). - Set(node.ParentColumn, eid). - Where(sql.InInts(node.FieldID, ids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } + if nodes := nu.parent; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: node.ParentTable, + Columns: []string{node.ParentColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: node.FieldID, + }, + }, } + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + spec.Edges.Add = append(spec.Edges.Add, edge) } - if len(nu.removedChildren) > 0 { - eids := make([]int, len(nu.removedChildren)) - for eid := range nu.removedChildren { - eids = append(eids, eid) + if nodes := nu.removedChildren; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: node.ChildrenTable, + Columns: []string{node.ChildrenColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: node.FieldID, + }, + }, } - query, args := builder.Update(node.ChildrenTable). - SetNull(node.ChildrenColumn). - Where(sql.InInts(node.ChildrenColumn, ids...)). - Where(sql.InInts(node.FieldID, eids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) } + spec.Edges.Clear = append(spec.Edges.Clear, edge) } - if len(nu.children) > 0 { - for _, id := range ids { - p := sql.P() - for eid := range nu.children { - p.Or().EQ(node.FieldID, eid) - } - query, args := builder.Update(node.ChildrenTable). - Set(node.ChildrenColumn, id). - Where(sql.And(p, sql.IsNull(node.ChildrenColumn))). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } - affected, err := res.RowsAffected() - if err != nil { - return 0, rollback(tx, err) - } - if int(affected) < len(nu.children) { - return 0, rollback(tx, &ConstraintError{msg: fmt.Sprintf("one of \"children\" %v already connected to a different \"Node\"", keys(nu.children))}) - } + if nodes := nu.children; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: node.ChildrenTable, + Columns: []string{node.ChildrenColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: node.FieldID, + }, + }, } + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + spec.Edges.Add = append(spec.Edges.Add, edge) } - if err = tx.Commit(); err != nil { + if n, err = sqlgraph.UpdateNodes(ctx, nu.driver, spec); err != nil { + if cerr, ok := isSQLConstraintError(err); ok { + err = cerr + } return 0, err } - return len(ids), nil + return n, nil } // NodeUpdateOne is the builder for updating a single Node entity. @@ -387,115 +393,130 @@ func (nuo *NodeUpdateOne) ExecX(ctx context.Context) { } func (nuo *NodeUpdateOne) sqlSave(ctx context.Context) (n *Node, err error) { - var ( - builder = sql.Dialect(nuo.driver.Dialect()) - selector = builder.Select(node.Columns...).From(builder.Table(node.Table)) - ) - node.ID(nuo.id)(selector) - rows := &sql.Rows{} - query, args := selector.Query() - if err = nuo.driver.Query(ctx, query, args, rows); err != nil { - return nil, err + spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: node.Table, + Columns: node.Columns, + ID: &sqlgraph.FieldSpec{ + Value: nuo.id, + Type: field.TypeInt, + Column: node.FieldID, + }, + }, } - defer rows.Close() - - var ids []int - for rows.Next() { - var id int - n = &Node{config: nuo.config} - if err := n.FromRows(rows); err != nil { - return nil, fmt.Errorf("ent: failed scanning row into Node: %v", err) - } - id = n.ID - ids = append(ids, id) - } - switch n := len(ids); { - case n == 0: - return nil, &ErrNotFound{fmt.Sprintf("Node with id: %v", nuo.id)} - case n > 1: - return nil, fmt.Errorf("ent: more than one Node with the same id: %v", nuo.id) - } - - tx, err := nuo.driver.Tx(ctx) - if err != nil { - return nil, err - } - var ( - res sql.Result - updater = builder.Update(node.Table) - ) - updater = updater.Where(sql.InInts(node.FieldID, ids...)) if value := nuo.value; value != nil { - updater.Set(node.FieldValue, *value) - n.Value = *value + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: *value, + Column: node.FieldValue, + }) } if value := nuo.addvalue; value != nil { - updater.Add(node.FieldValue, *value) - n.Value += *value - } - if !updater.Empty() { - query, args := updater.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) - } + spec.Fields.Add = append(spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: *value, + Column: node.FieldValue, + }) } if nuo.clearedParent { - query, args := builder.Update(node.ParentTable). - SetNull(node.ParentColumn). - Where(sql.InInts(node.FieldID, ids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: node.ParentTable, + Columns: []string{node.ParentColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: node.FieldID, + }, + }, } + spec.Edges.Clear = append(spec.Edges.Clear, edge) } - if len(nuo.parent) > 0 { - for eid := range nuo.parent { - query, args := builder.Update(node.ParentTable). - Set(node.ParentColumn, eid). - Where(sql.InInts(node.FieldID, ids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) - } + if nodes := nuo.parent; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: node.ParentTable, + Columns: []string{node.ParentColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: node.FieldID, + }, + }, } + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + spec.Edges.Add = append(spec.Edges.Add, edge) } - if len(nuo.removedChildren) > 0 { - eids := make([]int, len(nuo.removedChildren)) - for eid := range nuo.removedChildren { - eids = append(eids, eid) + if nodes := nuo.removedChildren; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: node.ChildrenTable, + Columns: []string{node.ChildrenColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: node.FieldID, + }, + }, } - query, args := builder.Update(node.ChildrenTable). - SetNull(node.ChildrenColumn). - Where(sql.InInts(node.ChildrenColumn, ids...)). - Where(sql.InInts(node.FieldID, eids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) } + spec.Edges.Clear = append(spec.Edges.Clear, edge) } - if len(nuo.children) > 0 { - for _, id := range ids { - p := sql.P() - for eid := range nuo.children { - p.Or().EQ(node.FieldID, eid) - } - query, args := builder.Update(node.ChildrenTable). - Set(node.ChildrenColumn, id). - Where(sql.And(p, sql.IsNull(node.ChildrenColumn))). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) - } - affected, err := res.RowsAffected() - if err != nil { - return nil, rollback(tx, err) - } - if int(affected) < len(nuo.children) { - return nil, rollback(tx, &ConstraintError{msg: fmt.Sprintf("one of \"children\" %v already connected to a different \"Node\"", keys(nuo.children))}) - } + if nodes := nuo.children; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: node.ChildrenTable, + Columns: []string{node.ChildrenColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: node.FieldID, + }, + }, } + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + spec.Edges.Add = append(spec.Edges.Add, edge) } - if err = tx.Commit(); err != nil { + n = &Node{config: nuo.config} + spec.ScanTypes = []interface{}{ + &sql.NullInt64{}, + &sql.NullInt64{}, + } + spec.Assign = func(values ...interface{}) error { + if m, n := len(values), len(spec.ScanTypes); m != n { + return fmt.Errorf("mismatch number of scan values: %d != %d", m, n) + } + value, ok := values[0].(*sql.NullInt64) + if !ok { + return fmt.Errorf("unexpected type %T for field id", value) + } + n.ID = int(value.Int64) + values = values[1:] + if value, ok := values[0].(*sql.NullInt64); !ok { + return fmt.Errorf("unexpected type %T for field value", values[0]) + } else if value.Valid { + n.Value = int(value.Int64) + } + return nil + } + if err = sqlgraph.UpdateNode(ctx, nuo.driver, spec); err != nil { + if cerr, ok := isSQLConstraintError(err); ok { + err = cerr + } return nil, err } return n, nil diff --git a/examples/o2o2types/ent/card_update.go b/examples/o2o2types/ent/card_update.go index 7d56af2a6..9acff830b 100644 --- a/examples/o2o2types/ent/card_update.go +++ b/examples/o2o2types/ent/card_update.go @@ -13,9 +13,11 @@ import ( "time" "github.com/facebookincubator/ent/dialect/sql" + "github.com/facebookincubator/ent/dialect/sql/sqlgraph" "github.com/facebookincubator/ent/examples/o2o2types/ent/card" "github.com/facebookincubator/ent/examples/o2o2types/ent/predicate" "github.com/facebookincubator/ent/examples/o2o2types/ent/user" + "github.com/facebookincubator/ent/schema/field" ) // CardUpdate is the builder for updating Card entities. @@ -100,85 +102,79 @@ func (cu *CardUpdate) ExecX(ctx context.Context) { } func (cu *CardUpdate) sqlSave(ctx context.Context) (n int, err error) { - var ( - builder = sql.Dialect(cu.driver.Dialect()) - selector = builder.Select(card.FieldID).From(builder.Table(card.Table)) - ) - for _, p := range cu.predicates { - p(selector) + spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: card.Table, + Columns: card.Columns, + ID: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: card.FieldID, + }, + }, } - rows := &sql.Rows{} - query, args := selector.Query() - if err = cu.driver.Query(ctx, query, args, rows); err != nil { - return 0, err - } - defer rows.Close() - - var ids []int - for rows.Next() { - var id int - if err := rows.Scan(&id); err != nil { - return 0, fmt.Errorf("ent: failed reading id: %v", err) + if ps := cu.predicates; len(ps) > 0 { + spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } } - ids = append(ids, id) } - if len(ids) == 0 { - return 0, nil - } - - tx, err := cu.driver.Tx(ctx) - if err != nil { - return 0, err - } - var ( - res sql.Result - updater = builder.Update(card.Table) - ) - updater = updater.Where(sql.InInts(card.FieldID, ids...)) if value := cu.expired; value != nil { - updater.Set(card.FieldExpired, *value) + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeTime, + Value: *value, + Column: card.FieldExpired, + }) } if value := cu.number; value != nil { - updater.Set(card.FieldNumber, *value) - } - if !updater.Empty() { - query, args := updater.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: *value, + Column: card.FieldNumber, + }) } if cu.clearedOwner { - query, args := builder.Update(card.OwnerTable). - SetNull(card.OwnerColumn). - Where(sql.InInts(user.FieldID, ids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2O, + Inverse: true, + Table: card.OwnerTable, + Columns: []string{card.OwnerColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: user.FieldID, + }, + }, } + spec.Edges.Clear = append(spec.Edges.Clear, edge) } - if len(cu.owner) > 0 { - for _, id := range ids { - eid := keys(cu.owner)[0] - query, args := builder.Update(card.OwnerTable). - Set(card.OwnerColumn, eid). - Where(sql.EQ(card.FieldID, id).And().IsNull(card.OwnerColumn)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } - affected, err := res.RowsAffected() - if err != nil { - return 0, rollback(tx, err) - } - if int(affected) < len(cu.owner) { - return 0, rollback(tx, &ConstraintError{msg: fmt.Sprintf("one of \"owner\" %v already connected to a different \"Card\"", keys(cu.owner))}) - } + if nodes := cu.owner; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2O, + Inverse: true, + Table: card.OwnerTable, + Columns: []string{card.OwnerColumn}, + Bidi: false, + 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 err = tx.Commit(); err != nil { + if n, err = sqlgraph.UpdateNodes(ctx, cu.driver, spec); err != nil { + if cerr, ok := isSQLConstraintError(err); ok { + err = cerr + } return 0, err } - return len(ids), nil + return n, nil } // CardUpdateOne is the builder for updating a single Card entity. @@ -257,87 +253,98 @@ func (cuo *CardUpdateOne) ExecX(ctx context.Context) { } func (cuo *CardUpdateOne) sqlSave(ctx context.Context) (c *Card, err error) { - var ( - builder = sql.Dialect(cuo.driver.Dialect()) - selector = builder.Select(card.Columns...).From(builder.Table(card.Table)) - ) - card.ID(cuo.id)(selector) - rows := &sql.Rows{} - query, args := selector.Query() - if err = cuo.driver.Query(ctx, query, args, rows); err != nil { - return nil, err + spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: card.Table, + Columns: card.Columns, + ID: &sqlgraph.FieldSpec{ + Value: cuo.id, + Type: field.TypeInt, + Column: card.FieldID, + }, + }, } - defer rows.Close() - - var ids []int - for rows.Next() { - var id int - c = &Card{config: cuo.config} - if err := c.FromRows(rows); err != nil { - return nil, fmt.Errorf("ent: failed scanning row into Card: %v", err) - } - id = c.ID - ids = append(ids, id) - } - switch n := len(ids); { - case n == 0: - return nil, &ErrNotFound{fmt.Sprintf("Card with id: %v", cuo.id)} - case n > 1: - return nil, fmt.Errorf("ent: more than one Card with the same id: %v", cuo.id) - } - - tx, err := cuo.driver.Tx(ctx) - if err != nil { - return nil, err - } - var ( - res sql.Result - updater = builder.Update(card.Table) - ) - updater = updater.Where(sql.InInts(card.FieldID, ids...)) if value := cuo.expired; value != nil { - updater.Set(card.FieldExpired, *value) - c.Expired = *value + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeTime, + Value: *value, + Column: card.FieldExpired, + }) } if value := cuo.number; value != nil { - updater.Set(card.FieldNumber, *value) - c.Number = *value - } - if !updater.Empty() { - query, args := updater.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) - } + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: *value, + Column: card.FieldNumber, + }) } if cuo.clearedOwner { - query, args := builder.Update(card.OwnerTable). - SetNull(card.OwnerColumn). - Where(sql.InInts(user.FieldID, ids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2O, + Inverse: true, + Table: card.OwnerTable, + Columns: []string{card.OwnerColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: user.FieldID, + }, + }, } + spec.Edges.Clear = append(spec.Edges.Clear, edge) } - if len(cuo.owner) > 0 { - for _, id := range ids { - eid := keys(cuo.owner)[0] - query, args := builder.Update(card.OwnerTable). - Set(card.OwnerColumn, eid). - Where(sql.EQ(card.FieldID, id).And().IsNull(card.OwnerColumn)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) - } - affected, err := res.RowsAffected() - if err != nil { - return nil, rollback(tx, err) - } - if int(affected) < len(cuo.owner) { - return nil, rollback(tx, &ConstraintError{msg: fmt.Sprintf("one of \"owner\" %v already connected to a different \"Card\"", keys(cuo.owner))}) - } + if nodes := cuo.owner; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2O, + Inverse: true, + Table: card.OwnerTable, + Columns: []string{card.OwnerColumn}, + Bidi: false, + 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 err = tx.Commit(); err != nil { + c = &Card{config: cuo.config} + spec.ScanTypes = []interface{}{ + &sql.NullInt64{}, + &sql.NullTime{}, + &sql.NullString{}, + } + spec.Assign = func(values ...interface{}) error { + if m, n := len(values), len(spec.ScanTypes); m != n { + return fmt.Errorf("mismatch number of scan values: %d != %d", m, n) + } + value, ok := values[0].(*sql.NullInt64) + if !ok { + return fmt.Errorf("unexpected type %T for field id", value) + } + c.ID = int(value.Int64) + values = values[1:] + if value, ok := values[0].(*sql.NullTime); !ok { + return fmt.Errorf("unexpected type %T for field expired", values[0]) + } else if value.Valid { + c.Expired = value.Time + } + if value, ok := values[1].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field number", values[1]) + } else if value.Valid { + c.Number = value.String + } + return nil + } + if err = sqlgraph.UpdateNode(ctx, cuo.driver, spec); err != nil { + if cerr, ok := isSQLConstraintError(err); ok { + err = cerr + } return nil, err } return c, nil diff --git a/examples/o2o2types/ent/user_update.go b/examples/o2o2types/ent/user_update.go index 4befced0d..f0ebb4d4c 100644 --- a/examples/o2o2types/ent/user_update.go +++ b/examples/o2o2types/ent/user_update.go @@ -12,9 +12,11 @@ import ( "fmt" "github.com/facebookincubator/ent/dialect/sql" + "github.com/facebookincubator/ent/dialect/sql/sqlgraph" "github.com/facebookincubator/ent/examples/o2o2types/ent/card" "github.com/facebookincubator/ent/examples/o2o2types/ent/predicate" "github.com/facebookincubator/ent/examples/o2o2types/ent/user" + "github.com/facebookincubator/ent/schema/field" ) // UserUpdate is the builder for updating User entities. @@ -116,88 +118,86 @@ func (uu *UserUpdate) ExecX(ctx context.Context) { } func (uu *UserUpdate) sqlSave(ctx context.Context) (n int, err error) { - var ( - builder = sql.Dialect(uu.driver.Dialect()) - selector = builder.Select(user.FieldID).From(builder.Table(user.Table)) - ) - for _, p := range uu.predicates { - p(selector) + spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: user.Table, + Columns: user.Columns, + ID: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: user.FieldID, + }, + }, } - rows := &sql.Rows{} - query, args := selector.Query() - if err = uu.driver.Query(ctx, query, args, rows); err != nil { - return 0, err - } - defer rows.Close() - - var ids []int - for rows.Next() { - var id int - if err := rows.Scan(&id); err != nil { - return 0, fmt.Errorf("ent: failed reading id: %v", err) + if ps := uu.predicates; len(ps) > 0 { + spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } } - ids = append(ids, id) } - if len(ids) == 0 { - return 0, nil - } - - tx, err := uu.driver.Tx(ctx) - if err != nil { - return 0, err - } - var ( - res sql.Result - updater = builder.Update(user.Table) - ) - updater = updater.Where(sql.InInts(user.FieldID, ids...)) if value := uu.age; value != nil { - updater.Set(user.FieldAge, *value) + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: *value, + Column: user.FieldAge, + }) } if value := uu.addage; value != nil { - updater.Add(user.FieldAge, *value) + spec.Fields.Add = append(spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: *value, + Column: user.FieldAge, + }) } if value := uu.name; value != nil { - updater.Set(user.FieldName, *value) - } - if !updater.Empty() { - query, args := updater.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: *value, + Column: user.FieldName, + }) } if uu.clearedCard { - query, args := builder.Update(user.CardTable). - SetNull(user.CardColumn). - Where(sql.InInts(card.FieldID, ids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2O, + Inverse: false, + Table: user.CardTable, + Columns: []string{user.CardColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: card.FieldID, + }, + }, } + spec.Edges.Clear = append(spec.Edges.Clear, edge) } - if len(uu.card) > 0 { - for _, id := range ids { - eid := keys(uu.card)[0] - query, args := builder.Update(user.CardTable). - Set(user.CardColumn, id). - Where(sql.EQ(card.FieldID, eid).And().IsNull(user.CardColumn)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } - affected, err := res.RowsAffected() - if err != nil { - return 0, rollback(tx, err) - } - if int(affected) < len(uu.card) { - return 0, rollback(tx, &ConstraintError{msg: fmt.Sprintf("one of \"card\" %v already connected to a different \"User\"", keys(uu.card))}) - } + if nodes := uu.card; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2O, + Inverse: false, + Table: user.CardTable, + Columns: []string{user.CardColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: card.FieldID, + }, + }, } + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + spec.Edges.Add = append(spec.Edges.Add, edge) } - if err = tx.Commit(); err != nil { + if n, err = sqlgraph.UpdateNodes(ctx, uu.driver, spec); err != nil { + if cerr, ok := isSQLConstraintError(err); ok { + err = cerr + } return 0, err } - return len(ids), nil + return n, nil } // UserUpdateOne is the builder for updating a single User entity. @@ -293,91 +293,105 @@ func (uuo *UserUpdateOne) ExecX(ctx context.Context) { } func (uuo *UserUpdateOne) sqlSave(ctx context.Context) (u *User, err error) { - var ( - builder = sql.Dialect(uuo.driver.Dialect()) - selector = builder.Select(user.Columns...).From(builder.Table(user.Table)) - ) - user.ID(uuo.id)(selector) - rows := &sql.Rows{} - query, args := selector.Query() - if err = uuo.driver.Query(ctx, query, args, rows); err != nil { - return nil, err + spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: user.Table, + Columns: user.Columns, + ID: &sqlgraph.FieldSpec{ + Value: uuo.id, + Type: field.TypeInt, + Column: user.FieldID, + }, + }, } - defer rows.Close() - - var ids []int - for rows.Next() { - var id int - u = &User{config: uuo.config} - if err := u.FromRows(rows); err != nil { - return nil, fmt.Errorf("ent: failed scanning row into User: %v", err) - } - id = u.ID - ids = append(ids, id) - } - switch n := len(ids); { - case n == 0: - return nil, &ErrNotFound{fmt.Sprintf("User with id: %v", uuo.id)} - case n > 1: - return nil, fmt.Errorf("ent: more than one User with the same id: %v", uuo.id) - } - - tx, err := uuo.driver.Tx(ctx) - if err != nil { - return nil, err - } - var ( - res sql.Result - updater = builder.Update(user.Table) - ) - updater = updater.Where(sql.InInts(user.FieldID, ids...)) if value := uuo.age; value != nil { - updater.Set(user.FieldAge, *value) - u.Age = *value + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: *value, + Column: user.FieldAge, + }) } if value := uuo.addage; value != nil { - updater.Add(user.FieldAge, *value) - u.Age += *value + spec.Fields.Add = append(spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: *value, + Column: user.FieldAge, + }) } if value := uuo.name; value != nil { - updater.Set(user.FieldName, *value) - u.Name = *value - } - if !updater.Empty() { - query, args := updater.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) - } + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: *value, + Column: user.FieldName, + }) } if uuo.clearedCard { - query, args := builder.Update(user.CardTable). - SetNull(user.CardColumn). - Where(sql.InInts(card.FieldID, ids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2O, + Inverse: false, + Table: user.CardTable, + Columns: []string{user.CardColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: card.FieldID, + }, + }, } + spec.Edges.Clear = append(spec.Edges.Clear, edge) } - if len(uuo.card) > 0 { - for _, id := range ids { - eid := keys(uuo.card)[0] - query, args := builder.Update(user.CardTable). - Set(user.CardColumn, id). - Where(sql.EQ(card.FieldID, eid).And().IsNull(user.CardColumn)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) - } - affected, err := res.RowsAffected() - if err != nil { - return nil, rollback(tx, err) - } - if int(affected) < len(uuo.card) { - return nil, rollback(tx, &ConstraintError{msg: fmt.Sprintf("one of \"card\" %v already connected to a different \"User\"", keys(uuo.card))}) - } + if nodes := uuo.card; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2O, + Inverse: false, + Table: user.CardTable, + Columns: []string{user.CardColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: card.FieldID, + }, + }, } + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + spec.Edges.Add = append(spec.Edges.Add, edge) } - if err = tx.Commit(); err != nil { + u = &User{config: uuo.config} + spec.ScanTypes = []interface{}{ + &sql.NullInt64{}, + &sql.NullInt64{}, + &sql.NullString{}, + } + spec.Assign = func(values ...interface{}) error { + if m, n := len(values), len(spec.ScanTypes); m != n { + return fmt.Errorf("mismatch number of scan values: %d != %d", m, n) + } + value, ok := values[0].(*sql.NullInt64) + if !ok { + return fmt.Errorf("unexpected type %T for field id", value) + } + u.ID = int(value.Int64) + values = values[1:] + if value, ok := values[0].(*sql.NullInt64); !ok { + return fmt.Errorf("unexpected type %T for field age", values[0]) + } else if value.Valid { + u.Age = int(value.Int64) + } + if value, ok := values[1].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field name", values[1]) + } else if value.Valid { + u.Name = value.String + } + return nil + } + if err = sqlgraph.UpdateNode(ctx, uuo.driver, spec); err != nil { + if cerr, ok := isSQLConstraintError(err); ok { + err = cerr + } return nil, err } return u, nil diff --git a/examples/o2obidi/ent/user_update.go b/examples/o2obidi/ent/user_update.go index 221b2a20f..41f5aeb24 100644 --- a/examples/o2obidi/ent/user_update.go +++ b/examples/o2obidi/ent/user_update.go @@ -12,8 +12,10 @@ import ( "fmt" "github.com/facebookincubator/ent/dialect/sql" + "github.com/facebookincubator/ent/dialect/sql/sqlgraph" "github.com/facebookincubator/ent/examples/o2obidi/ent/predicate" "github.com/facebookincubator/ent/examples/o2obidi/ent/user" + "github.com/facebookincubator/ent/schema/field" ) // UserUpdate is the builder for updating User entities. @@ -115,102 +117,86 @@ func (uu *UserUpdate) ExecX(ctx context.Context) { } func (uu *UserUpdate) sqlSave(ctx context.Context) (n int, err error) { - var ( - builder = sql.Dialect(uu.driver.Dialect()) - selector = builder.Select(user.FieldID).From(builder.Table(user.Table)) - ) - for _, p := range uu.predicates { - p(selector) + spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: user.Table, + Columns: user.Columns, + ID: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: user.FieldID, + }, + }, } - rows := &sql.Rows{} - query, args := selector.Query() - if err = uu.driver.Query(ctx, query, args, rows); err != nil { - return 0, err - } - defer rows.Close() - - var ids []int - for rows.Next() { - var id int - if err := rows.Scan(&id); err != nil { - return 0, fmt.Errorf("ent: failed reading id: %v", err) + if ps := uu.predicates; len(ps) > 0 { + spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } } - ids = append(ids, id) } - if len(ids) == 0 { - return 0, nil - } - - tx, err := uu.driver.Tx(ctx) - if err != nil { - return 0, err - } - var ( - res sql.Result - updater = builder.Update(user.Table) - ) - updater = updater.Where(sql.InInts(user.FieldID, ids...)) if value := uu.age; value != nil { - updater.Set(user.FieldAge, *value) + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: *value, + Column: user.FieldAge, + }) } if value := uu.addage; value != nil { - updater.Add(user.FieldAge, *value) + spec.Fields.Add = append(spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: *value, + Column: user.FieldAge, + }) } if value := uu.name; value != nil { - updater.Set(user.FieldName, *value) - } - if !updater.Empty() { - query, args := updater.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: *value, + Column: user.FieldName, + }) } if uu.clearedSpouse { - query, args := builder.Update(user.SpouseTable). - SetNull(user.SpouseColumn). - Where(sql.InInts(user.FieldID, ids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } - query, args = builder.Update(user.SpouseTable). - SetNull(user.SpouseColumn). - Where(sql.InInts(user.SpouseColumn, ids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2O, + Inverse: false, + Table: user.SpouseTable, + Columns: []string{user.SpouseColumn}, + Bidi: true, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: user.FieldID, + }, + }, } + spec.Edges.Clear = append(spec.Edges.Clear, edge) } - if len(uu.spouse) > 0 { - if n := len(ids); n > 1 { - return 0, rollback(tx, fmt.Errorf("ent: can't link O2O edge \"spouse\" to %d vertices (> 1)", n)) + if nodes := uu.spouse; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2O, + Inverse: false, + Table: user.SpouseTable, + Columns: []string{user.SpouseColumn}, + Bidi: true, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: user.FieldID, + }, + }, } - for eid := range uu.spouse { - query, args := builder.Update(user.SpouseTable). - Set(user.SpouseColumn, eid). - Where(sql.EQ(user.FieldID, ids[0])).Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } - query, args = builder.Update(user.SpouseTable). - Set(user.SpouseColumn, ids[0]). - Where(sql.EQ(user.FieldID, eid).And().IsNull(user.SpouseColumn)).Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } - affected, err := res.RowsAffected() - if err != nil { - return 0, rollback(tx, err) - } - if int(affected) < len(uu.spouse) { - return 0, rollback(tx, &ConstraintError{msg: fmt.Sprintf("\"spouse\" (%v) already connected to a different \"User\"", eid)}) - } + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) } + spec.Edges.Add = append(spec.Edges.Add, edge) } - if err = tx.Commit(); err != nil { + if n, err = sqlgraph.UpdateNodes(ctx, uu.driver, spec); err != nil { + if cerr, ok := isSQLConstraintError(err); ok { + err = cerr + } return 0, err } - return len(ids), nil + return n, nil } // UserUpdateOne is the builder for updating a single User entity. @@ -306,105 +292,105 @@ func (uuo *UserUpdateOne) ExecX(ctx context.Context) { } func (uuo *UserUpdateOne) sqlSave(ctx context.Context) (u *User, err error) { - var ( - builder = sql.Dialect(uuo.driver.Dialect()) - selector = builder.Select(user.Columns...).From(builder.Table(user.Table)) - ) - user.ID(uuo.id)(selector) - rows := &sql.Rows{} - query, args := selector.Query() - if err = uuo.driver.Query(ctx, query, args, rows); err != nil { - return nil, err + spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: user.Table, + Columns: user.Columns, + ID: &sqlgraph.FieldSpec{ + Value: uuo.id, + Type: field.TypeInt, + Column: user.FieldID, + }, + }, } - defer rows.Close() - - var ids []int - for rows.Next() { - var id int - u = &User{config: uuo.config} - if err := u.FromRows(rows); err != nil { - return nil, fmt.Errorf("ent: failed scanning row into User: %v", err) - } - id = u.ID - ids = append(ids, id) - } - switch n := len(ids); { - case n == 0: - return nil, &ErrNotFound{fmt.Sprintf("User with id: %v", uuo.id)} - case n > 1: - return nil, fmt.Errorf("ent: more than one User with the same id: %v", uuo.id) - } - - tx, err := uuo.driver.Tx(ctx) - if err != nil { - return nil, err - } - var ( - res sql.Result - updater = builder.Update(user.Table) - ) - updater = updater.Where(sql.InInts(user.FieldID, ids...)) if value := uuo.age; value != nil { - updater.Set(user.FieldAge, *value) - u.Age = *value + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: *value, + Column: user.FieldAge, + }) } if value := uuo.addage; value != nil { - updater.Add(user.FieldAge, *value) - u.Age += *value + spec.Fields.Add = append(spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: *value, + Column: user.FieldAge, + }) } if value := uuo.name; value != nil { - updater.Set(user.FieldName, *value) - u.Name = *value - } - if !updater.Empty() { - query, args := updater.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) - } + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: *value, + Column: user.FieldName, + }) } if uuo.clearedSpouse { - query, args := builder.Update(user.SpouseTable). - SetNull(user.SpouseColumn). - Where(sql.InInts(user.FieldID, ids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) - } - query, args = builder.Update(user.SpouseTable). - SetNull(user.SpouseColumn). - Where(sql.InInts(user.SpouseColumn, ids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2O, + Inverse: false, + Table: user.SpouseTable, + Columns: []string{user.SpouseColumn}, + Bidi: true, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: user.FieldID, + }, + }, } + spec.Edges.Clear = append(spec.Edges.Clear, edge) } - if len(uuo.spouse) > 0 { - if n := len(ids); n > 1 { - return nil, rollback(tx, fmt.Errorf("ent: can't link O2O edge \"spouse\" to %d vertices (> 1)", n)) + if nodes := uuo.spouse; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2O, + Inverse: false, + Table: user.SpouseTable, + Columns: []string{user.SpouseColumn}, + Bidi: true, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: user.FieldID, + }, + }, } - for eid := range uuo.spouse { - query, args := builder.Update(user.SpouseTable). - Set(user.SpouseColumn, eid). - Where(sql.EQ(user.FieldID, ids[0])).Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) - } - query, args = builder.Update(user.SpouseTable). - Set(user.SpouseColumn, ids[0]). - Where(sql.EQ(user.FieldID, eid).And().IsNull(user.SpouseColumn)).Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) - } - affected, err := res.RowsAffected() - if err != nil { - return nil, rollback(tx, err) - } - if int(affected) < len(uuo.spouse) { - return nil, rollback(tx, &ConstraintError{msg: fmt.Sprintf("\"spouse\" (%v) already connected to a different \"User\"", eid)}) - } + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) } + spec.Edges.Add = append(spec.Edges.Add, edge) } - if err = tx.Commit(); err != nil { + u = &User{config: uuo.config} + spec.ScanTypes = []interface{}{ + &sql.NullInt64{}, + &sql.NullInt64{}, + &sql.NullString{}, + } + spec.Assign = func(values ...interface{}) error { + if m, n := len(values), len(spec.ScanTypes); m != n { + return fmt.Errorf("mismatch number of scan values: %d != %d", m, n) + } + value, ok := values[0].(*sql.NullInt64) + if !ok { + return fmt.Errorf("unexpected type %T for field id", value) + } + u.ID = int(value.Int64) + values = values[1:] + if value, ok := values[0].(*sql.NullInt64); !ok { + return fmt.Errorf("unexpected type %T for field age", values[0]) + } else if value.Valid { + u.Age = int(value.Int64) + } + if value, ok := values[1].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field name", values[1]) + } else if value.Valid { + u.Name = value.String + } + return nil + } + if err = sqlgraph.UpdateNode(ctx, uuo.driver, spec); err != nil { + if cerr, ok := isSQLConstraintError(err); ok { + err = cerr + } return nil, err } return u, nil diff --git a/examples/o2orecur/ent/node_update.go b/examples/o2orecur/ent/node_update.go index 054be5abb..f92ebf40e 100644 --- a/examples/o2orecur/ent/node_update.go +++ b/examples/o2orecur/ent/node_update.go @@ -12,8 +12,10 @@ import ( "fmt" "github.com/facebookincubator/ent/dialect/sql" + "github.com/facebookincubator/ent/dialect/sql/sqlgraph" "github.com/facebookincubator/ent/examples/o2orecur/ent/node" "github.com/facebookincubator/ent/examples/o2orecur/ent/predicate" + "github.com/facebookincubator/ent/schema/field" ) // NodeUpdate is the builder for updating Node entities. @@ -141,113 +143,114 @@ func (nu *NodeUpdate) ExecX(ctx context.Context) { } func (nu *NodeUpdate) sqlSave(ctx context.Context) (n int, err error) { - var ( - builder = sql.Dialect(nu.driver.Dialect()) - selector = builder.Select(node.FieldID).From(builder.Table(node.Table)) - ) - for _, p := range nu.predicates { - p(selector) + spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: node.Table, + Columns: node.Columns, + ID: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: node.FieldID, + }, + }, } - rows := &sql.Rows{} - query, args := selector.Query() - if err = nu.driver.Query(ctx, query, args, rows); err != nil { - return 0, err - } - defer rows.Close() - - var ids []int - for rows.Next() { - var id int - if err := rows.Scan(&id); err != nil { - return 0, fmt.Errorf("ent: failed reading id: %v", err) + if ps := nu.predicates; len(ps) > 0 { + spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } } - ids = append(ids, id) } - if len(ids) == 0 { - return 0, nil - } - - tx, err := nu.driver.Tx(ctx) - if err != nil { - return 0, err - } - var ( - res sql.Result - updater = builder.Update(node.Table) - ) - updater = updater.Where(sql.InInts(node.FieldID, ids...)) if value := nu.value; value != nil { - updater.Set(node.FieldValue, *value) + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: *value, + Column: node.FieldValue, + }) } if value := nu.addvalue; value != nil { - updater.Add(node.FieldValue, *value) - } - if !updater.Empty() { - query, args := updater.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } + spec.Fields.Add = append(spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: *value, + Column: node.FieldValue, + }) } if nu.clearedPrev { - query, args := builder.Update(node.PrevTable). - SetNull(node.PrevColumn). - Where(sql.InInts(node.FieldID, ids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2O, + Inverse: true, + Table: node.PrevTable, + Columns: []string{node.PrevColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: node.FieldID, + }, + }, } + spec.Edges.Clear = append(spec.Edges.Clear, edge) } - if len(nu.prev) > 0 { - for _, id := range ids { - eid := keys(nu.prev)[0] - query, args := builder.Update(node.PrevTable). - Set(node.PrevColumn, eid). - Where(sql.EQ(node.FieldID, id).And().IsNull(node.PrevColumn)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } - affected, err := res.RowsAffected() - if err != nil { - return 0, rollback(tx, err) - } - if int(affected) < len(nu.prev) { - return 0, rollback(tx, &ConstraintError{msg: fmt.Sprintf("one of \"prev\" %v already connected to a different \"Node\"", keys(nu.prev))}) - } + if nodes := nu.prev; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2O, + Inverse: true, + Table: node.PrevTable, + Columns: []string{node.PrevColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: node.FieldID, + }, + }, } + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + spec.Edges.Add = append(spec.Edges.Add, edge) } if nu.clearedNext { - query, args := builder.Update(node.NextTable). - SetNull(node.NextColumn). - Where(sql.InInts(node.FieldID, ids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2O, + Inverse: false, + Table: node.NextTable, + Columns: []string{node.NextColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: node.FieldID, + }, + }, } + spec.Edges.Clear = append(spec.Edges.Clear, edge) } - if len(nu.next) > 0 { - for _, id := range ids { - eid := keys(nu.next)[0] - query, args := builder.Update(node.NextTable). - Set(node.NextColumn, id). - Where(sql.EQ(node.FieldID, eid).And().IsNull(node.NextColumn)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } - affected, err := res.RowsAffected() - if err != nil { - return 0, rollback(tx, err) - } - if int(affected) < len(nu.next) { - return 0, rollback(tx, &ConstraintError{msg: fmt.Sprintf("one of \"next\" %v already connected to a different \"Node\"", keys(nu.next))}) - } + if nodes := nu.next; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2O, + Inverse: false, + Table: node.NextTable, + Columns: []string{node.NextColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: node.FieldID, + }, + }, } + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + spec.Edges.Add = append(spec.Edges.Add, edge) } - if err = tx.Commit(); err != nil { + if n, err = sqlgraph.UpdateNodes(ctx, nu.driver, spec); err != nil { + if cerr, ok := isSQLConstraintError(err); ok { + err = cerr + } return 0, err } - return len(ids), nil + return n, nil } // NodeUpdateOne is the builder for updating a single Node entity. @@ -369,115 +372,127 @@ func (nuo *NodeUpdateOne) ExecX(ctx context.Context) { } func (nuo *NodeUpdateOne) sqlSave(ctx context.Context) (n *Node, err error) { - var ( - builder = sql.Dialect(nuo.driver.Dialect()) - selector = builder.Select(node.Columns...).From(builder.Table(node.Table)) - ) - node.ID(nuo.id)(selector) - rows := &sql.Rows{} - query, args := selector.Query() - if err = nuo.driver.Query(ctx, query, args, rows); err != nil { - return nil, err + spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: node.Table, + Columns: node.Columns, + ID: &sqlgraph.FieldSpec{ + Value: nuo.id, + Type: field.TypeInt, + Column: node.FieldID, + }, + }, } - defer rows.Close() - - var ids []int - for rows.Next() { - var id int - n = &Node{config: nuo.config} - if err := n.FromRows(rows); err != nil { - return nil, fmt.Errorf("ent: failed scanning row into Node: %v", err) - } - id = n.ID - ids = append(ids, id) - } - switch n := len(ids); { - case n == 0: - return nil, &ErrNotFound{fmt.Sprintf("Node with id: %v", nuo.id)} - case n > 1: - return nil, fmt.Errorf("ent: more than one Node with the same id: %v", nuo.id) - } - - tx, err := nuo.driver.Tx(ctx) - if err != nil { - return nil, err - } - var ( - res sql.Result - updater = builder.Update(node.Table) - ) - updater = updater.Where(sql.InInts(node.FieldID, ids...)) if value := nuo.value; value != nil { - updater.Set(node.FieldValue, *value) - n.Value = *value + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: *value, + Column: node.FieldValue, + }) } if value := nuo.addvalue; value != nil { - updater.Add(node.FieldValue, *value) - n.Value += *value - } - if !updater.Empty() { - query, args := updater.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) - } + spec.Fields.Add = append(spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: *value, + Column: node.FieldValue, + }) } if nuo.clearedPrev { - query, args := builder.Update(node.PrevTable). - SetNull(node.PrevColumn). - Where(sql.InInts(node.FieldID, ids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2O, + Inverse: true, + Table: node.PrevTable, + Columns: []string{node.PrevColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: node.FieldID, + }, + }, } + spec.Edges.Clear = append(spec.Edges.Clear, edge) } - if len(nuo.prev) > 0 { - for _, id := range ids { - eid := keys(nuo.prev)[0] - query, args := builder.Update(node.PrevTable). - Set(node.PrevColumn, eid). - Where(sql.EQ(node.FieldID, id).And().IsNull(node.PrevColumn)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) - } - affected, err := res.RowsAffected() - if err != nil { - return nil, rollback(tx, err) - } - if int(affected) < len(nuo.prev) { - return nil, rollback(tx, &ConstraintError{msg: fmt.Sprintf("one of \"prev\" %v already connected to a different \"Node\"", keys(nuo.prev))}) - } + if nodes := nuo.prev; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2O, + Inverse: true, + Table: node.PrevTable, + Columns: []string{node.PrevColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: node.FieldID, + }, + }, } + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + spec.Edges.Add = append(spec.Edges.Add, edge) } if nuo.clearedNext { - query, args := builder.Update(node.NextTable). - SetNull(node.NextColumn). - Where(sql.InInts(node.FieldID, ids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2O, + Inverse: false, + Table: node.NextTable, + Columns: []string{node.NextColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: node.FieldID, + }, + }, } + spec.Edges.Clear = append(spec.Edges.Clear, edge) } - if len(nuo.next) > 0 { - for _, id := range ids { - eid := keys(nuo.next)[0] - query, args := builder.Update(node.NextTable). - Set(node.NextColumn, id). - Where(sql.EQ(node.FieldID, eid).And().IsNull(node.NextColumn)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) - } - affected, err := res.RowsAffected() - if err != nil { - return nil, rollback(tx, err) - } - if int(affected) < len(nuo.next) { - return nil, rollback(tx, &ConstraintError{msg: fmt.Sprintf("one of \"next\" %v already connected to a different \"Node\"", keys(nuo.next))}) - } + if nodes := nuo.next; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2O, + Inverse: false, + Table: node.NextTable, + Columns: []string{node.NextColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: node.FieldID, + }, + }, } + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + spec.Edges.Add = append(spec.Edges.Add, edge) } - if err = tx.Commit(); err != nil { + n = &Node{config: nuo.config} + spec.ScanTypes = []interface{}{ + &sql.NullInt64{}, + &sql.NullInt64{}, + } + spec.Assign = func(values ...interface{}) error { + if m, n := len(values), len(spec.ScanTypes); m != n { + return fmt.Errorf("mismatch number of scan values: %d != %d", m, n) + } + value, ok := values[0].(*sql.NullInt64) + if !ok { + return fmt.Errorf("unexpected type %T for field id", value) + } + n.ID = int(value.Int64) + values = values[1:] + if value, ok := values[0].(*sql.NullInt64); !ok { + return fmt.Errorf("unexpected type %T for field value", values[0]) + } else if value.Valid { + n.Value = int(value.Int64) + } + return nil + } + if err = sqlgraph.UpdateNode(ctx, nuo.driver, spec); err != nil { + if cerr, ok := isSQLConstraintError(err); ok { + err = cerr + } return nil, err } return n, nil diff --git a/examples/start/ent/car_update.go b/examples/start/ent/car_update.go index 06c5f74bd..69bf1362b 100644 --- a/examples/start/ent/car_update.go +++ b/examples/start/ent/car_update.go @@ -13,9 +13,11 @@ import ( "time" "github.com/facebookincubator/ent/dialect/sql" + "github.com/facebookincubator/ent/dialect/sql/sqlgraph" "github.com/facebookincubator/ent/examples/start/ent/car" "github.com/facebookincubator/ent/examples/start/ent/predicate" "github.com/facebookincubator/ent/examples/start/ent/user" + "github.com/facebookincubator/ent/schema/field" ) // CarUpdate is the builder for updating Car entities. @@ -105,77 +107,79 @@ func (cu *CarUpdate) ExecX(ctx context.Context) { } func (cu *CarUpdate) sqlSave(ctx context.Context) (n int, err error) { - var ( - builder = sql.Dialect(cu.driver.Dialect()) - selector = builder.Select(car.FieldID).From(builder.Table(car.Table)) - ) - for _, p := range cu.predicates { - p(selector) + spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: car.Table, + Columns: car.Columns, + ID: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: car.FieldID, + }, + }, } - rows := &sql.Rows{} - query, args := selector.Query() - if err = cu.driver.Query(ctx, query, args, rows); err != nil { - return 0, err - } - defer rows.Close() - - var ids []int - for rows.Next() { - var id int - if err := rows.Scan(&id); err != nil { - return 0, fmt.Errorf("ent: failed reading id: %v", err) - } - ids = append(ids, id) - } - if len(ids) == 0 { - return 0, nil - } - - tx, err := cu.driver.Tx(ctx) - if err != nil { - return 0, err - } - var ( - res sql.Result - updater = builder.Update(car.Table) - ) - updater = updater.Where(sql.InInts(car.FieldID, ids...)) - if value := cu.model; value != nil { - updater.Set(car.FieldModel, *value) - } - if value := cu.registered_at; value != nil { - updater.Set(car.FieldRegisteredAt, *value) - } - if !updater.Empty() { - query, args := updater.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } - } - if cu.clearedOwner { - query, args := builder.Update(car.OwnerTable). - SetNull(car.OwnerColumn). - Where(sql.InInts(user.FieldID, ids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } - } - if len(cu.owner) > 0 { - for eid := range cu.owner { - query, args := builder.Update(car.OwnerTable). - Set(car.OwnerColumn, eid). - Where(sql.InInts(car.FieldID, ids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) + if ps := cu.predicates; len(ps) > 0 { + spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) } } } - if err = tx.Commit(); err != nil { + if value := cu.model; value != nil { + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: *value, + Column: car.FieldModel, + }) + } + if value := cu.registered_at; value != nil { + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeTime, + Value: *value, + Column: car.FieldRegisteredAt, + }) + } + if cu.clearedOwner { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: car.OwnerTable, + Columns: []string{car.OwnerColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: user.FieldID, + }, + }, + } + spec.Edges.Clear = append(spec.Edges.Clear, edge) + } + if nodes := cu.owner; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: car.OwnerTable, + Columns: []string{car.OwnerColumn}, + Bidi: false, + 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, cu.driver, spec); err != nil { + if cerr, ok := isSQLConstraintError(err); ok { + err = cerr + } return 0, err } - return len(ids), nil + return n, nil } // CarUpdateOne is the builder for updating a single Car entity. @@ -259,79 +263,98 @@ func (cuo *CarUpdateOne) ExecX(ctx context.Context) { } func (cuo *CarUpdateOne) sqlSave(ctx context.Context) (c *Car, err error) { - var ( - builder = sql.Dialect(cuo.driver.Dialect()) - selector = builder.Select(car.Columns...).From(builder.Table(car.Table)) - ) - car.ID(cuo.id)(selector) - rows := &sql.Rows{} - query, args := selector.Query() - if err = cuo.driver.Query(ctx, query, args, rows); err != nil { - return nil, err + spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: car.Table, + Columns: car.Columns, + ID: &sqlgraph.FieldSpec{ + Value: cuo.id, + Type: field.TypeInt, + Column: car.FieldID, + }, + }, } - defer rows.Close() - - var ids []int - for rows.Next() { - var id int - c = &Car{config: cuo.config} - if err := c.FromRows(rows); err != nil { - return nil, fmt.Errorf("ent: failed scanning row into Car: %v", err) - } - id = c.ID - ids = append(ids, id) - } - switch n := len(ids); { - case n == 0: - return nil, &ErrNotFound{fmt.Sprintf("Car with id: %v", cuo.id)} - case n > 1: - return nil, fmt.Errorf("ent: more than one Car with the same id: %v", cuo.id) - } - - tx, err := cuo.driver.Tx(ctx) - if err != nil { - return nil, err - } - var ( - res sql.Result - updater = builder.Update(car.Table) - ) - updater = updater.Where(sql.InInts(car.FieldID, ids...)) if value := cuo.model; value != nil { - updater.Set(car.FieldModel, *value) - c.Model = *value + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: *value, + Column: car.FieldModel, + }) } if value := cuo.registered_at; value != nil { - updater.Set(car.FieldRegisteredAt, *value) - c.RegisteredAt = *value - } - if !updater.Empty() { - query, args := updater.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) - } + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeTime, + Value: *value, + Column: car.FieldRegisteredAt, + }) } if cuo.clearedOwner { - query, args := builder.Update(car.OwnerTable). - SetNull(car.OwnerColumn). - Where(sql.InInts(user.FieldID, ids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: car.OwnerTable, + Columns: []string{car.OwnerColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: user.FieldID, + }, + }, } + spec.Edges.Clear = append(spec.Edges.Clear, edge) } - if len(cuo.owner) > 0 { - for eid := range cuo.owner { - query, args := builder.Update(car.OwnerTable). - Set(car.OwnerColumn, eid). - Where(sql.InInts(car.FieldID, ids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) - } + if nodes := cuo.owner; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: car.OwnerTable, + Columns: []string{car.OwnerColumn}, + Bidi: false, + 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 err = tx.Commit(); err != nil { + c = &Car{config: cuo.config} + spec.ScanTypes = []interface{}{ + &sql.NullInt64{}, + &sql.NullString{}, + &sql.NullTime{}, + } + spec.Assign = func(values ...interface{}) error { + if m, n := len(values), len(spec.ScanTypes); m != n { + return fmt.Errorf("mismatch number of scan values: %d != %d", m, n) + } + value, ok := values[0].(*sql.NullInt64) + if !ok { + return fmt.Errorf("unexpected type %T for field id", value) + } + c.ID = int(value.Int64) + values = values[1:] + if value, ok := values[0].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field model", values[0]) + } else if value.Valid { + c.Model = value.String + } + if value, ok := values[1].(*sql.NullTime); !ok { + return fmt.Errorf("unexpected type %T for field registered_at", values[1]) + } else if value.Valid { + c.RegisteredAt = value.Time + } + return nil + } + if err = sqlgraph.UpdateNode(ctx, cuo.driver, spec); err != nil { + if cerr, ok := isSQLConstraintError(err); ok { + err = cerr + } return nil, err } return c, nil diff --git a/examples/start/ent/group_update.go b/examples/start/ent/group_update.go index 7aa7e4c14..2d66a2550 100644 --- a/examples/start/ent/group_update.go +++ b/examples/start/ent/group_update.go @@ -11,8 +11,11 @@ import ( "fmt" "github.com/facebookincubator/ent/dialect/sql" + "github.com/facebookincubator/ent/dialect/sql/sqlgraph" "github.com/facebookincubator/ent/examples/start/ent/group" "github.com/facebookincubator/ent/examples/start/ent/predicate" + "github.com/facebookincubator/ent/examples/start/ent/user" + "github.com/facebookincubator/ent/schema/field" ) // GroupUpdate is the builder for updating Group entities. @@ -109,84 +112,75 @@ func (gu *GroupUpdate) ExecX(ctx context.Context) { } func (gu *GroupUpdate) sqlSave(ctx context.Context) (n int, err error) { - var ( - builder = sql.Dialect(gu.driver.Dialect()) - selector = builder.Select(group.FieldID).From(builder.Table(group.Table)) - ) - for _, p := range gu.predicates { - p(selector) + spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: group.Table, + Columns: group.Columns, + ID: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: group.FieldID, + }, + }, } - rows := &sql.Rows{} - query, args := selector.Query() - if err = gu.driver.Query(ctx, query, args, rows); err != nil { - return 0, err - } - defer rows.Close() - - var ids []int - for rows.Next() { - var id int - if err := rows.Scan(&id); err != nil { - return 0, fmt.Errorf("ent: failed reading id: %v", err) - } - ids = append(ids, id) - } - if len(ids) == 0 { - return 0, nil - } - - tx, err := gu.driver.Tx(ctx) - if err != nil { - return 0, err - } - var ( - res sql.Result - updater = builder.Update(group.Table) - ) - updater = updater.Where(sql.InInts(group.FieldID, ids...)) - if value := gu.name; value != nil { - updater.Set(group.FieldName, *value) - } - if !updater.Empty() { - query, args := updater.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } - } - if len(gu.removedUsers) > 0 { - eids := make([]int, len(gu.removedUsers)) - for eid := range gu.removedUsers { - eids = append(eids, eid) - } - query, args := builder.Delete(group.UsersTable). - Where(sql.InInts(group.UsersPrimaryKey[0], ids...)). - Where(sql.InInts(group.UsersPrimaryKey[1], eids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } - } - if len(gu.users) > 0 { - values := make([][]int, 0, len(ids)) - for _, id := range ids { - for eid := range gu.users { - values = append(values, []int{id, eid}) + if ps := gu.predicates; len(ps) > 0 { + spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) } } - builder := builder.Insert(group.UsersTable). - Columns(group.UsersPrimaryKey[0], group.UsersPrimaryKey[1]) - for _, v := range values { - builder.Values(v[0], v[1]) - } - query, args := builder.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } } - if err = tx.Commit(); err != nil { + if value := gu.name; value != nil { + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: *value, + Column: group.FieldName, + }) + } + if nodes := gu.removedUsers; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: false, + Table: group.UsersTable, + Columns: group.UsersPrimaryKey, + Bidi: false, + 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 := gu.users; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: false, + Table: group.UsersTable, + Columns: group.UsersPrimaryKey, + Bidi: false, + 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, gu.driver, spec); err != nil { + if cerr, ok := isSQLConstraintError(err); ok { + err = cerr + } return 0, err } - return len(ids), nil + return n, nil } // GroupUpdateOne is the builder for updating a single Group entity. @@ -277,85 +271,88 @@ func (guo *GroupUpdateOne) ExecX(ctx context.Context) { } func (guo *GroupUpdateOne) sqlSave(ctx context.Context) (gr *Group, err error) { - var ( - builder = sql.Dialect(guo.driver.Dialect()) - selector = builder.Select(group.Columns...).From(builder.Table(group.Table)) - ) - group.ID(guo.id)(selector) - rows := &sql.Rows{} - query, args := selector.Query() - if err = guo.driver.Query(ctx, query, args, rows); err != nil { - return nil, err + spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: group.Table, + Columns: group.Columns, + ID: &sqlgraph.FieldSpec{ + Value: guo.id, + Type: field.TypeInt, + Column: group.FieldID, + }, + }, } - defer rows.Close() - - var ids []int - for rows.Next() { - var id int - gr = &Group{config: guo.config} - if err := gr.FromRows(rows); err != nil { - return nil, fmt.Errorf("ent: failed scanning row into Group: %v", err) - } - id = gr.ID - ids = append(ids, id) - } - switch n := len(ids); { - case n == 0: - return nil, &ErrNotFound{fmt.Sprintf("Group with id: %v", guo.id)} - case n > 1: - return nil, fmt.Errorf("ent: more than one Group with the same id: %v", guo.id) - } - - tx, err := guo.driver.Tx(ctx) - if err != nil { - return nil, err - } - var ( - res sql.Result - updater = builder.Update(group.Table) - ) - updater = updater.Where(sql.InInts(group.FieldID, ids...)) if value := guo.name; value != nil { - updater.Set(group.FieldName, *value) - gr.Name = *value + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: *value, + Column: group.FieldName, + }) } - if !updater.Empty() { - query, args := updater.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) + if nodes := guo.removedUsers; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: false, + Table: group.UsersTable, + Columns: group.UsersPrimaryKey, + Bidi: false, + 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 len(guo.removedUsers) > 0 { - eids := make([]int, len(guo.removedUsers)) - for eid := range guo.removedUsers { - eids = append(eids, eid) + if nodes := guo.users; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: false, + Table: group.UsersTable, + Columns: group.UsersPrimaryKey, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: user.FieldID, + }, + }, } - query, args := builder.Delete(group.UsersTable). - Where(sql.InInts(group.UsersPrimaryKey[0], ids...)). - Where(sql.InInts(group.UsersPrimaryKey[1], eids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) } + spec.Edges.Add = append(spec.Edges.Add, edge) } - if len(guo.users) > 0 { - values := make([][]int, 0, len(ids)) - for _, id := range ids { - for eid := range guo.users { - values = append(values, []int{id, eid}) - } - } - builder := builder.Insert(group.UsersTable). - Columns(group.UsersPrimaryKey[0], group.UsersPrimaryKey[1]) - for _, v := range values { - builder.Values(v[0], v[1]) - } - query, args := builder.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) - } + gr = &Group{config: guo.config} + spec.ScanTypes = []interface{}{ + &sql.NullInt64{}, + &sql.NullString{}, } - if err = tx.Commit(); err != nil { + spec.Assign = func(values ...interface{}) error { + if m, n := len(values), len(spec.ScanTypes); m != n { + return fmt.Errorf("mismatch number of scan values: %d != %d", m, n) + } + value, ok := values[0].(*sql.NullInt64) + if !ok { + return fmt.Errorf("unexpected type %T for field id", value) + } + gr.ID = int(value.Int64) + values = values[1:] + if value, ok := values[0].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field name", values[0]) + } else if value.Valid { + gr.Name = value.String + } + return nil + } + if err = sqlgraph.UpdateNode(ctx, guo.driver, spec); err != nil { + if cerr, ok := isSQLConstraintError(err); ok { + err = cerr + } return nil, err } return gr, nil diff --git a/examples/start/ent/user_update.go b/examples/start/ent/user_update.go index 3ceca8ba4..2208ef15e 100644 --- a/examples/start/ent/user_update.go +++ b/examples/start/ent/user_update.go @@ -11,9 +11,12 @@ import ( "fmt" "github.com/facebookincubator/ent/dialect/sql" + "github.com/facebookincubator/ent/dialect/sql/sqlgraph" "github.com/facebookincubator/ent/examples/start/ent/car" + "github.com/facebookincubator/ent/examples/start/ent/group" "github.com/facebookincubator/ent/examples/start/ent/predicate" "github.com/facebookincubator/ent/examples/start/ent/user" + "github.com/facebookincubator/ent/schema/field" ) // UserUpdate is the builder for updating User entities. @@ -179,126 +182,127 @@ func (uu *UserUpdate) ExecX(ctx context.Context) { } func (uu *UserUpdate) sqlSave(ctx context.Context) (n int, err error) { - var ( - builder = sql.Dialect(uu.driver.Dialect()) - selector = builder.Select(user.FieldID).From(builder.Table(user.Table)) - ) - for _, p := range uu.predicates { - p(selector) + spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: user.Table, + Columns: user.Columns, + ID: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: user.FieldID, + }, + }, } - rows := &sql.Rows{} - query, args := selector.Query() - if err = uu.driver.Query(ctx, query, args, rows); err != nil { - return 0, err - } - defer rows.Close() - - var ids []int - for rows.Next() { - var id int - if err := rows.Scan(&id); err != nil { - return 0, fmt.Errorf("ent: failed reading id: %v", err) + if ps := uu.predicates; len(ps) > 0 { + spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } } - ids = append(ids, id) } - if len(ids) == 0 { - return 0, nil - } - - tx, err := uu.driver.Tx(ctx) - if err != nil { - return 0, err - } - var ( - res sql.Result - updater = builder.Update(user.Table) - ) - updater = updater.Where(sql.InInts(user.FieldID, ids...)) if value := uu.age; value != nil { - updater.Set(user.FieldAge, *value) + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: *value, + Column: user.FieldAge, + }) } if value := uu.addage; value != nil { - updater.Add(user.FieldAge, *value) + spec.Fields.Add = append(spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: *value, + Column: user.FieldAge, + }) } if value := uu.name; value != nil { - updater.Set(user.FieldName, *value) + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: *value, + Column: user.FieldName, + }) } - if !updater.Empty() { - query, args := updater.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) + if nodes := uu.removedCars; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: user.CarsTable, + Columns: []string{user.CarsColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: car.FieldID, + }, + }, } + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + spec.Edges.Clear = append(spec.Edges.Clear, edge) } - if len(uu.removedCars) > 0 { - eids := make([]int, len(uu.removedCars)) - for eid := range uu.removedCars { - eids = append(eids, eid) + if nodes := uu.cars; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: user.CarsTable, + Columns: []string{user.CarsColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: car.FieldID, + }, + }, } - query, args := builder.Update(user.CarsTable). - SetNull(user.CarsColumn). - Where(sql.InInts(user.CarsColumn, ids...)). - Where(sql.InInts(car.FieldID, eids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) } + spec.Edges.Add = append(spec.Edges.Add, edge) } - if len(uu.cars) > 0 { - for _, id := range ids { - p := sql.P() - for eid := range uu.cars { - p.Or().EQ(car.FieldID, eid) - } - query, args := builder.Update(user.CarsTable). - Set(user.CarsColumn, id). - Where(sql.And(p, sql.IsNull(user.CarsColumn))). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } - affected, err := res.RowsAffected() - if err != nil { - return 0, rollback(tx, err) - } - if int(affected) < len(uu.cars) { - return 0, rollback(tx, &ConstraintError{msg: fmt.Sprintf("one of \"cars\" %v already connected to a different \"User\"", keys(uu.cars))}) - } + if nodes := uu.removedGroups; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: true, + Table: user.GroupsTable, + Columns: user.GroupsPrimaryKey, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: group.FieldID, + }, + }, } + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + spec.Edges.Clear = append(spec.Edges.Clear, edge) } - if len(uu.removedGroups) > 0 { - eids := make([]int, len(uu.removedGroups)) - for eid := range uu.removedGroups { - eids = append(eids, eid) + if nodes := uu.groups; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: true, + Table: user.GroupsTable, + Columns: user.GroupsPrimaryKey, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: group.FieldID, + }, + }, } - query, args := builder.Delete(user.GroupsTable). - Where(sql.InInts(user.GroupsPrimaryKey[1], ids...)). - Where(sql.InInts(user.GroupsPrimaryKey[0], eids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) } + spec.Edges.Add = append(spec.Edges.Add, edge) } - if len(uu.groups) > 0 { - values := make([][]int, 0, len(ids)) - for _, id := range ids { - for eid := range uu.groups { - values = append(values, []int{id, eid}) - } + if n, err = sqlgraph.UpdateNodes(ctx, uu.driver, spec); err != nil { + if cerr, ok := isSQLConstraintError(err); ok { + err = cerr } - builder := builder.Insert(user.GroupsTable). - Columns(user.GroupsPrimaryKey[1], user.GroupsPrimaryKey[0]) - for _, v := range values { - builder.Values(v[0], v[1]) - } - query, args := builder.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } - } - if err = tx.Commit(); err != nil { return 0, err } - return len(ids), nil + return n, nil } // UserUpdateOne is the builder for updating a single User entity. @@ -458,129 +462,146 @@ func (uuo *UserUpdateOne) ExecX(ctx context.Context) { } func (uuo *UserUpdateOne) sqlSave(ctx context.Context) (u *User, err error) { - var ( - builder = sql.Dialect(uuo.driver.Dialect()) - selector = builder.Select(user.Columns...).From(builder.Table(user.Table)) - ) - user.ID(uuo.id)(selector) - rows := &sql.Rows{} - query, args := selector.Query() - if err = uuo.driver.Query(ctx, query, args, rows); err != nil { - return nil, err + spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: user.Table, + Columns: user.Columns, + ID: &sqlgraph.FieldSpec{ + Value: uuo.id, + Type: field.TypeInt, + Column: user.FieldID, + }, + }, } - defer rows.Close() - - var ids []int - for rows.Next() { - var id int - u = &User{config: uuo.config} - if err := u.FromRows(rows); err != nil { - return nil, fmt.Errorf("ent: failed scanning row into User: %v", err) - } - id = u.ID - ids = append(ids, id) - } - switch n := len(ids); { - case n == 0: - return nil, &ErrNotFound{fmt.Sprintf("User with id: %v", uuo.id)} - case n > 1: - return nil, fmt.Errorf("ent: more than one User with the same id: %v", uuo.id) - } - - tx, err := uuo.driver.Tx(ctx) - if err != nil { - return nil, err - } - var ( - res sql.Result - updater = builder.Update(user.Table) - ) - updater = updater.Where(sql.InInts(user.FieldID, ids...)) if value := uuo.age; value != nil { - updater.Set(user.FieldAge, *value) - u.Age = *value + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: *value, + Column: user.FieldAge, + }) } if value := uuo.addage; value != nil { - updater.Add(user.FieldAge, *value) - u.Age += *value + spec.Fields.Add = append(spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: *value, + Column: user.FieldAge, + }) } if value := uuo.name; value != nil { - updater.Set(user.FieldName, *value) - u.Name = *value + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: *value, + Column: user.FieldName, + }) } - if !updater.Empty() { - query, args := updater.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) + if nodes := uuo.removedCars; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: user.CarsTable, + Columns: []string{user.CarsColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: car.FieldID, + }, + }, } + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + spec.Edges.Clear = append(spec.Edges.Clear, edge) } - if len(uuo.removedCars) > 0 { - eids := make([]int, len(uuo.removedCars)) - for eid := range uuo.removedCars { - eids = append(eids, eid) + if nodes := uuo.cars; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: user.CarsTable, + Columns: []string{user.CarsColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: car.FieldID, + }, + }, } - query, args := builder.Update(user.CarsTable). - SetNull(user.CarsColumn). - Where(sql.InInts(user.CarsColumn, ids...)). - Where(sql.InInts(car.FieldID, eids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) } + spec.Edges.Add = append(spec.Edges.Add, edge) } - if len(uuo.cars) > 0 { - for _, id := range ids { - p := sql.P() - for eid := range uuo.cars { - p.Or().EQ(car.FieldID, eid) - } - query, args := builder.Update(user.CarsTable). - Set(user.CarsColumn, id). - Where(sql.And(p, sql.IsNull(user.CarsColumn))). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) - } - affected, err := res.RowsAffected() - if err != nil { - return nil, rollback(tx, err) - } - if int(affected) < len(uuo.cars) { - return nil, rollback(tx, &ConstraintError{msg: fmt.Sprintf("one of \"cars\" %v already connected to a different \"User\"", keys(uuo.cars))}) - } + if nodes := uuo.removedGroups; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: true, + Table: user.GroupsTable, + Columns: user.GroupsPrimaryKey, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: group.FieldID, + }, + }, } + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + spec.Edges.Clear = append(spec.Edges.Clear, edge) } - if len(uuo.removedGroups) > 0 { - eids := make([]int, len(uuo.removedGroups)) - for eid := range uuo.removedGroups { - eids = append(eids, eid) + if nodes := uuo.groups; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: true, + Table: user.GroupsTable, + Columns: user.GroupsPrimaryKey, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: group.FieldID, + }, + }, } - query, args := builder.Delete(user.GroupsTable). - Where(sql.InInts(user.GroupsPrimaryKey[1], ids...)). - Where(sql.InInts(user.GroupsPrimaryKey[0], eids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) } + spec.Edges.Add = append(spec.Edges.Add, edge) } - if len(uuo.groups) > 0 { - values := make([][]int, 0, len(ids)) - for _, id := range ids { - for eid := range uuo.groups { - values = append(values, []int{id, eid}) - } - } - builder := builder.Insert(user.GroupsTable). - Columns(user.GroupsPrimaryKey[1], user.GroupsPrimaryKey[0]) - for _, v := range values { - builder.Values(v[0], v[1]) - } - query, args := builder.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) - } + u = &User{config: uuo.config} + spec.ScanTypes = []interface{}{ + &sql.NullInt64{}, + &sql.NullInt64{}, + &sql.NullString{}, } - if err = tx.Commit(); err != nil { + spec.Assign = func(values ...interface{}) error { + if m, n := len(values), len(spec.ScanTypes); m != n { + return fmt.Errorf("mismatch number of scan values: %d != %d", m, n) + } + value, ok := values[0].(*sql.NullInt64) + if !ok { + return fmt.Errorf("unexpected type %T for field id", value) + } + u.ID = int(value.Int64) + values = values[1:] + if value, ok := values[0].(*sql.NullInt64); !ok { + return fmt.Errorf("unexpected type %T for field age", values[0]) + } else if value.Valid { + u.Age = int(value.Int64) + } + if value, ok := values[1].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field name", values[1]) + } else if value.Valid { + u.Name = value.String + } + return nil + } + if err = sqlgraph.UpdateNode(ctx, uuo.driver, spec); err != nil { + if cerr, ok := isSQLConstraintError(err); ok { + err = cerr + } return nil, err } return u, nil diff --git a/examples/traversal/ent/group_update.go b/examples/traversal/ent/group_update.go index 8bd541474..1d8445124 100644 --- a/examples/traversal/ent/group_update.go +++ b/examples/traversal/ent/group_update.go @@ -12,9 +12,11 @@ import ( "fmt" "github.com/facebookincubator/ent/dialect/sql" + "github.com/facebookincubator/ent/dialect/sql/sqlgraph" "github.com/facebookincubator/ent/examples/traversal/ent/group" "github.com/facebookincubator/ent/examples/traversal/ent/predicate" "github.com/facebookincubator/ent/examples/traversal/ent/user" + "github.com/facebookincubator/ent/schema/field" ) // GroupUpdate is the builder for updating Group entities. @@ -139,104 +141,110 @@ func (gu *GroupUpdate) ExecX(ctx context.Context) { } func (gu *GroupUpdate) sqlSave(ctx context.Context) (n int, err error) { - var ( - builder = sql.Dialect(gu.driver.Dialect()) - selector = builder.Select(group.FieldID).From(builder.Table(group.Table)) - ) - for _, p := range gu.predicates { - p(selector) + spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: group.Table, + Columns: group.Columns, + ID: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: group.FieldID, + }, + }, } - rows := &sql.Rows{} - query, args := selector.Query() - if err = gu.driver.Query(ctx, query, args, rows); err != nil { - return 0, err - } - defer rows.Close() - - var ids []int - for rows.Next() { - var id int - if err := rows.Scan(&id); err != nil { - return 0, fmt.Errorf("ent: failed reading id: %v", err) - } - ids = append(ids, id) - } - if len(ids) == 0 { - return 0, nil - } - - tx, err := gu.driver.Tx(ctx) - if err != nil { - return 0, err - } - var ( - res sql.Result - updater = builder.Update(group.Table) - ) - updater = updater.Where(sql.InInts(group.FieldID, ids...)) - if value := gu.name; value != nil { - updater.Set(group.FieldName, *value) - } - if !updater.Empty() { - query, args := updater.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } - } - if len(gu.removedUsers) > 0 { - eids := make([]int, len(gu.removedUsers)) - for eid := range gu.removedUsers { - eids = append(eids, eid) - } - query, args := builder.Delete(group.UsersTable). - Where(sql.InInts(group.UsersPrimaryKey[0], ids...)). - Where(sql.InInts(group.UsersPrimaryKey[1], eids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } - } - if len(gu.users) > 0 { - values := make([][]int, 0, len(ids)) - for _, id := range ids { - for eid := range gu.users { - values = append(values, []int{id, eid}) + if ps := gu.predicates; len(ps) > 0 { + spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) } } - builder := builder.Insert(group.UsersTable). - Columns(group.UsersPrimaryKey[0], group.UsersPrimaryKey[1]) - for _, v := range values { - builder.Values(v[0], v[1]) + } + if value := gu.name; value != nil { + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: *value, + Column: group.FieldName, + }) + } + if nodes := gu.removedUsers; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: false, + Table: group.UsersTable, + Columns: group.UsersPrimaryKey, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: user.FieldID, + }, + }, } - query, args := builder.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) } + spec.Edges.Clear = append(spec.Edges.Clear, edge) + } + if nodes := gu.users; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: false, + Table: group.UsersTable, + Columns: group.UsersPrimaryKey, + Bidi: false, + 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 gu.clearedAdmin { - query, args := builder.Update(group.AdminTable). - SetNull(group.AdminColumn). - Where(sql.InInts(user.FieldID, ids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: false, + Table: group.AdminTable, + Columns: []string{group.AdminColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: user.FieldID, + }, + }, } + spec.Edges.Clear = append(spec.Edges.Clear, edge) } - if len(gu.admin) > 0 { - for eid := range gu.admin { - query, args := builder.Update(group.AdminTable). - Set(group.AdminColumn, eid). - Where(sql.InInts(group.FieldID, ids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } + if nodes := gu.admin; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: false, + Table: group.AdminTable, + Columns: []string{group.AdminColumn}, + Bidi: false, + 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 err = tx.Commit(); err != nil { + if n, err = sqlgraph.UpdateNodes(ctx, gu.driver, spec); err != nil { + if cerr, ok := isSQLConstraintError(err); ok { + err = cerr + } return 0, err } - return len(ids), nil + return n, nil } // GroupUpdateOne is the builder for updating a single Group entity. @@ -355,105 +363,123 @@ func (guo *GroupUpdateOne) ExecX(ctx context.Context) { } func (guo *GroupUpdateOne) sqlSave(ctx context.Context) (gr *Group, err error) { - var ( - builder = sql.Dialect(guo.driver.Dialect()) - selector = builder.Select(group.Columns...).From(builder.Table(group.Table)) - ) - group.ID(guo.id)(selector) - rows := &sql.Rows{} - query, args := selector.Query() - if err = guo.driver.Query(ctx, query, args, rows); err != nil { - return nil, err + spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: group.Table, + Columns: group.Columns, + ID: &sqlgraph.FieldSpec{ + Value: guo.id, + Type: field.TypeInt, + Column: group.FieldID, + }, + }, } - defer rows.Close() - - var ids []int - for rows.Next() { - var id int - gr = &Group{config: guo.config} - if err := gr.FromRows(rows); err != nil { - return nil, fmt.Errorf("ent: failed scanning row into Group: %v", err) - } - id = gr.ID - ids = append(ids, id) - } - switch n := len(ids); { - case n == 0: - return nil, &ErrNotFound{fmt.Sprintf("Group with id: %v", guo.id)} - case n > 1: - return nil, fmt.Errorf("ent: more than one Group with the same id: %v", guo.id) - } - - tx, err := guo.driver.Tx(ctx) - if err != nil { - return nil, err - } - var ( - res sql.Result - updater = builder.Update(group.Table) - ) - updater = updater.Where(sql.InInts(group.FieldID, ids...)) if value := guo.name; value != nil { - updater.Set(group.FieldName, *value) - gr.Name = *value + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: *value, + Column: group.FieldName, + }) } - if !updater.Empty() { - query, args := updater.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) + if nodes := guo.removedUsers; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: false, + Table: group.UsersTable, + Columns: group.UsersPrimaryKey, + Bidi: false, + 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 len(guo.removedUsers) > 0 { - eids := make([]int, len(guo.removedUsers)) - for eid := range guo.removedUsers { - eids = append(eids, eid) + if nodes := guo.users; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: false, + Table: group.UsersTable, + Columns: group.UsersPrimaryKey, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: user.FieldID, + }, + }, } - query, args := builder.Delete(group.UsersTable). - Where(sql.InInts(group.UsersPrimaryKey[0], ids...)). - Where(sql.InInts(group.UsersPrimaryKey[1], eids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) - } - } - if len(guo.users) > 0 { - values := make([][]int, 0, len(ids)) - for _, id := range ids { - for eid := range guo.users { - values = append(values, []int{id, eid}) - } - } - builder := builder.Insert(group.UsersTable). - Columns(group.UsersPrimaryKey[0], group.UsersPrimaryKey[1]) - for _, v := range values { - builder.Values(v[0], v[1]) - } - query, args := builder.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) } + spec.Edges.Add = append(spec.Edges.Add, edge) } if guo.clearedAdmin { - query, args := builder.Update(group.AdminTable). - SetNull(group.AdminColumn). - Where(sql.InInts(user.FieldID, ids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: false, + Table: group.AdminTable, + Columns: []string{group.AdminColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: user.FieldID, + }, + }, } + spec.Edges.Clear = append(spec.Edges.Clear, edge) } - if len(guo.admin) > 0 { - for eid := range guo.admin { - query, args := builder.Update(group.AdminTable). - Set(group.AdminColumn, eid). - Where(sql.InInts(group.FieldID, ids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) - } + if nodes := guo.admin; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: false, + Table: group.AdminTable, + Columns: []string{group.AdminColumn}, + Bidi: false, + 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 err = tx.Commit(); err != nil { + gr = &Group{config: guo.config} + spec.ScanTypes = []interface{}{ + &sql.NullInt64{}, + &sql.NullString{}, + } + spec.Assign = func(values ...interface{}) error { + if m, n := len(values), len(spec.ScanTypes); m != n { + return fmt.Errorf("mismatch number of scan values: %d != %d", m, n) + } + value, ok := values[0].(*sql.NullInt64) + if !ok { + return fmt.Errorf("unexpected type %T for field id", value) + } + gr.ID = int(value.Int64) + values = values[1:] + if value, ok := values[0].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field name", values[0]) + } else if value.Valid { + gr.Name = value.String + } + return nil + } + if err = sqlgraph.UpdateNode(ctx, guo.driver, spec); err != nil { + if cerr, ok := isSQLConstraintError(err); ok { + err = cerr + } return nil, err } return gr, nil diff --git a/examples/traversal/ent/pet_update.go b/examples/traversal/ent/pet_update.go index c8785012c..7e22207cd 100644 --- a/examples/traversal/ent/pet_update.go +++ b/examples/traversal/ent/pet_update.go @@ -12,9 +12,11 @@ import ( "fmt" "github.com/facebookincubator/ent/dialect/sql" + "github.com/facebookincubator/ent/dialect/sql/sqlgraph" "github.com/facebookincubator/ent/examples/traversal/ent/pet" "github.com/facebookincubator/ent/examples/traversal/ent/predicate" "github.com/facebookincubator/ent/examples/traversal/ent/user" + "github.com/facebookincubator/ent/schema/field" ) // PetUpdate is the builder for updating Pet entities. @@ -139,111 +141,110 @@ func (pu *PetUpdate) ExecX(ctx context.Context) { } func (pu *PetUpdate) sqlSave(ctx context.Context) (n int, err error) { - var ( - builder = sql.Dialect(pu.driver.Dialect()) - selector = builder.Select(pet.FieldID).From(builder.Table(pet.Table)) - ) - for _, p := range pu.predicates { - p(selector) + spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: pet.Table, + Columns: pet.Columns, + ID: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: pet.FieldID, + }, + }, } - rows := &sql.Rows{} - query, args := selector.Query() - if err = pu.driver.Query(ctx, query, args, rows); err != nil { - return 0, err - } - defer rows.Close() - - var ids []int - for rows.Next() { - var id int - if err := rows.Scan(&id); err != nil { - return 0, fmt.Errorf("ent: failed reading id: %v", err) - } - ids = append(ids, id) - } - if len(ids) == 0 { - return 0, nil - } - - tx, err := pu.driver.Tx(ctx) - if err != nil { - return 0, err - } - var ( - res sql.Result - updater = builder.Update(pet.Table) - ) - updater = updater.Where(sql.InInts(pet.FieldID, ids...)) - if value := pu.name; value != nil { - updater.Set(pet.FieldName, *value) - } - if !updater.Empty() { - query, args := updater.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } - } - if len(pu.removedFriends) > 0 { - eids := make([]int, len(pu.removedFriends)) - for eid := range pu.removedFriends { - eids = append(eids, eid) - } - query, args := builder.Delete(pet.FriendsTable). - Where(sql.InInts(pet.FriendsPrimaryKey[0], ids...)). - Where(sql.InInts(pet.FriendsPrimaryKey[1], eids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } - query, args = builder.Delete(pet.FriendsTable). - Where(sql.InInts(pet.FriendsPrimaryKey[1], ids...)). - Where(sql.InInts(pet.FriendsPrimaryKey[0], eids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } - } - if len(pu.friends) > 0 { - values := make([][]int, 0, len(ids)) - for _, id := range ids { - for eid := range pu.friends { - values = append(values, []int{id, eid}, []int{eid, id}) + if ps := pu.predicates; len(ps) > 0 { + spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) } } - builder := builder.Insert(pet.FriendsTable). - Columns(pet.FriendsPrimaryKey[0], pet.FriendsPrimaryKey[1]) - for _, v := range values { - builder.Values(v[0], v[1]) + } + if value := pu.name; value != nil { + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: *value, + Column: pet.FieldName, + }) + } + if nodes := pu.removedFriends; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: false, + Table: pet.FriendsTable, + Columns: pet.FriendsPrimaryKey, + Bidi: true, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: pet.FieldID, + }, + }, } - query, args := builder.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) } + spec.Edges.Clear = append(spec.Edges.Clear, edge) + } + if nodes := pu.friends; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: false, + Table: pet.FriendsTable, + Columns: pet.FriendsPrimaryKey, + Bidi: true, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: pet.FieldID, + }, + }, + } + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + spec.Edges.Add = append(spec.Edges.Add, edge) } if pu.clearedOwner { - query, args := builder.Update(pet.OwnerTable). - SetNull(pet.OwnerColumn). - Where(sql.InInts(user.FieldID, ids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: pet.OwnerTable, + Columns: []string{pet.OwnerColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: user.FieldID, + }, + }, } + spec.Edges.Clear = append(spec.Edges.Clear, edge) } - if len(pu.owner) > 0 { - for eid := range pu.owner { - query, args := builder.Update(pet.OwnerTable). - Set(pet.OwnerColumn, eid). - Where(sql.InInts(pet.FieldID, ids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } + if nodes := pu.owner; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: pet.OwnerTable, + Columns: []string{pet.OwnerColumn}, + Bidi: false, + 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 err = tx.Commit(); err != nil { + if n, err = sqlgraph.UpdateNodes(ctx, pu.driver, spec); err != nil { + if cerr, ok := isSQLConstraintError(err); ok { + err = cerr + } return 0, err } - return len(ids), nil + return n, nil } // PetUpdateOne is the builder for updating a single Pet entity. @@ -362,112 +363,123 @@ func (puo *PetUpdateOne) ExecX(ctx context.Context) { } func (puo *PetUpdateOne) sqlSave(ctx context.Context) (pe *Pet, err error) { - var ( - builder = sql.Dialect(puo.driver.Dialect()) - selector = builder.Select(pet.Columns...).From(builder.Table(pet.Table)) - ) - pet.ID(puo.id)(selector) - rows := &sql.Rows{} - query, args := selector.Query() - if err = puo.driver.Query(ctx, query, args, rows); err != nil { - return nil, err + spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: pet.Table, + Columns: pet.Columns, + ID: &sqlgraph.FieldSpec{ + Value: puo.id, + Type: field.TypeInt, + Column: pet.FieldID, + }, + }, } - defer rows.Close() - - var ids []int - for rows.Next() { - var id int - pe = &Pet{config: puo.config} - if err := pe.FromRows(rows); err != nil { - return nil, fmt.Errorf("ent: failed scanning row into Pet: %v", err) - } - id = pe.ID - ids = append(ids, id) - } - switch n := len(ids); { - case n == 0: - return nil, &ErrNotFound{fmt.Sprintf("Pet with id: %v", puo.id)} - case n > 1: - return nil, fmt.Errorf("ent: more than one Pet with the same id: %v", puo.id) - } - - tx, err := puo.driver.Tx(ctx) - if err != nil { - return nil, err - } - var ( - res sql.Result - updater = builder.Update(pet.Table) - ) - updater = updater.Where(sql.InInts(pet.FieldID, ids...)) if value := puo.name; value != nil { - updater.Set(pet.FieldName, *value) - pe.Name = *value + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: *value, + Column: pet.FieldName, + }) } - if !updater.Empty() { - query, args := updater.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) + if nodes := puo.removedFriends; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: false, + Table: pet.FriendsTable, + Columns: pet.FriendsPrimaryKey, + Bidi: true, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: pet.FieldID, + }, + }, } + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + spec.Edges.Clear = append(spec.Edges.Clear, edge) } - if len(puo.removedFriends) > 0 { - eids := make([]int, len(puo.removedFriends)) - for eid := range puo.removedFriends { - eids = append(eids, eid) + if nodes := puo.friends; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: false, + Table: pet.FriendsTable, + Columns: pet.FriendsPrimaryKey, + Bidi: true, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: pet.FieldID, + }, + }, } - query, args := builder.Delete(pet.FriendsTable). - Where(sql.InInts(pet.FriendsPrimaryKey[0], ids...)). - Where(sql.InInts(pet.FriendsPrimaryKey[1], eids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) - } - query, args = builder.Delete(pet.FriendsTable). - Where(sql.InInts(pet.FriendsPrimaryKey[1], ids...)). - Where(sql.InInts(pet.FriendsPrimaryKey[0], eids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) - } - } - if len(puo.friends) > 0 { - values := make([][]int, 0, len(ids)) - for _, id := range ids { - for eid := range puo.friends { - values = append(values, []int{id, eid}, []int{eid, id}) - } - } - builder := builder.Insert(pet.FriendsTable). - Columns(pet.FriendsPrimaryKey[0], pet.FriendsPrimaryKey[1]) - for _, v := range values { - builder.Values(v[0], v[1]) - } - query, args := builder.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) } + spec.Edges.Add = append(spec.Edges.Add, edge) } if puo.clearedOwner { - query, args := builder.Update(pet.OwnerTable). - SetNull(pet.OwnerColumn). - Where(sql.InInts(user.FieldID, ids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: pet.OwnerTable, + Columns: []string{pet.OwnerColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: user.FieldID, + }, + }, } + spec.Edges.Clear = append(spec.Edges.Clear, edge) } - if len(puo.owner) > 0 { - for eid := range puo.owner { - query, args := builder.Update(pet.OwnerTable). - Set(pet.OwnerColumn, eid). - Where(sql.InInts(pet.FieldID, ids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) - } + if nodes := puo.owner; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: pet.OwnerTable, + Columns: []string{pet.OwnerColumn}, + Bidi: false, + 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 err = tx.Commit(); err != nil { + pe = &Pet{config: puo.config} + spec.ScanTypes = []interface{}{ + &sql.NullInt64{}, + &sql.NullString{}, + } + spec.Assign = func(values ...interface{}) error { + if m, n := len(values), len(spec.ScanTypes); m != n { + return fmt.Errorf("mismatch number of scan values: %d != %d", m, n) + } + value, ok := values[0].(*sql.NullInt64) + if !ok { + return fmt.Errorf("unexpected type %T for field id", value) + } + pe.ID = int(value.Int64) + values = values[1:] + if value, ok := values[0].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field name", values[0]) + } else if value.Valid { + pe.Name = value.String + } + return nil + } + if err = sqlgraph.UpdateNode(ctx, puo.driver, spec); err != nil { + if cerr, ok := isSQLConstraintError(err); ok { + err = cerr + } return nil, err } return pe, nil diff --git a/examples/traversal/ent/user_update.go b/examples/traversal/ent/user_update.go index ba694afc6..b2bffb0e5 100644 --- a/examples/traversal/ent/user_update.go +++ b/examples/traversal/ent/user_update.go @@ -11,10 +11,12 @@ import ( "fmt" "github.com/facebookincubator/ent/dialect/sql" + "github.com/facebookincubator/ent/dialect/sql/sqlgraph" "github.com/facebookincubator/ent/examples/traversal/ent/group" "github.com/facebookincubator/ent/examples/traversal/ent/pet" "github.com/facebookincubator/ent/examples/traversal/ent/predicate" "github.com/facebookincubator/ent/examples/traversal/ent/user" + "github.com/facebookincubator/ent/schema/field" ) // UserUpdate is the builder for updating User entities. @@ -251,199 +253,203 @@ func (uu *UserUpdate) ExecX(ctx context.Context) { } func (uu *UserUpdate) sqlSave(ctx context.Context) (n int, err error) { - var ( - builder = sql.Dialect(uu.driver.Dialect()) - selector = builder.Select(user.FieldID).From(builder.Table(user.Table)) - ) - for _, p := range uu.predicates { - p(selector) + spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: user.Table, + Columns: user.Columns, + ID: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: user.FieldID, + }, + }, } - rows := &sql.Rows{} - query, args := selector.Query() - if err = uu.driver.Query(ctx, query, args, rows); err != nil { - return 0, err - } - defer rows.Close() - - var ids []int - for rows.Next() { - var id int - if err := rows.Scan(&id); err != nil { - return 0, fmt.Errorf("ent: failed reading id: %v", err) + if ps := uu.predicates; len(ps) > 0 { + spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } } - ids = append(ids, id) } - if len(ids) == 0 { - return 0, nil - } - - tx, err := uu.driver.Tx(ctx) - if err != nil { - return 0, err - } - var ( - res sql.Result - updater = builder.Update(user.Table) - ) - updater = updater.Where(sql.InInts(user.FieldID, ids...)) if value := uu.age; value != nil { - updater.Set(user.FieldAge, *value) + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: *value, + Column: user.FieldAge, + }) } if value := uu.addage; value != nil { - updater.Add(user.FieldAge, *value) + spec.Fields.Add = append(spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: *value, + Column: user.FieldAge, + }) } if value := uu.name; value != nil { - updater.Set(user.FieldName, *value) + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: *value, + Column: user.FieldName, + }) } - if !updater.Empty() { - query, args := updater.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) + if nodes := uu.removedPets; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: user.PetsTable, + Columns: []string{user.PetsColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: pet.FieldID, + }, + }, } + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + spec.Edges.Clear = append(spec.Edges.Clear, edge) } - if len(uu.removedPets) > 0 { - eids := make([]int, len(uu.removedPets)) - for eid := range uu.removedPets { - eids = append(eids, eid) + if nodes := uu.pets; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: user.PetsTable, + Columns: []string{user.PetsColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: pet.FieldID, + }, + }, } - query, args := builder.Update(user.PetsTable). - SetNull(user.PetsColumn). - Where(sql.InInts(user.PetsColumn, ids...)). - Where(sql.InInts(pet.FieldID, eids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) } + spec.Edges.Add = append(spec.Edges.Add, edge) } - if len(uu.pets) > 0 { - for _, id := range ids { - p := sql.P() - for eid := range uu.pets { - p.Or().EQ(pet.FieldID, eid) - } - query, args := builder.Update(user.PetsTable). - Set(user.PetsColumn, id). - Where(sql.And(p, sql.IsNull(user.PetsColumn))). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } - affected, err := res.RowsAffected() - if err != nil { - return 0, rollback(tx, err) - } - if int(affected) < len(uu.pets) { - return 0, rollback(tx, &ConstraintError{msg: fmt.Sprintf("one of \"pets\" %v already connected to a different \"User\"", keys(uu.pets))}) - } + if nodes := uu.removedFriends; 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 len(uu.removedFriends) > 0 { - eids := make([]int, len(uu.removedFriends)) - for eid := range uu.removedFriends { - eids = append(eids, eid) + if nodes := uu.friends; 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, + }, + }, } - query, args := builder.Delete(user.FriendsTable). - Where(sql.InInts(user.FriendsPrimaryKey[0], ids...)). - Where(sql.InInts(user.FriendsPrimaryKey[1], eids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } - query, args = builder.Delete(user.FriendsTable). - Where(sql.InInts(user.FriendsPrimaryKey[1], ids...)). - Where(sql.InInts(user.FriendsPrimaryKey[0], eids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) } + spec.Edges.Add = append(spec.Edges.Add, edge) } - if len(uu.friends) > 0 { - values := make([][]int, 0, len(ids)) - for _, id := range ids { - for eid := range uu.friends { - values = append(values, []int{id, eid}, []int{eid, id}) - } + if nodes := uu.removedGroups; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: true, + Table: user.GroupsTable, + Columns: user.GroupsPrimaryKey, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: group.FieldID, + }, + }, } - builder := builder.Insert(user.FriendsTable). - Columns(user.FriendsPrimaryKey[0], user.FriendsPrimaryKey[1]) - for _, v := range values { - builder.Values(v[0], v[1]) - } - query, args := builder.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) } + spec.Edges.Clear = append(spec.Edges.Clear, edge) } - if len(uu.removedGroups) > 0 { - eids := make([]int, len(uu.removedGroups)) - for eid := range uu.removedGroups { - eids = append(eids, eid) + if nodes := uu.groups; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: true, + Table: user.GroupsTable, + Columns: user.GroupsPrimaryKey, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: group.FieldID, + }, + }, } - query, args := builder.Delete(user.GroupsTable). - Where(sql.InInts(user.GroupsPrimaryKey[1], ids...)). - Where(sql.InInts(user.GroupsPrimaryKey[0], eids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) } + spec.Edges.Add = append(spec.Edges.Add, edge) } - if len(uu.groups) > 0 { - values := make([][]int, 0, len(ids)) - for _, id := range ids { - for eid := range uu.groups { - values = append(values, []int{id, eid}) - } + if nodes := uu.removedManage; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: true, + Table: user.ManageTable, + Columns: []string{user.ManageColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: group.FieldID, + }, + }, } - builder := builder.Insert(user.GroupsTable). - Columns(user.GroupsPrimaryKey[1], user.GroupsPrimaryKey[0]) - for _, v := range values { - builder.Values(v[0], v[1]) - } - query, args := builder.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) } + spec.Edges.Clear = append(spec.Edges.Clear, edge) } - if len(uu.removedManage) > 0 { - eids := make([]int, len(uu.removedManage)) - for eid := range uu.removedManage { - eids = append(eids, eid) + if nodes := uu.manage; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: true, + Table: user.ManageTable, + Columns: []string{user.ManageColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: group.FieldID, + }, + }, } - query, args := builder.Update(user.ManageTable). - SetNull(user.ManageColumn). - Where(sql.InInts(user.ManageColumn, ids...)). - Where(sql.InInts(group.FieldID, eids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) } + spec.Edges.Add = append(spec.Edges.Add, edge) } - if len(uu.manage) > 0 { - for _, id := range ids { - p := sql.P() - for eid := range uu.manage { - p.Or().EQ(group.FieldID, eid) - } - query, args := builder.Update(user.ManageTable). - Set(user.ManageColumn, id). - Where(sql.And(p, sql.IsNull(user.ManageColumn))). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return 0, rollback(tx, err) - } - affected, err := res.RowsAffected() - if err != nil { - return 0, rollback(tx, err) - } - if int(affected) < len(uu.manage) { - return 0, rollback(tx, &ConstraintError{msg: fmt.Sprintf("one of \"manage\" %v already connected to a different \"User\"", keys(uu.manage))}) - } + if n, err = sqlgraph.UpdateNodes(ctx, uu.driver, spec); err != nil { + if cerr, ok := isSQLConstraintError(err); ok { + err = cerr } - } - if err = tx.Commit(); err != nil { return 0, err } - return len(ids), nil + return n, nil } // UserUpdateOne is the builder for updating a single User entity. @@ -674,202 +680,222 @@ func (uuo *UserUpdateOne) ExecX(ctx context.Context) { } func (uuo *UserUpdateOne) sqlSave(ctx context.Context) (u *User, err error) { - var ( - builder = sql.Dialect(uuo.driver.Dialect()) - selector = builder.Select(user.Columns...).From(builder.Table(user.Table)) - ) - user.ID(uuo.id)(selector) - rows := &sql.Rows{} - query, args := selector.Query() - if err = uuo.driver.Query(ctx, query, args, rows); err != nil { - return nil, err + spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: user.Table, + Columns: user.Columns, + ID: &sqlgraph.FieldSpec{ + Value: uuo.id, + Type: field.TypeInt, + Column: user.FieldID, + }, + }, } - defer rows.Close() - - var ids []int - for rows.Next() { - var id int - u = &User{config: uuo.config} - if err := u.FromRows(rows); err != nil { - return nil, fmt.Errorf("ent: failed scanning row into User: %v", err) - } - id = u.ID - ids = append(ids, id) - } - switch n := len(ids); { - case n == 0: - return nil, &ErrNotFound{fmt.Sprintf("User with id: %v", uuo.id)} - case n > 1: - return nil, fmt.Errorf("ent: more than one User with the same id: %v", uuo.id) - } - - tx, err := uuo.driver.Tx(ctx) - if err != nil { - return nil, err - } - var ( - res sql.Result - updater = builder.Update(user.Table) - ) - updater = updater.Where(sql.InInts(user.FieldID, ids...)) if value := uuo.age; value != nil { - updater.Set(user.FieldAge, *value) - u.Age = *value + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: *value, + Column: user.FieldAge, + }) } if value := uuo.addage; value != nil { - updater.Add(user.FieldAge, *value) - u.Age += *value + spec.Fields.Add = append(spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: *value, + Column: user.FieldAge, + }) } if value := uuo.name; value != nil { - updater.Set(user.FieldName, *value) - u.Name = *value + spec.Fields.Set = append(spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: *value, + Column: user.FieldName, + }) } - if !updater.Empty() { - query, args := updater.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) + if nodes := uuo.removedPets; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: user.PetsTable, + Columns: []string{user.PetsColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: pet.FieldID, + }, + }, } + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + spec.Edges.Clear = append(spec.Edges.Clear, edge) } - if len(uuo.removedPets) > 0 { - eids := make([]int, len(uuo.removedPets)) - for eid := range uuo.removedPets { - eids = append(eids, eid) + if nodes := uuo.pets; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: user.PetsTable, + Columns: []string{user.PetsColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: pet.FieldID, + }, + }, } - query, args := builder.Update(user.PetsTable). - SetNull(user.PetsColumn). - Where(sql.InInts(user.PetsColumn, ids...)). - Where(sql.InInts(pet.FieldID, eids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) } + spec.Edges.Add = append(spec.Edges.Add, edge) } - if len(uuo.pets) > 0 { - for _, id := range ids { - p := sql.P() - for eid := range uuo.pets { - p.Or().EQ(pet.FieldID, eid) - } - query, args := builder.Update(user.PetsTable). - Set(user.PetsColumn, id). - Where(sql.And(p, sql.IsNull(user.PetsColumn))). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) - } - affected, err := res.RowsAffected() - if err != nil { - return nil, rollback(tx, err) - } - if int(affected) < len(uuo.pets) { - return nil, rollback(tx, &ConstraintError{msg: fmt.Sprintf("one of \"pets\" %v already connected to a different \"User\"", keys(uuo.pets))}) - } + if nodes := uuo.removedFriends; 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 len(uuo.removedFriends) > 0 { - eids := make([]int, len(uuo.removedFriends)) - for eid := range uuo.removedFriends { - eids = append(eids, eid) + if nodes := uuo.friends; 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, + }, + }, } - query, args := builder.Delete(user.FriendsTable). - Where(sql.InInts(user.FriendsPrimaryKey[0], ids...)). - Where(sql.InInts(user.FriendsPrimaryKey[1], eids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) - } - query, args = builder.Delete(user.FriendsTable). - Where(sql.InInts(user.FriendsPrimaryKey[1], ids...)). - Where(sql.InInts(user.FriendsPrimaryKey[0], eids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) } + spec.Edges.Add = append(spec.Edges.Add, edge) } - if len(uuo.friends) > 0 { - values := make([][]int, 0, len(ids)) - for _, id := range ids { - for eid := range uuo.friends { - values = append(values, []int{id, eid}, []int{eid, id}) - } + if nodes := uuo.removedGroups; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: true, + Table: user.GroupsTable, + Columns: user.GroupsPrimaryKey, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: group.FieldID, + }, + }, } - builder := builder.Insert(user.FriendsTable). - Columns(user.FriendsPrimaryKey[0], user.FriendsPrimaryKey[1]) - for _, v := range values { - builder.Values(v[0], v[1]) - } - query, args := builder.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) } + spec.Edges.Clear = append(spec.Edges.Clear, edge) } - if len(uuo.removedGroups) > 0 { - eids := make([]int, len(uuo.removedGroups)) - for eid := range uuo.removedGroups { - eids = append(eids, eid) + if nodes := uuo.groups; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: true, + Table: user.GroupsTable, + Columns: user.GroupsPrimaryKey, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: group.FieldID, + }, + }, } - query, args := builder.Delete(user.GroupsTable). - Where(sql.InInts(user.GroupsPrimaryKey[1], ids...)). - Where(sql.InInts(user.GroupsPrimaryKey[0], eids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) } + spec.Edges.Add = append(spec.Edges.Add, edge) } - if len(uuo.groups) > 0 { - values := make([][]int, 0, len(ids)) - for _, id := range ids { - for eid := range uuo.groups { - values = append(values, []int{id, eid}) - } + if nodes := uuo.removedManage; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: true, + Table: user.ManageTable, + Columns: []string{user.ManageColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: group.FieldID, + }, + }, } - builder := builder.Insert(user.GroupsTable). - Columns(user.GroupsPrimaryKey[1], user.GroupsPrimaryKey[0]) - for _, v := range values { - builder.Values(v[0], v[1]) - } - query, args := builder.Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) } + spec.Edges.Clear = append(spec.Edges.Clear, edge) } - if len(uuo.removedManage) > 0 { - eids := make([]int, len(uuo.removedManage)) - for eid := range uuo.removedManage { - eids = append(eids, eid) + if nodes := uuo.manage; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: true, + Table: user.ManageTable, + Columns: []string{user.ManageColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: group.FieldID, + }, + }, } - query, args := builder.Update(user.ManageTable). - SetNull(user.ManageColumn). - Where(sql.InInts(user.ManageColumn, ids...)). - Where(sql.InInts(group.FieldID, eids...)). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) } + spec.Edges.Add = append(spec.Edges.Add, edge) } - if len(uuo.manage) > 0 { - for _, id := range ids { - p := sql.P() - for eid := range uuo.manage { - p.Or().EQ(group.FieldID, eid) - } - query, args := builder.Update(user.ManageTable). - Set(user.ManageColumn, id). - Where(sql.And(p, sql.IsNull(user.ManageColumn))). - Query() - if err := tx.Exec(ctx, query, args, &res); err != nil { - return nil, rollback(tx, err) - } - affected, err := res.RowsAffected() - if err != nil { - return nil, rollback(tx, err) - } - if int(affected) < len(uuo.manage) { - return nil, rollback(tx, &ConstraintError{msg: fmt.Sprintf("one of \"manage\" %v already connected to a different \"User\"", keys(uuo.manage))}) - } - } + u = &User{config: uuo.config} + spec.ScanTypes = []interface{}{ + &sql.NullInt64{}, + &sql.NullInt64{}, + &sql.NullString{}, } - if err = tx.Commit(); err != nil { + spec.Assign = func(values ...interface{}) error { + if m, n := len(values), len(spec.ScanTypes); m != n { + return fmt.Errorf("mismatch number of scan values: %d != %d", m, n) + } + value, ok := values[0].(*sql.NullInt64) + if !ok { + return fmt.Errorf("unexpected type %T for field id", value) + } + u.ID = int(value.Int64) + values = values[1:] + if value, ok := values[0].(*sql.NullInt64); !ok { + return fmt.Errorf("unexpected type %T for field age", values[0]) + } else if value.Valid { + u.Age = int(value.Int64) + } + if value, ok := values[1].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field name", values[1]) + } else if value.Valid { + u.Name = value.String + } + return nil + } + if err = sqlgraph.UpdateNode(ctx, uuo.driver, spec); err != nil { + if cerr, ok := isSQLConstraintError(err); ok { + err = cerr + } return nil, err } return u, nil From d6d7ef565f2aa999320d9be53bbb3653c57e6a7c Mon Sep 17 00:00:00 2001 From: Ariel Mashraki Date: Sun, 22 Dec 2019 15:36:03 +0200 Subject: [PATCH 2/2] dialect/sql/sqlgraph: minor grammar changes --- dialect/sql/sqlgraph/graph.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dialect/sql/sqlgraph/graph.go b/dialect/sql/sqlgraph/graph.go index 2a9c3b9e7..19a904808 100644 --- a/dialect/sql/sqlgraph/graph.go +++ b/dialect/sql/sqlgraph/graph.go @@ -630,7 +630,7 @@ func (u *updater) setExternalEdges(ctx context.Context, ids []driver.Value, addE // setTableColumns sets the table columns and foreign_keys used in insert. func (u *updater) setTableColumns(update *sql.UpdateBuilder, addEdges, clearEdges map[Rel][]*EdgeSpec) error { - // Avoid multiple assignments to same column. + // Avoid multiple assignments to the same column. setEdges := make(map[string]bool) for _, e := range addEdges[M2O] { setEdges[e.Columns[0]] = true