PageSourceSearch

https://entgo.io/assets/js/5288f7dc.bd93d13c.js

js entgo.io collected 2026-10-03 22:16:30 UTC 21,668 bytes, 1 lines download raw bytes

1"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[6588],{3905:(e,n,t)=>{t.d(n,{Zo:()=>d,kt:()=>m});var a=t(7294);function r(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function l(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);n&&(a=a.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,a)}return t}function o(e){for(var n=1;n<arguments.length;n++){var t=null!=arguments[n]?arguments[n]:{};n%2?l(Object(t),!0).forEach((function(n){r(e,n,t[n])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(t)):l(Object(t)).forEach((function(n){Object.defineProperty(e,n,Object.getOwnPropertyDescriptor(t,n))}))}return e}function i(e,n){if(null==e)return{};var t,a,r=function(e,n){if(null==e)return{};var t,a,r={},l=Object.keys(e);for(a=0;a<l.length;a++)t=l[a],n.indexOf(t)>=0||(r[t]=e[t]);return r}(e,n);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(a=0;a<l.length;a++)t=l[a],n.indexOf(t)>=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(r[t]=e[t])}return r}var s=a.createContext({}),p=function(e){var n=a.useContext(s),t=n;return e&&(t="function"==typeof e?e(n):o(o({},n),e)),t},d=function(e){var n=p(e.components);return a.createElement(s.Provider,{value:n},e.children)},u={inlineCode:"code",wrapper:function(e){var n=e.children;return a.createElement(a.Fragment,{},n)}},c=a.forwardRef((function(e,n){var t=e.components,r=e.mdxType,l=e.originalType,s=e.parentName,d=i(e,["components","mdxType","originalType","parentName"]),c=p(t),m=r,g=c["".concat(s,".").concat(m)]||c[m]||u[m]||l;return t?a.createElement(g,o(o({ref:n},d),{},{components:t})):a.createElement(g,o({ref:n},d))}));function m(e,n){var t=arguments,r=n&&n.mdxType;if("string"==typeof e||r){var l=t.length,o=new Array(l);o[0]=c;var i={};for(var s in n)hasOwnProperty.call(n,s)&&(i[s]=n[s]);i.originalType=e,i.mdxType="string"==typeof e?e:r,o[1]=i;for(var p=2;p<l;p++)o[p]=t[p];return a.createElement.apply(null,o)}return a.createElement.apply(null,t)}c.displayName="MDXCreateElement"},6077:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>d,contentTitle:()=>s,default:()=>m,frontMatter:()=>i,metadata:()=>p,toc:()=>u});var a=t(7462),r=t(3366),l=(t(7294),t(3905)),o=["components"],i={id:"feature-flags",title:"Feature Flags",sidebar_label:"Feature Flags"},s=void 0,p={unversionedId:"feature-flags",id:"feature-flags",title:"Feature Flags",description:"The framework provides a collection of code-generation features that be added or removed using flags.",source:"@site/../md/features.md",sourceDirName:".",slug:"/feature-flags",permalink:"/docs/feature-flags",draft:!1,editUrl:"https://github.com/ent/ent/edit/master/doc/md/../md/features.md",tags:[],version:"current",lastUpdatedBy:"Jannik Clausen",lastUpdatedAt:1740483745,formattedLastUpdatedAt:"Feb 25, 2025",frontMatter:{id:"feature-flags",title:"Feature Flags",sidebar_label:"Feature Flags"},sidebar:"md",previous:{title:"FAQ",permalink:"/docs/faq"},next:{title:"Generating Schemas",permalink:"/docs/generating-ent-schemas"}},d={},u=[{value:"Usage",id:"usage",level:2},{value:"CLI",id:"cli",level:4},{value:"Go",id:"go",level:4},{value:"List of Features",id:"list-of-features",level:2},{value:"Auto-Solve Merge Conflicts",id:"auto-solve-merge-conflicts",level:3},{value:"Privacy Layer",id:"privacy-layer",level:3},{value:"EntQL Filtering",id:"entql-filtering",level:3},{value:"Named Edges",id:"named-edges",level:3},{value:"Bidirectional Edge Refs",id:"bidirectional-edge-refs",level:3},{value:"Schema Config",id:"schema-config",level:3},{value:"Row-level Locks",id:"row-level-locks",level:3},{value:"Custom SQL Modifiers",id:"custom-sql-modifiers",level:3},{value:"Modify Example 1",id:"modify-example-1",level:4},{value:"Select and Scan Dynamic Values",id:"select-and-scan-dynamic-values",level:4},{value:"Modify Example 2",id:"modify-example-2",level:4},{value:"Modify Example 3",id:"modify-example-3",level:4},{value:"Modify Example 4",id:"modify-example-4",level:4},{value:"Modify Example 5",id:"modify-example-5",level:4},{value:"Modify Example 6",id:"modify-example-6",level:4},{value:"Modify Example 7",id:"modify-example-7",level:4},{value:"SQL Raw API",id:"sql-raw-api",level:3},{value:"Upsert",id:"upsert",level:3},{value:"Globally Unique ID",id:"globally-unique-id",level:3}],c={toc:u};function m(e){var n=e.components,t=(0,r.Z)(e,o);return(0,l.kt)("wrapper",(0,a.Z)({},c,t,{components:n,mdxType:"MDXLayout"}),(0,l.kt)("p",null,"The framework provides a collection of code-generation features that be added or removed using flags."),(0,l.kt)("h2",{id:"usage"},"Usage"),(0,l.kt)("p",null,"Feature flags can be provided either by CLI flags or as arguments to the ",(0,l.kt)("inlineCode",{parentName:"p"},"gen")," package. "),(0,l.kt)("h4",{id:"cli"}
1,"CLI"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-console"},"go run -mod=mod entgo.io/ent/cmd/ent generate --feature privacy,entql ./ent/schema\n")),(0,l.kt)("h4",{id:"go"},"Go"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-go"},'// +build ignore\n\npackage main\n\nimport (\n    "log"\n    "text/template"\n\n    "entgo.io/ent/entc"\n    "entgo.io/ent/entc/gen"\n)\n\nfunc main() {\n    err := entc.Generate("./schema", &gen.Config{\n        Features: []gen.Feature{\n            gen.FeaturePrivacy,\n            gen.FeatureEntQL,\n        },\n        Templates: []*gen.Template{\n            gen.MustParse(gen.NewTemplate("static").\n                Funcs(template.FuncMap{"title": strings.ToTitle}).\n                ParseFiles("template/static.tmpl")),\n        },\n    })\n    if err != nil {\n        log.Fatalf("running ent codegen: %v", err)\n    }\n}\n')),(0,l.kt)("h2",{id:"list-of-features"},"List of Features"),(0,l.kt)("h3",{id:"auto-solve-merge-conflicts"},"Auto-Solve Merge Conflicts"),(0,l.kt)("p",null,"The ",(0,l.kt)("inlineCode",{parentName:"p"},"schema/snapshot")," option tells ",(0,l.kt)("inlineCode",{parentName:"p"},"entc")," (ent codegen) to store a snapshot of the latest schema in an internal package,\nand use it to automatically solve merge conflicts when user's schema can't be built."),(0,l.kt)("p",null,"This option can be added to a project using the ",(0,l.kt)("inlineCode",{parentName:"p"},"--feature schema/snapshot")," flag, but please see\n",(0,l.kt)("a",{parentName:"p",href:"https://github.com/ent/ent/issues/852"},"ent/ent/issues/852")," to get more context about it."),(0,l.kt)("h3",{id:"privacy-layer"},"Privacy Layer"),(0,l.kt)("p",null,"The privacy layer allows configuring privacy policy for queries and mutations of entities in the database."),(0,l.kt)("p",null,"This option can be added to a project using the ",(0,l.kt)("inlineCode",{parentName:"p"},"--feature privacy")," flag, and you can learn more about in the\n",(0,l.kt)("a",{parentName:"p",href:"/docs/privacy"},"privacy")," documentation."),(0,l.kt)("h3",{id:"entql-filtering"},"EntQL Filtering"),(0,l.kt)("p",null,"The ",(0,l.kt)("inlineCode",{parentName:"p"},"entql")," option provides a generic and dynamic filtering capability at runtime for the different query builders."),(0,l.kt)("p",null,"This option can be added to a project using the ",(0,l.kt)("inlineCode",{parentName:"p"},"--feature entql")," flag, and you can learn more about in the\n",(0,l.kt)("a",{parentName:"p",href:"/docs/privacy#multi-tenancy"},"privacy")," documentation."),(0,l.kt)("h3",{id:"named-edges"},"Named Edges"),(0,l.kt)("p",null,"The ",(0,l.kt)("inlineCode",{parentName:"p"},"namedges")," option provides an API for preloading edges with custom names."),(0,l.kt)("p",null,"This option can be added to a project using the ",(0,l.kt)("inlineCode",{parentName:"p"},"--feature namedges")," flag, and you can learn more about in the\n",(0,l.kt)("a",{parentName:"p",href:"/docs/eager-load"},"Eager Loading")," documentation."),(0,l.kt)("h3",{id:"bidirectional-edge-refs"},"Bidirectional Edge Refs"),(0,l.kt)("p",null,"The ",(0,l.kt)("inlineCode",{parentName:"p"},"bidiedges")," option guides Ent to set two-way references when eager-loading (O2M/O2O) edges."),(0,l.kt)("p",null,"This option can be added to a project using the ",(0,l.kt)("inlineCode",{parentName:"p"},"--feature bidiedges")," flag."),(0,l.kt)("admonition",{type:"note"},(0,l.kt)("p",{parentName:"admonition"},"Users that use the standard encoding/json.MarshalJSON should detach the circular references before calling ",(0,l.kt)("inlineCode",{parentName:"p"},"json.Marshal"),".")),(0,l.kt)("h3",{id:"schema-config"},"Schema Config"),(0,l.kt)("p",null,"The ",(0,l.kt)("inlineCode",{parentName:"p"},"sql/schemaconfig")," option lets you pass alternate SQL database names to models. This is useful when your models don't all live under one database and are spread out across different schemas."),(0,l.kt)("p",null,"This option can be added to a project using the ",(0,l.kt)("inlineCode",{parentName:"p"},"--feature sql/schemaconfig")," flag. Once you generate the code, you can now use a new option as such: "),(0,l.kt)("pre",null,(0,l.kt)("c
1ode",{parentName:"pre",className:"language-go"},'c, err := ent.Open(dialect, conn, ent.AlternateSchema(ent.SchemaConfig{\n    User: "usersdb",\n    Car: "carsdb",\n}))\nc.User.Query().All(ctx) // SELECT * FROM `usersdb`.`users`\nc.Car.Query().All(ctx)  // SELECT * FROM `carsdb`.`cars`\n')),(0,l.kt)("h3",{id:"row-level-locks"},"Row-level Locks"),(0,l.kt)("p",null,"The ",(0,l.kt)("inlineCode",{parentName:"p"},"sql/lock")," option lets configure row-level locking using the SQL ",(0,l.kt)("inlineCode",{parentName:"p"},"SELECT ... FOR {UPDATE | SHARE}")," syntax."),(0,l.kt)("p",null,"This option can be added to a project using the ",(0,l.kt)("inlineCode",{parentName:"p"},"--feature sql/lock")," flag."),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-go"},"tx, err := client.Tx(ctx)\nif err != nil {\n    log.Fatal(err)\n}\n\ntx.Pet.Query().\n    Where(pet.Name(name)).\n    ForUpdate().\n    Only(ctx)\n\ntx.Pet.Query().\n    Where(pet.ID(id)).\n    ForShare(\n        sql.WithLockTables(pet.Table),\n        sql.WithLockAction(sql.NoWait),\n    ).\n    Only(ctx)\n")),(0,l.kt)("h3",{id:"custom-sql-modifiers"},"Custom SQL Modifiers"),(0,l.kt)("p",null,"The ",(0,l.kt)("inlineCode",{parentName:"p"},"sql/modifier")," option lets add custom SQL modifiers to the builders and mutate the statements before they are executed."),(0,l.kt)("p",null,"This option can be added to a project using the ",(0,l.kt)("inlineCode",{parentName:"p"},"--feature sql/modifier")," flag."),(0,l.kt)("h4",{id:"modify-example-1"},"Modify Example 1"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-go"},'client.Pet.\n    Query().\n    Modify(func(s *sql.Selector) {\n        s.Select("SUM(LENGTH(name))")\n    }).\n    IntX(ctx)\n')),(0,l.kt)("p",null,"The above code will produce the following SQL query:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-sql"},"SELECT SUM(LENGTH(name)) FROM `pet`\n")),(0,l.kt)("h4",{id:"select-and-scan-dynamic-values"},"Select and Scan Dynamic Values"),(0,l.kt)("p",null,"If you work with SQL modifiers and need to scan dynamic values not present in your Ent schema definition, such as\naggregation or custom ordering, you can apply ",(0,l.kt)("inlineCode",{parentName:"p"},"AppendSelect"),"/",(0,l.kt)("inlineCode",{parentName:"p"},"AppendSelectAs")," to the ",(0,l.kt)("inlineCode",{parentName:"p"},"sql.Selector"),". You can later\naccess their values using the ",(0,l.kt)("inlineCode",{parentName:"p"},"Value")," method defined on each entity:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-go",metastring:"{6,11}","{6,11}":!0},'const as = "name_length"\n\n// Query the entity with the dynamic value.\np := client.Pet.Query().\n    Modify(func(s *sql.Selector) {\n        s.AppendSelectAs("LENGTH(name)", as)\n    }).\n    FirstX(ctx)\n\n// Read the value from the entity.\nn, err := p.Value(as)\nif err != nil {\n    log.Fatal(err)\n}\nfmt.Println("Name length: %d == %d", n, len(p.Name))\n')),(0,l.kt)("h4",{id:"modify-example-2"},"Modify Example 2"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-go"},'var p1 []struct {\n    ent.Pet\n    NameLength int `sql:"length"`\n}\n\nclient.Pet.Query().\n    Order(ent.Asc(pet.FieldID)).\n    Modify(func(s *sql.Selector) {\n        s.AppendSelect("LENGTH(name)")\n    }).\n    ScanX(ctx, &p1)\n')),(0,l.kt)("p",null,"The above code will produce the following SQL query:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-sql"},"SELECT `pet`.*, LENGTH(name) FROM `pet` ORDER BY `pet`.`id` ASC\n")),(0,l.kt)("h4",{id:"modify-example-3"},"Modify Example 3"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-go"},'var v []struct {\n    Count     int       `json:"count"`\n    Price     int       `json:"price"`\n    CreatedAt time.Time `json:"created_at"`\n}\n\nclient.User.\n    Query().\n    Where(\n        user.CreatedAtGT(x),\n        user.CreatedAtLT(y),\n    ).\n    Modify(func(s *sql.Selector) {\n        s.Select(\n            sql.As(sql.Count("*"), "count"),\n            sql.As(sql.Sum("price"), "price"),\n            sql.As("DATE(created_at)", "created_at"),\n        ).\n        GroupBy("DATE(created_at)").\n        OrderBy(sql.Desc("DATE(created_at)"))\n    }).\n    ScanX(ctx, &v)\n')),(0,l.kt)("p",null,"The above code will produce the following SQL query:"),(0,l.kt)("pre",null,(0,l.kt)("c
1ode",{parentName:"pre",className:"language-sql"},"SELECT\n    COUNT(*) AS `count`,\n    SUM(`price`) AS `price`,\n    DATE(created_at) AS `created_at`\nFROM\n    `users`\nWHERE\n    `created_at` > x AND `created_at` < y\nGROUP BY\n    DATE(created_at)\nORDER BY\n    DATE(created_at) DESC\n")),(0,l.kt)("h4",{id:"modify-example-4"},"Modify Example 4"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-go"},'var gs []struct {\n    ent.Group\n    UsersCount int `sql:"users_count"`\n}\n\nclient.Group.Query().\n    Order(ent.Asc(group.FieldID)).\n    Modify(func(s *sql.Selector) {\n        t := sql.Table(group.UsersTable)\n        s.LeftJoin(t).\n            On(\n                s.C(group.FieldID),\n                t.C(group.UsersPrimaryKey[1]),\n            ).\n            // Append the "users_count" column to the selected columns.\n            AppendSelect(\n                sql.As(sql.Count(t.C(group.UsersPrimaryKey[1])), "users_count"),\n            ).\n            GroupBy(s.C(group.FieldID))\n    }).\n    ScanX(ctx, &gs)\n')),(0,l.kt)("p",null,"The above code will produce the following SQL query:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-sql"},"SELECT\n    `groups`.*,\n    COUNT(`t1`.`group_id`) AS `users_count`\nFROM\n    `groups` LEFT JOIN `user_groups` AS `t1`\nON\n    `groups`.`id` = `t1`.`group_id`\nGROUP BY\n    `groups`.`id`\nORDER BY\n    `groups`.`id` ASC\n")),(0,l.kt)("h4",{id:"modify-example-5"},"Modify Example 5"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-go"},'client.User.Update().\n    Modify(func(s *sql.UpdateBuilder) {\n        s.Set(user.FieldName, sql.Expr(fmt.Sprintf("UPPER(%s)", user.FieldName)))\n    }).\n    ExecX(ctx)\n')),(0,l.kt)("p",null,"The above code will produce the following SQL query:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-sql"},"UPDATE `users` SET `name` = UPPER(`name`)\n")),(0,l.kt)("h4",{id:"modify-example-6"},"Modify Example 6"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-go"},"client.User.Update().\n    Modify(func(u *sql.UpdateBuilder) {\n        u.Set(user.FieldID, sql.ExprFunc(func(b *sql.Builder) {\n            b.Ident(user.FieldID).WriteOp(sql.OpAdd).Arg(1)\n        }))\n        u.OrderBy(sql.Desc(user.FieldID))\n    }).\n    ExecX(ctx)\n")),(0,l.kt)("p",null,"The above code will produce the following SQL query:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-sql"},"UPDATE `users` SET `id` = `id` + 1 ORDER BY `id` DESC\n")),(0,l.kt)("h4",{id:"modify-example-7"},"Modify Example 7"),(0,l.kt)("p",null,"Append elements to the ",(0,l.kt)("inlineCode",{parentName:"p"},"values")," array in a JSON column:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-go"},'client.User.Update().\n    Modify(func(u *sql.UpdateBuilder) {\n        sqljson.Append(u, user.FieldTags, []string{"tag1", "tag2"}, sqljson.Path("values"))\n    }).\n    ExecX(ctx)\n')),(0,l.kt)("p",null,"The above code will produce the following SQL query:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-sql"},"UPDATE `users` SET `tags` = CASE\n    WHEN (JSON_TYPE(JSON_EXTRACT(`tags`, '$.values')) IS NULL OR JSON_TYPE(JSON_EXTRACT(`tags`, '$.values')) = 'NULL')\n    THEN JSON_SET(`tags`, '$.values', JSON_ARRAY(?, ?))\n    ELSE JSON_ARRAY_APPEND(`tags`, '$.values', ?, '$.values', ?) END\n    WHERE `id` = ?\n")),(0,l.kt)("h3",{id:"sql-raw-api"},"SQL Raw API"),(0,l.kt)("p",null,"The ",(0,l.kt)("inlineCode",{parentName:"p"},"sql/execquery")," option allows executing statements using the ",(0,l.kt)("inlineCode",{parentName:"p"},"ExecContext"),"/",(0,l.kt)("inlineCode",{parentName:"p"},"QueryContext")," methods of the underlying\ndriver. For full documentation, see: ",(0,l.kt)("a",{parentName:"p",href:"https://pkg.go.dev/database/sql#DB.ExecContext"},"DB.ExecContext"),", and\n",(0,l.kt)("a",{parentName:"p",href:"https://pkg.go.dev/database/sql#DB.QueryContext"}
1,"DB.QueryContext"),"."),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-go"},'// From ent.Client.\nif _, err := client.ExecContext(ctx, "TRUNCATE t1"); err != nil {\n    return err\n}\n\n// From ent.Tx.\ntx, err := client.Tx(ctx)\nif err != nil {\n    return err\n}\nif err := tx.User.Create().Exec(ctx); err != nil {\n    return err\n}\nif _, err := tx.ExecContext("SAVEPOINT user_created"); err != nil {\n    return err\n}\n// ...\n')),(0,l.kt)("admonition",{title:"Note",type:"warning"},(0,l.kt)("p",{parentName:"admonition"},"Statements executed using ",(0,l.kt)("inlineCode",{parentName:"p"},"ExecContext"),"/",(0,l.kt)("inlineCode",{parentName:"p"},"QueryContext")," do not go through Ent, and may skip fundamental layers in your\napplication such as hooks, privacy (authorization), and validators.")),(0,l.kt)("h3",{id:"upsert"},"Upsert"),(0,l.kt)("p",null,"The ",(0,l.kt)("inlineCode",{parentName:"p"},"sql/upsert")," option lets configure upsert and bulk-upsert logic using the SQL ",(0,l.kt)("inlineCode",{parentName:"p"},"ON CONFLICT")," / ",(0,l.kt)("inlineCode",{parentName:"p"},"ON DUPLICATE KEY"),"\nsyntax. For full documentation, go to the ",(0,l.kt)("a",{parentName:"p",href:"/docs/crud#upsert-one"},"Upsert API"),"."),(0,l.kt)("p",null,"This option can be added to a project using the ",(0,l.kt)("inlineCode",{parentName:"p"},"--feature sql/upsert")," flag."),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-go"},'// Use the new values that were set on create.\nid, err := client.User.\n    Create().\n    SetAge(30).\n    SetName("Ariel").\n    OnConflict().\n    UpdateNewValues().\n    ID(ctx)\n\n// In PostgreSQL, the conflict target is required.\nerr := client.User.\n    Create().\n    SetAge(30).\n    SetName("Ariel").\n    OnConflictColumns(user.FieldName).\n    UpdateNewValues().\n    Exec(ctx)\n\n// Bulk upsert is also supported.\nclient.User.\n    CreateBulk(builders...).\n    OnConflict(\n        sql.ConflictWhere(...),\n        sql.UpdateWhere(...),\n    ).\n    UpdateNewValues().\n    Exec(ctx)\n\n// INSERT INTO "users" (...) VALUES ... ON CONFLICT WHERE ... DO UPDATE SET ... WHERE ...\n')),(0,l.kt)("h3",{id:"globally-unique-id"},"Globally Unique ID"),(0,l.kt)("p",null,"By default, SQL primary-keys start from 1 for each table; which means that multiple entities of different types\ncan share the same ID. Unlike AWS Neptune, where node IDs are UUIDs."),(0,l.kt)("p",null,"This does not work well if you work with ",(0,l.kt)("a",{parentName:"p",href:"https://graphql.org/learn/schema/#scalar-types"},"GraphQL"),", which requires\nthe object ID to be unique."),(0,l.kt)("p",null,"To enable the Universal-IDs support for your project, simply use the ",(0,l.kt)("inlineCode",{parentName:"p"},"--feature sql/globalid")," flag."),(0,l.kt)("admonition",{title:"Note",type:"warning"},(0,l.kt)("p",{parentName:"admonition"},"If you have used the ",(0,l.kt)("inlineCode",{parentName:"p"},"migrate.WithGlobalUniqueID(true)")," migration option in the past, please read\n",(0,l.kt)("a",{parentName:"p",href:"globalid-migrate"},"this guide")," before you switch your project to use the new globalid feature.")),(0,l.kt)("p",null,(0,l.kt)("strong",{parentName:"p"},"How does it work?")," ",(0,l.kt)("inlineCode",{parentName:"p"},"ent")," migration allocates a 1<<32 range for the IDs of each entity (table),\nand store this information alongside your generated code (",(0,l.kt)("inlineCode",{parentName:"p"},"internal/globalid.go"),"). For example, type ",(0,l.kt)("inlineCode",{parentName:"p"},"A")," will have the\nrange of ",(0,l.kt)("inlineCode",{parentName:"p"},"[1,4294967296)")," for its IDs, and type ",(0,l.kt)("inlineCode",{parentName:"p"},"B")," will have the range of ",(0,l.kt)("inlineCode",{parentName:"p"},"[4294967296,8589934592)"),", etc."),(0,l.kt)("p",null,"Note that if this option is enabled, the maximum number of possible tables is ",(0,l.kt)("strong",{parentName:"p"},"65535"),"."))}m.isMDXComponent=!0}}]);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.