[{"data":1,"prerenderedAt":929},["ShallowReactive",2],{"navigation":3,"\u002Fguides\u002Foptimistic-locking":123,"\u002Fguides\u002Foptimistic-locking-surround":924},[4,9,31,107,118],{"title":5,"path":6,"stem":7,"icon":8},"Getting started","\u002Fgetting-started","01.getting-started","i-tabler-rocket",{"title":10,"icon":11,"path":12,"stem":13,"children":14,"page":30},"Concepts","i-tabler-code","\u002Fconcepts","02.concepts",[15,20,25],{"title":16,"path":17,"stem":18,"icon":19},"Architecture","\u002Fconcepts\u002Farchitecture","02.concepts\u002Farchitecture","i-tabler-sitemap",{"title":21,"path":22,"stem":23,"icon":24},"Metadata and registry","\u002Fconcepts\u002Fmetadata-and-registry","02.concepts\u002Fmetadata-and-registry","i-tabler-schema",{"title":26,"path":27,"stem":28,"icon":29},"Query Engine","\u002Fconcepts\u002Fquery-engine","02.concepts\u002Fquery-engine","i-tabler-engine",false,{"title":32,"icon":33,"path":34,"stem":35,"children":36,"page":30},"Guide","i-tabler-arrow-ramp-right","\u002Fguides","03.guides",[37,42,47,52,57,62,67,72,77,82,87,92,97,102],{"title":38,"path":39,"stem":40,"icon":41},"Aggregate queries","\u002Fguides\u002Faggregate-queries","03.guides\u002Faggregate-queries","i-tabler-chart-histogram",{"title":43,"path":44,"stem":45,"icon":46},"Audit Log","\u002Fguides\u002Faudit-log","03.guides\u002Faudit-log","i-tabler-history",{"title":48,"path":49,"stem":50,"icon":51},"Cursor pagination","\u002Fguides\u002Fcursor-pagination","03.guides\u002Fcursor-pagination","i-tabler-arrow-bar-to-down",{"title":53,"path":54,"stem":55,"icon":56},"Domain Events","\u002Fguides\u002Fdomain-events","03.guides\u002Fdomain-events","i-tabler-broadcast",{"title":58,"path":59,"stem":60,"icon":61},"Field transforms","\u002Fguides\u002Ffield-transforms","03.guides\u002Ffield-transforms","i-tabler-transform",{"title":63,"path":64,"stem":65,"icon":66},"Field visibility","\u002Fguides\u002Ffield-visibility","03.guides\u002Ffield-visibility","i-tabler-eye-off",{"title":68,"path":69,"stem":70,"icon":71},"Lifecycle hooks","\u002Fguides\u002Flifecycle-hooks","03.guides\u002Flifecycle-hooks","i-tabler-arrows-split",{"title":73,"path":74,"stem":75,"icon":76},"Migrations","\u002Fguides\u002Fmigrations","03.guides\u002Fmigrations","i-tabler-database-export",{"title":78,"path":79,"stem":80,"icon":81},"Optimistic locking","\u002Fguides\u002Foptimistic-locking","03.guides\u002Foptimistic-locking","i-tabler-lock-check",{"title":83,"path":84,"stem":85,"icon":86},"Production playground","\u002Fguides\u002Fplayground","03.guides\u002Fplayground","i-tabler-flask",{"title":88,"path":89,"stem":90,"icon":91},"Queries and filters","\u002Fguides\u002Fqueries-and-filters","03.guides\u002Fqueries-and-filters","i-tabler-filter",{"title":93,"path":94,"stem":95,"icon":96},"Relations","\u002Fguides\u002Frelations","03.guides\u002Frelations","i-tabler-link",{"title":98,"path":99,"stem":100,"icon":101},"Schema consistency","\u002Fguides\u002Fschema-consistency","03.guides\u002Fschema-consistency","i-tabler-database-search",{"title":103,"path":104,"stem":105,"icon":106},"Validation","\u002Fguides\u002Fvalidation","03.guides\u002Fvalidation","i-tabler-checkup-list",{"title":108,"icon":109,"path":110,"stem":111,"children":112,"page":30},"Adapters","i-tabler-plug","\u002Fadapters","04.adapters",[113],{"title":114,"path":115,"stem":116,"icon":117},"PostgreSQL adapter","\u002Fadapters\u002Fpostgresql","04.adapters\u002Fpostgresql","i-simple-icons-postgresql",{"title":119,"path":120,"stem":121,"icon":122},"Current limitations","\u002Fcurrent-limitations","05.current-limitations","i-tabler-circle-dashed-x",{"id":124,"title":78,"body":125,"description":917,"extension":918,"links":919,"meta":920,"navigation":921,"path":79,"seo":922,"stem":80,"__hash__":923},"docs\u002F03.guides\u002Foptimistic-locking.md",{"type":126,"value":127,"toc":913},"minimark",[128,132,137,145,448,451,454,458,461,574,577,711,722,744,754,884,899,909],[129,130,131],"p",{},"Optimistic locking protects an entity with an integer version. Every update\ncompares the version read by the caller with the version currently stored in\nthe database. A successful update increments it atomically; a stale update\nfails instead of overwriting newer data.",[133,134,136],"h2",{"id":135},"configure-a-version-field","Configure a version field",[129,138,139,140,144],{},"Add a non-null integer column and reference its logical name from\n",[141,142,143],"code",{},"optimisticLock",":",[146,147,152],"pre",{"className":148,"code":149,"language":150,"meta":151,"style":151},"language-ts shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","const documentsMetadata = defineTable({\n  name: 'documents',\n  collectionName: 'documents',\n  columns: [\n    \u002F\u002F Other columns...\n    {\n      name: 'version',\n      columnName: 'version',\n      type: 'integer',\n      nullable: false,\n      primaryKey: false,\n      unique: false,\n      default: 1,\n      validators: []\n    }\n  ],\n  relations: [],\n  tableValidators: [],\n  optimisticLock: {\n    field: 'version',\n    initialVersion: 1\n  }\n})\n","ts","",[141,153,154,181,203,219,230,237,243,260,276,293,307,319,331,345,356,362,370,383,395,406,422,433,439],{"__ignoreMap":151},[155,156,159,163,167,171,175,178],"span",{"class":157,"line":158},"line",1,[155,160,162],{"class":161},"spNyl","const",[155,164,166],{"class":165},"sTEyZ"," documentsMetadata ",[155,168,170],{"class":169},"sMK4o","=",[155,172,174],{"class":173},"s2Zo4"," defineTable",[155,176,177],{"class":165},"(",[155,179,180],{"class":169},"{\n",[155,182,184,188,190,193,197,200],{"class":157,"line":183},2,[155,185,187],{"class":186},"swJcz","  name",[155,189,144],{"class":169},[155,191,192],{"class":169}," '",[155,194,196],{"class":195},"sfazB","documents",[155,198,199],{"class":169},"'",[155,201,202],{"class":169},",\n",[155,204,206,209,211,213,215,217],{"class":157,"line":205},3,[155,207,208],{"class":186},"  collectionName",[155,210,144],{"class":169},[155,212,192],{"class":169},[155,214,196],{"class":195},[155,216,199],{"class":169},[155,218,202],{"class":169},[155,220,222,225,227],{"class":157,"line":221},4,[155,223,224],{"class":186},"  columns",[155,226,144],{"class":169},[155,228,229],{"class":165}," [\n",[155,231,233],{"class":157,"line":232},5,[155,234,236],{"class":235},"sHwdD","    \u002F\u002F Other columns...\n",[155,238,240],{"class":157,"line":239},6,[155,241,242],{"class":169},"    {\n",[155,244,246,249,251,253,256,258],{"class":157,"line":245},7,[155,247,248],{"class":186},"      name",[155,250,144],{"class":169},[155,252,192],{"class":169},[155,254,255],{"class":195},"version",[155,257,199],{"class":169},[155,259,202],{"class":169},[155,261,263,266,268,270,272,274],{"class":157,"line":262},8,[155,264,265],{"class":186},"      columnName",[155,267,144],{"class":169},[155,269,192],{"class":169},[155,271,255],{"class":195},[155,273,199],{"class":169},[155,275,202],{"class":169},[155,277,279,282,284,286,289,291],{"class":157,"line":278},9,[155,280,281],{"class":186},"      type",[155,283,144],{"class":169},[155,285,192],{"class":169},[155,287,288],{"class":195},"integer",[155,290,199],{"class":169},[155,292,202],{"class":169},[155,294,296,299,301,305],{"class":157,"line":295},10,[155,297,298],{"class":186},"      nullable",[155,300,144],{"class":169},[155,302,304],{"class":303},"sfNiH"," false",[155,306,202],{"class":169},[155,308,310,313,315,317],{"class":157,"line":309},11,[155,311,312],{"class":186},"      primaryKey",[155,314,144],{"class":169},[155,316,304],{"class":303},[155,318,202],{"class":169},[155,320,322,325,327,329],{"class":157,"line":321},12,[155,323,324],{"class":186},"      unique",[155,326,144],{"class":169},[155,328,304],{"class":303},[155,330,202],{"class":169},[155,332,334,337,339,343],{"class":157,"line":333},13,[155,335,336],{"class":186},"      default",[155,338,144],{"class":169},[155,340,342],{"class":341},"sbssI"," 1",[155,344,202],{"class":169},[155,346,348,351,353],{"class":157,"line":347},14,[155,349,350],{"class":186},"      validators",[155,352,144],{"class":169},[155,354,355],{"class":165}," []\n",[155,357,359],{"class":157,"line":358},15,[155,360,361],{"class":169},"    }\n",[155,363,365,368],{"class":157,"line":364},16,[155,366,367],{"class":165},"  ]",[155,369,202],{"class":169},[155,371,373,376,378,381],{"class":157,"line":372},17,[155,374,375],{"class":186},"  relations",[155,377,144],{"class":169},[155,379,380],{"class":165}," []",[155,382,202],{"class":169},[155,384,386,389,391,393],{"class":157,"line":385},18,[155,387,388],{"class":186},"  tableValidators",[155,390,144],{"class":169},[155,392,380],{"class":165},[155,394,202],{"class":169},[155,396,398,401,403],{"class":157,"line":397},19,[155,399,400],{"class":186},"  optimisticLock",[155,402,144],{"class":169},[155,404,405],{"class":169}," {\n",[155,407,409,412,414,416,418,420],{"class":157,"line":408},20,[155,410,411],{"class":186},"    field",[155,413,144],{"class":169},[155,415,192],{"class":169},[155,417,255],{"class":195},[155,419,199],{"class":169},[155,421,202],{"class":169},[155,423,425,428,430],{"class":157,"line":424},21,[155,426,427],{"class":186},"    initialVersion",[155,429,144],{"class":169},[155,431,432],{"class":341}," 1\n",[155,434,436],{"class":157,"line":435},22,[155,437,438],{"class":169},"  }\n",[155,440,442,445],{"class":157,"line":441},23,[155,443,444],{"class":169},"}",[155,446,447],{"class":165},")\n",[129,449,450],{},"The registry rejects an unknown, nullable or non-integer version field. The\nversion field cannot declare a write transform.",[129,452,453],{},"For an existing table, generate a migration that adds the version column with\na static default so existing rows receive an initial value.",[133,455,457],{"id":456},"update-with-the-version-you-read","Update with the version you read",[129,459,460],{},"Return the version to the client with the entity:",[146,462,464],{"className":148,"code":463,"language":150,"meta":151,"style":151},"const document = await engine.findOne('documents', {\n  where: {\n    conditions: [{ field: 'id', operator: 'eq', value: documentId }]\n  }\n})\n",[141,465,466,501,510,564,568],{"__ignoreMap":151},[155,467,468,470,473,475,479,482,485,488,490,492,494,496,499],{"class":157,"line":158},[155,469,162],{"class":161},[155,471,472],{"class":165}," document ",[155,474,170],{"class":169},[155,476,478],{"class":477},"s7zQu"," await",[155,480,481],{"class":165}," engine",[155,483,484],{"class":169},".",[155,486,487],{"class":173},"findOne",[155,489,177],{"class":165},[155,491,199],{"class":169},[155,493,196],{"class":195},[155,495,199],{"class":169},[155,497,498],{"class":169},",",[155,500,405],{"class":169},[155,502,503,506,508],{"class":157,"line":183},[155,504,505],{"class":186},"  where",[155,507,144],{"class":169},[155,509,405],{"class":169},[155,511,512,515,517,520,523,526,528,530,533,535,537,540,542,544,547,549,551,554,556,559,561],{"class":157,"line":205},[155,513,514],{"class":186},"    conditions",[155,516,144],{"class":169},[155,518,519],{"class":165}," [",[155,521,522],{"class":169},"{",[155,524,525],{"class":186}," field",[155,527,144],{"class":169},[155,529,192],{"class":169},[155,531,532],{"class":195},"id",[155,534,199],{"class":169},[155,536,498],{"class":169},[155,538,539],{"class":186}," operator",[155,541,144],{"class":169},[155,543,192],{"class":169},[155,545,546],{"class":195},"eq",[155,548,199],{"class":169},[155,550,498],{"class":169},[155,552,553],{"class":186}," value",[155,555,144],{"class":169},[155,557,558],{"class":165}," documentId ",[155,560,444],{"class":169},[155,562,563],{"class":165},"]\n",[155,565,566],{"class":157,"line":221},[155,567,438],{"class":169},[155,569,570,572],{"class":157,"line":232},[155,571,444],{"class":169},[155,573,447],{"class":165},[129,575,576],{},"Send that version back in the update patch:",[146,578,580],{"className":148,"code":579,"language":150,"meta":151,"style":151},"const updated = await engine.updateOne(\n  'documents',\n  {\n    conditions: [{ field: 'id', operator: 'eq', value: documentId }]\n  },\n  {\n    title: 'Updated title',\n    version: document.version\n  }\n)\n",[141,581,582,603,614,619,663,668,672,688,703,707],{"__ignoreMap":151},[155,583,584,586,589,591,593,595,597,600],{"class":157,"line":158},[155,585,162],{"class":161},[155,587,588],{"class":165}," updated ",[155,590,170],{"class":169},[155,592,478],{"class":477},[155,594,481],{"class":165},[155,596,484],{"class":169},[155,598,599],{"class":173},"updateOne",[155,601,602],{"class":165},"(\n",[155,604,605,608,610,612],{"class":157,"line":183},[155,606,607],{"class":169},"  '",[155,609,196],{"class":195},[155,611,199],{"class":169},[155,613,202],{"class":169},[155,615,616],{"class":157,"line":205},[155,617,618],{"class":169},"  {\n",[155,620,621,623,625,627,629,631,633,635,637,639,641,643,645,647,649,651,653,655,657,659,661],{"class":157,"line":221},[155,622,514],{"class":186},[155,624,144],{"class":169},[155,626,519],{"class":165},[155,628,522],{"class":169},[155,630,525],{"class":186},[155,632,144],{"class":169},[155,634,192],{"class":169},[155,636,532],{"class":195},[155,638,199],{"class":169},[155,640,498],{"class":169},[155,642,539],{"class":186},[155,644,144],{"class":169},[155,646,192],{"class":169},[155,648,546],{"class":195},[155,650,199],{"class":169},[155,652,498],{"class":169},[155,654,553],{"class":186},[155,656,144],{"class":169},[155,658,558],{"class":165},[155,660,444],{"class":169},[155,662,563],{"class":165},[155,664,665],{"class":157,"line":232},[155,666,667],{"class":169},"  },\n",[155,669,670],{"class":157,"line":239},[155,671,618],{"class":169},[155,673,674,677,679,681,684,686],{"class":157,"line":245},[155,675,676],{"class":186},"    title",[155,678,144],{"class":169},[155,680,192],{"class":169},[155,682,683],{"class":195},"Updated title",[155,685,199],{"class":169},[155,687,202],{"class":169},[155,689,690,693,695,698,700],{"class":157,"line":262},[155,691,692],{"class":186},"    version",[155,694,144],{"class":169},[155,696,697],{"class":165}," document",[155,699,484],{"class":169},[155,701,702],{"class":165},"version\n",[155,704,705],{"class":157,"line":278},[155,706,438],{"class":169},[155,708,709],{"class":157,"line":295},[155,710,447],{"class":165},[129,712,713,714,717,718,721],{},"If ",[141,715,716],{},"document.version"," is ",[141,719,720],{},"3",", the adapter performs the equivalent of:",[146,723,727],{"className":724,"code":725,"language":726,"meta":151,"style":151},"language-sql shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","UPDATE documents\nSET title = 'Updated title', version = 4\nWHERE id = $1 AND version = 3;\n","sql",[141,728,729,734,739],{"__ignoreMap":151},[155,730,731],{"class":157,"line":158},[155,732,733],{},"UPDATE documents\n",[155,735,736],{"class":157,"line":183},[155,737,738],{},"SET title = 'Updated title', version = 4\n",[155,740,741],{"class":157,"line":205},[155,742,743],{},"WHERE id = $1 AND version = 3;\n",[129,745,746,747,750,751,484],{},"If another request already changed the row, no row matches ",[141,748,749],{},"version = 3"," and\nPersistence throws ",[141,752,753],{},"OptimisticLockError",[146,755,757],{"className":148,"code":756,"language":150,"meta":151,"style":151},"import { OptimisticLockError } from '@opensya\u002Fpersistence'\n\ntry {\n  await engine.updateOne('documents', byId(documentId), patch)\n} catch (error) {\n  if (error instanceof OptimisticLockError) {\n    \u002F\u002F Reload the current entity and ask the user to reconcile the changes.\n  }\n}\n",[141,758,759,784,790,797,836,848,870,875,879],{"__ignoreMap":151},[155,760,761,764,767,770,773,776,778,781],{"class":157,"line":158},[155,762,763],{"class":477},"import",[155,765,766],{"class":169}," {",[155,768,769],{"class":165}," OptimisticLockError",[155,771,772],{"class":169}," }",[155,774,775],{"class":477}," from",[155,777,192],{"class":169},[155,779,780],{"class":195},"@opensya\u002Fpersistence",[155,782,783],{"class":169},"'\n",[155,785,786],{"class":157,"line":183},[155,787,789],{"emptyLinePlaceholder":788},true,"\n",[155,791,792,795],{"class":157,"line":205},[155,793,794],{"class":477},"try",[155,796,405],{"class":169},[155,798,799,802,804,806,808,810,812,814,816,818,821,823,826,829,831,834],{"class":157,"line":221},[155,800,801],{"class":477},"  await",[155,803,481],{"class":165},[155,805,484],{"class":169},[155,807,599],{"class":173},[155,809,177],{"class":186},[155,811,199],{"class":169},[155,813,196],{"class":195},[155,815,199],{"class":169},[155,817,498],{"class":169},[155,819,820],{"class":173}," byId",[155,822,177],{"class":186},[155,824,825],{"class":165},"documentId",[155,827,828],{"class":186},")",[155,830,498],{"class":169},[155,832,833],{"class":165}," patch",[155,835,447],{"class":186},[155,837,838,840,843,846],{"class":157,"line":232},[155,839,444],{"class":169},[155,841,842],{"class":477}," catch",[155,844,845],{"class":165}," (error) ",[155,847,180],{"class":169},[155,849,850,853,856,859,862,865,868],{"class":157,"line":239},[155,851,852],{"class":477},"  if",[155,854,855],{"class":186}," (",[155,857,858],{"class":165},"error",[155,860,861],{"class":169}," instanceof",[155,863,769],{"class":864},"sBMFI",[155,866,867],{"class":186},") ",[155,869,180],{"class":169},[155,871,872],{"class":157,"line":245},[155,873,874],{"class":235},"    \u002F\u002F Reload the current entity and ask the user to reconcile the changes.\n",[155,876,877],{"class":157,"line":262},[155,878,438],{"class":169},[155,880,881],{"class":157,"line":278},[155,882,883],{"class":169},"}\n",[129,885,886,887,890,891,894,895,898],{},"Omitting the version from an update throws\n",[141,888,889],{},"OptimisticLockVersionRequiredError",". Creation always assigns\n",[141,892,893],{},"initialVersion"," (or ",[141,896,897],{},"1"," by default), so callers cannot choose the first\nversion.",[129,900,901,904,905,908],{},[141,902,903],{},"updateMany()"," is also protected, but every selected row must currently have\nthe version supplied in the shared patch. For independent entity versions,\nprefer separate ",[141,906,907],{},"updateOne()"," calls inside an application transaction.",[910,911,912],"style",{},"html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .sfNiH, html code.shiki .sfNiH{--shiki-light:#FF5370;--shiki-default:#FF9CAC;--shiki-dark:#FF9CAC}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}",{"title":151,"searchDepth":158,"depth":183,"links":914},[915,916],{"id":135,"depth":183,"text":136},{"id":456,"depth":183,"text":457},"Prevent concurrent users from silently overwriting each other's changes.","md",null,{},{"icon":81},{"title":78,"description":917},"qFINK70fQE8DVqHnGMe_lWhiJKyAbe1bt-hMF7Mp30Y",[925,927],{"title":73,"path":74,"stem":75,"description":926,"icon":76,"children":-1},"Generate, review and execute versioned database migrations from Persistence metadata.",{"title":83,"path":84,"stem":85,"description":928,"icon":86,"children":-1},"Exercise the built package against an isolated PostgreSQL database.",1783964087004]