<!-- CANARY: REQ=REQ-DOCS-001; FEATURE="Docs"; ASPECT=Documentation; STATUS=TESTED; OWNER=docs; UPDATED=2026-01-15 -->
<h2 id="schema-constraints" class="position-relative d-flex align-items-center group">
<span>Schema Constraints</span>
<button type="button"
class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1"
data-share-target="schema-constraints"
aria-haspopup="dialog"
aria-label="Share link: Schema Constraints">
<i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i>
<span class="visually-hidden">Share link</span>
</button>
</h2><div id="headingShareModal" class="heading-share-modal" role="dialog" aria-modal="true" aria-labelledby="headingShareTitle" hidden>
<div class="hsm-dialog" role="document">
<div class="hsm-header">
<h2 id="headingShareTitle" class="h6 mb-0 fw-bold">Share this section</h2>
<button type="button" class="hsm-close" aria-label="Close">
<i class="fa-solid fa-xmark"></i>
</button>
</div>
<div class="hsm-body">
<label for="headingShareInput" class="form-label small text-muted mb-1 text-uppercase fw-bold" style="font-size: 0.7rem; letter-spacing: 0.5px;">Permalink</label>
<div class="input-group mb-4 hsm-url-group">
<input id="headingShareInput" type="text" class="form-control font-monospace" readonly aria-readonly="true" style="font-size: 0.85rem;" />
<button class="btn btn-primary hsm-copy" type="button" aria-label="Copy" title="Copy">
<i class="fa-duotone fa-clipboard" aria-hidden="true"></i>
</button>
</div>
<div class="small fw-bold mb-2 text-muted text-uppercase" style="font-size: 0.7rem; letter-spacing: 0.5px;">Share via</div>
<div class="hsm-share-grid">
<a id="share-twitter" class="btn btn-outline-secondary w-100" target="_blank" rel="noopener noreferrer">
<i class="fa-brands fa-twitter me-2"></i>Twitter
</a>
<a id="share-linkedin" class="btn btn-outline-secondary w-100" target="_blank" rel="noopener noreferrer">
<i class="fa-brands fa-linkedin me-2"></i>LinkedIn
</a>
<a id="share-facebook" class="btn btn-outline-secondary w-100" target="_blank" rel="noopener noreferrer">
<i class="fa-brands fa-facebook me-2"></i>Facebook
</a>
</div>
</div>
</div>
</div>
<style>
.heading-share-modal {
position: fixed;
inset: 0;
display: flex;
justify-content: center;
align-items: center;
background: rgba(0, 0, 0, 0.6);
z-index: 1050;
padding: 1rem;
backdrop-filter: blur(4px);
-webkit-backdrop-filter: blur(4px);
}
.heading-share-modal[hidden] { display: none !important; }
.hsm-dialog {
max-width: 420px;
width: 100%;
background: var(--bs-body-bg, #fff);
color: var(--bs-body-color, #212529);
border: 1px solid var(--bs-border-color, rgba(0,0,0,0.1));
border-radius: 1rem;
box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
overflow: hidden;
animation: hsm-fade-in 0.2s ease-out;
}
@keyframes hsm-fade-in {
from { opacity: 0; transform: scale(0.95); }
to { opacity: 1; transform: scale(1); }
}
[data-bs-theme="dark"] .hsm-dialog {
background: #1e293b;
border-color: rgba(255,255,255,0.1);
color: #f8f9fa;
}
.hsm-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 1rem 1.5rem;
border-bottom: 1px solid var(--bs-border-color, rgba(0,0,0,0.1));
background: rgba(0,0,0,0.02);
}
[data-bs-theme="dark"] .hsm-header {
background: rgba(255,255,255,0.02);
border-color: rgba(255,255,255,0.1);
}
.hsm-close {
background: transparent;
border: none;
color: inherit;
opacity: 0.5;
padding: 0.25rem 0.5rem;
border-radius: 0.25rem;
font-size: 1.2rem;
line-height: 1;
transition: opacity 0.2s;
}
.hsm-close:hover {
opacity: 1;
}
.hsm-body {
padding: 1.5rem;
}
.hsm-url-group {
display: flex !important;
align-items: stretch;
}
.hsm-url-group .form-control {
flex: 1;
min-width: 0;
margin: 0;
background: var(--bs-secondary-bg, #f8f9fa);
border-color: var(--bs-border-color, #dee2e6);
border-top-right-radius: 0;
border-bottom-right-radius: 0;
height: 42px;
}
.hsm-url-group .btn {
flex: 0 0 auto;
margin: 0;
margin-left: -1px;
border-top-left-radius: 0;
border-bottom-left-radius: 0;
height: 42px;
display: flex;
align-items: center;
justify-content: center;
padding: 0 1.25rem;
z-index: 2;
}
[data-bs-theme="dark"] .hsm-url-group .form-control {
background: #0f172a;
border-color: #334155;
color: #e2e8f0;
}
.hsm-share-grid {
display: flex;
flex-direction: column;
gap: 0.5rem;
}
.hsm-share-grid .btn {
display: flex;
align-items: center;
justify-content: center;
font-size: 0.9rem;
padding: 0.6rem;
border-color: var(--bs-border-color);
width: 100%;
}
[data-bs-theme="dark"] .hsm-share-grid .btn {
color: #e2e8f0;
border-color: #475569;
}
[data-bs-theme="dark"] .hsm-share-grid .btn:hover {
background: #334155;
border-color: #cbd5e1;
}
</style>
<script>
(function(){
const modal = document.getElementById('headingShareModal');
if(!modal) return;
const input = modal.querySelector('#headingShareInput');
const copyBtn = modal.querySelector('.hsm-copy');
const twitter = modal.querySelector('#share-twitter');
const linkedin = modal.querySelector('#share-linkedin');
const facebook = modal.querySelector('#share-facebook');
const closeBtn = modal.querySelector('.hsm-close');
let lastFocus=null;
let trapBound=false;
function buildUrl(id){ return window.location.origin + window.location.pathname + '#' + id; }
function isOpen(){ return !modal.hasAttribute('hidden'); }
function hydrate(id){
const url=buildUrl(id);
input.value=url;
const enc=encodeURIComponent(url);
const text=encodeURIComponent(document.title);
if(twitter) twitter.href=`https://twitter.com/intent/tweet?url=${enc}&text=${text}`;
if(linkedin) linkedin.href=`https://www.linkedin.com/sharing/share-offsite/?url=${enc}`;
if(facebook) facebook.href=`https://www.facebook.com/sharer/sharer.php?u=${enc}`;
}
function openModal(id){
lastFocus=document.activeElement;
hydrate(id);
if(!isOpen()){
modal.removeAttribute('hidden');
}
requestAnimationFrame(()=>{ input.focus(); });
trapFocus();
}
function closeModal(){
if(!isOpen()) return;
modal.setAttribute('hidden','');
if(lastFocus && typeof lastFocus.focus==='function') lastFocus.focus();
}
function copyCurrent(){
try{ navigator.clipboard.writeText(input.value).then(()=>feedback(true),()=>fallback()); }
catch(e){ fallback(); }
}
function fallback(){ input.select(); try{ document.execCommand('copy'); feedback(true);}catch(e){ feedback(false);} }
function feedback(ok){ if(!copyBtn) return; const icon=copyBtn.querySelector('i'); if(!icon) return; const prev=copyBtn.getAttribute('data-prev')||icon.className; if(!copyBtn.getAttribute('data-prev')) copyBtn.setAttribute('data-prev',prev); icon.className= ok ? 'fa-duotone fa-clipboard-check':'fa-duotone fa-circle-exclamation'; setTimeout(()=>{ icon.className=prev; },1800); }
function handleShareClick(e){ e.preventDefault(); const btn=e.currentTarget; const id=btn.getAttribute('data-share-target'); if(id) openModal(id); }
function bindShareButtons(){
document.querySelectorAll('.h-share').forEach(btn=>{
if(!btn.dataset.hShareBound){ btn.addEventListener('click', handleShareClick); btn.dataset.hShareBound='1'; }
});
}
bindShareButtons();
if(document.readyState==='loading'){
document.addEventListener('DOMContentLoaded', bindShareButtons);
} else {
requestAnimationFrame(bindShareButtons);
}
document.addEventListener('click', function(e){
const shareBtn=e.target.closest && e.target.closest('.h-share');
if(shareBtn && !shareBtn.dataset.hShareBound){ handleShareClick.call(shareBtn, e); }
}, true);
document.addEventListener('click', e=>{
if(e.target===modal) closeModal();
if(e.target.closest && e.target.closest('.hsm-close')){ e.preventDefault(); closeModal(); }
if(copyBtn && (e.target===copyBtn || (e.target.closest && e.target.closest('.hsm-copy')))) { e.preventDefault(); copyCurrent(); }
});
document.addEventListener('keydown', e=>{ if(e.key==='Escape' && isOpen()) closeModal(); });
function trapFocus(){
if(trapBound) return;
trapBound=true;
modal.addEventListener('keydown', f=>{ if(f.key==='Tab' && isOpen()){ const focusable=[...modal.querySelectorAll('a[href],button,input,textarea,select,[tabindex]:not([tabindex="-1"])')].filter(el=>!el.hasAttribute('disabled')); if(!focusable.length) return; const first=focusable[0]; const last=focusable[focusable.length-1]; if(f.shiftKey && document.activeElement===first){ f.preventDefault(); last.focus(); } else if(!f.shiftKey && document.activeElement===last){ f.preventDefault(); first.focus(); } } });
}
if(closeBtn) closeBtn.addEventListener('click', e=>{ e.preventDefault(); closeModal(); });
})();
</script><p>Schema constraints are declarative rules that enforce data integrity and consistency in your Geode graph database. By defining constraints at the schema level, you ensure that invalid data never enters the system, maintaining high quality across all nodes, edges, and properties. Geode implements constraints according to the ISO/IEC 39075:2024 GQL standard while optimizing enforcement at the graph storage layer.</p>
<h3 id="understanding-constraints-in-graph-context" class="position-relative d-flex align-items-center group">
<span>Understanding Constraints in Graph Context</span>
<button type="button"
class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1"
data-share-target="understanding-constraints-in-graph-context"
aria-haspopup="dialog"
aria-label="Share link: Understanding Constraints in Graph Context">
<i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i>
<span class="visually-hidden">Share link</span>
</button>
</h3><p>Unlike relational databases where constraints apply to tables and columns, Geode enforces constraints on node types, edge types, and their properties. This graph-native approach ensures that your property graph maintains structural and semantic integrity while preserving the flexibility that makes graph databases powerful.</p>
<p>Constraints in Geode serve multiple purposes:</p>
<ul>
<li><strong>Data Integrity</strong>: Prevent invalid data from entering the system</li>
<li><strong>Business Logic</strong>: Encode domain rules directly in the schema</li>
<li><strong>Performance</strong>: Enable query optimizer to make assumptions about data</li>
<li><strong>Documentation</strong>: Schema constraints self-document data requirements</li>
<li><strong>Client Safety</strong>: Provide early error detection before complex transactions</li>
</ul>
<h3 id="core-constraint-types" class="position-relative d-flex align-items-center group">
<span>Core Constraint Types</span>
<button type="button"
class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1"
data-share-target="core-constraint-types"
aria-haspopup="dialog"
aria-label="Share link: Core Constraint Types">
<i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i>
<span class="visually-hidden">Share link</span>
</button>
</h3>
<h4 id="not-null-constraints" class="position-relative d-flex align-items-center group">
<span>NOT NULL Constraints</span>
<button type="button"
class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1"
data-share-target="not-null-constraints"
aria-haspopup="dialog"
aria-label="Share link: NOT NULL Constraints">
<i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i>
<span class="visually-hidden">Share link</span>
</button>
</h4><p>NOT NULL constraints ensure that required properties always have values, preventing incomplete data from degrading graph quality. In graph databases, missing property values can break traversal logic and analytical queries.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-gql" data-lang="gql"><span class="line"><span class="cl"><span class="err">--</span><span class="w"> </span><span class="py">Define</span><span class="w"> </span><span class="py">required</span><span class="w"> </span><span class="py">properties</span><span class="w"> </span><span class="py">for</span><span class="w"> </span><span class="py">Person</span><span class="w"> </span><span class="py">nodes</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">CREATE</span><span class="w"> </span><span class="py">NODE</span><span class="w"> </span><span class="py">TYPE</span><span class="w"> </span><span class="py">Person</span><span class="w"> </span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">id</span><span class="w"> </span><span class="py">STRING</span><span class="w"> </span><span class="py">NOT</span><span class="w"> </span><span class="py">NULL</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">name</span><span class="w"> </span><span class="py">STRING</span><span class="w"> </span><span class="py">NOT</span><span class="w"> </span><span class="py">NULL</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">email</span><span class="w"> </span><span class="py">STRING</span><span class="w"> </span><span class="py">NOT</span><span class="w"> </span><span class="py">NULL</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">phone</span><span class="w"> </span><span class="py">STRING</span><span class="p">,</span><span class="w"> </span><span class="err">--</span><span class="w"> </span><span class="py">Optional</span><span class="w"> </span><span class="py">field</span><span class="p">,</span><span class="w"> </span><span class="py">nullable</span><span class="w"> </span><span class="py">by</span><span class="w"> </span><span class="py">default</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">middle_name</span><span class="w"> </span><span class="py">STRING</span><span class="p">,</span><span class="w"> </span><span class="err">--</span><span class="w"> </span><span class="py">Explicitly</span><span class="w"> </span><span class="py">nullable</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">created_at</span><span class="w"> </span><span class="py">TIMESTAMP</span><span class="w"> </span><span class="py">NOT</span><span class="w"> </span><span class="py">NULL</span><span class="w"> </span><span class="py">DEFAULT</span><span class="w"> </span><span class="py">NOW</span><span class="p">()</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">)</span><span class="err">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="err">--</span><span class="w"> </span><span class="py">Edge</span><span class="w"> </span><span class="kd">type</span><span class="w"> </span><span class="nc">with</span><span class="w"> </span><span class="py">required</span><span class="w"> </span><span class="py">relationship</span><span class="w"> </span><span class="py">metadata</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">CREATE</span><span class="w"> </span><span class="py">EDGE</span><span class="w"> </span><span class="py">TYPE</span><span class="w"> </span><span class="py">WORKS_FOR</span><span class="w"> </span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">start_date</span><span class="w"> </span><span class="py">DATE</span><span class="w"> </span><span class="py">NOT</span><span class="w"> </span><span class="py">NULL</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">end_date</span><span class="w"> </span><span class="py">DATE</span><span class="p">,</span><span class="w"> </span><span class="err">--</span><span class="w"> </span><span class="py">NULL</span><span class="w"> </span><span class="py">means</span><span class="w"> </span><span class="py">current</span><span class="w"> </span><span class="py">employment</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">position</span><span class="w"> </span><span class="py">STRING</span><span class="w"> </span><span class="py">NOT</span><span class="w"> </span><span class="py">NULL</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">department</span><span class="w"> </span><span class="py">STRING</span><span class="w"> </span><span class="py">NOT</span><span class="w"> </span><span class="py">NULL</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">)</span><span class="err">;</span><span class="w">
</span></span></span></code></pre></div><p>When inserting nodes without required values, Geode immediately rejects the operation:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="c1"># Python client - constraint violation</span>
</span></span><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">geode_client</span> <span class="kn">import</span> <span class="n">Client</span><span class="p">,</span> <span class="n">ConstraintViolationError</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">client</span> <span class="o">=</span> <span class="n">Client</span><span class="p">(</span><span class="n">host</span><span class="o">=</span><span class="s2">"localhost"</span><span class="p">,</span> <span class="n">port</span><span class="o">=</span><span class="mi">3141</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">async</span> <span class="k">with</span> <span class="n">client</span><span class="o">.</span><span class="n">connection</span><span class="p">()</span> <span class="k">as</span> <span class="n">conn</span><span class="p">:</span>
</span></span><span class="line"><span class="cl"> <span class="k">try</span><span class="p">:</span>
</span></span><span class="line"><span class="cl"> <span class="c1"># Missing required 'name' field</span>
</span></span><span class="line"><span class="cl"> <span class="k">await</span> <span class="n">conn</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span>
</span></span><span class="line"><span class="cl"> <span class="s2">"INSERT (p:Person {email: $email})"</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="p">{</span><span class="s2">"email"</span><span class="p">:</span> <span class="s2">"[email protected]"</span><span class="p">}</span>
</span></span><span class="line"><span class="cl"> <span class="p">)</span>
</span></span><span class="line"><span class="cl"> <span class="k">except</span> <span class="n">ConstraintViolationError</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
</span></span><span class="line"><span class="cl"> <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Missing required field: </span><span class="si">{</span><span class="n">e</span><span class="o">.</span><span class="n">field</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"> <span class="c1"># Output: Missing required field: name</span>
</span></span></code></pre></div>
<h4 id="unique-constraints" class="position-relative d-flex align-items-center group">
<span>UNIQUE Constraints</span>
<button type="button"
class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1"
data-share-target="unique-constraints"
aria-haspopup="dialog"
aria-label="Share link: UNIQUE Constraints">
<i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i>
<span class="visually-hidden">Share link</span>
</button>
</h4><p>UNIQUE constraints prevent duplicate values across nodes or edges of the same type. Geode automatically creates indexes for UNIQUE columns to provide O(1) duplicate checking and fast lookups.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-gql" data-lang="gql"><span class="line"><span class="cl"><span class="err">--</span><span class="w"> </span><span class="py">Single</span><span class="err">-</span><span class="py">column</span><span class="w"> </span><span class="py">uniqueness</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">CREATE</span><span class="w"> </span><span class="py">NODE</span><span class="w"> </span><span class="py">TYPE</span><span class="w"> </span><span class="py">Person</span><span class="w"> </span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">id</span><span class="w"> </span><span class="py">STRING</span><span class="w"> </span><span class="py">PRIMARY</span><span class="w"> </span><span class="py">KEY</span><span class="p">,</span><span class="w"> </span><span class="err">--</span><span class="w"> </span><span class="py">Implicitly</span><span class="w"> </span><span class="py">UNIQUE</span><span class="w"> </span><span class="py">and</span><span class="w"> </span><span class="py">NOT</span><span class="w"> </span><span class="py">NULL</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">email</span><span class="w"> </span><span class="py">STRING</span><span class="w"> </span><span class="py">UNIQUE</span><span class="w"> </span><span class="py">NOT</span><span class="w"> </span><span class="py">NULL</span><span class="p">,</span><span class="w"> </span><span class="err">--</span><span class="w"> </span><span class="py">Business</span><span class="w"> </span><span class="py">key</span><span class="w"> </span><span class="py">uniqueness</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">ssn</span><span class="w"> </span><span class="py">STRING</span><span class="w"> </span><span class="py">UNIQUE</span><span class="p">,</span><span class="w"> </span><span class="err">--</span><span class="w"> </span><span class="py">Nullable</span><span class="w"> </span><span class="py">but</span><span class="w"> </span><span class="py">unique</span><span class="w"> </span><span class="py">when</span><span class="w"> </span><span class="py">present</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">username</span><span class="w"> </span><span class="py">STRING</span><span class="w"> </span><span class="py">UNIQUE</span><span class="w"> </span><span class="py">NOT</span><span class="w"> </span><span class="py">NULL</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">)</span><span class="err">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="err">--</span><span class="w"> </span><span class="py">Multi</span><span class="err">-</span><span class="py">column</span><span class="w"> </span><span class="py">uniqueness</span><span class="w"> </span><span class="p">(</span><span class="py">composite</span><span class="w"> </span><span class="py">keys</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">CREATE</span><span class="w"> </span><span class="py">NODE</span><span class="w"> </span><span class="py">TYPE</span><span class="w"> </span><span class="py">Employee</span><span class="w"> </span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">employee_id</span><span class="w"> </span><span class="py">STRING</span><span class="w"> </span><span class="py">NOT</span><span class="w"> </span><span class="py">NULL</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">department</span><span class="w"> </span><span class="py">STRING</span><span class="w"> </span><span class="py">NOT</span><span class="w"> </span><span class="py">NULL</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">badge_number</span><span class="w"> </span><span class="py">STRING</span><span class="w"> </span><span class="py">NOT</span><span class="w"> </span><span class="py">NULL</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">CONSTRAINT</span><span class="w"> </span><span class="py">unique_dept_badge</span><span class="w"> </span><span class="py">UNIQUE</span><span class="w"> </span><span class="p">(</span><span class="py">department</span><span class="p">,</span><span class="w"> </span><span class="py">badge_number</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">)</span><span class="err">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="err">--</span><span class="w"> </span><span class="py">Edge</span><span class="w"> </span><span class="py">uniqueness</span><span class="w"> </span><span class="py">prevents</span><span class="w"> </span><span class="py">duplicate</span><span class="w"> </span><span class="py">relationships</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">CREATE</span><span class="w"> </span><span class="py">EDGE</span><span class="w"> </span><span class="py">TYPE</span><span class="w"> </span><span class="py">FOLLOWS</span><span class="w"> </span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">followed_at</span><span class="w"> </span><span class="py">TIMESTAMP</span><span class="w"> </span><span class="py">NOT</span><span class="w"> </span><span class="py">NULL</span><span class="w"> </span><span class="py">DEFAULT</span><span class="w"> </span><span class="py">NOW</span><span class="p">(),</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">CONSTRAINT</span><span class="w"> </span><span class="py">unique_follow</span><span class="w"> </span><span class="py">UNIQUE</span><span class="w"> </span><span class="p">(</span><span class="py">FROM</span><span class="p">,</span><span class="w"> </span><span class="py">TO</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">)</span><span class="err">;</span><span class="w">
</span></span></span></code></pre></div><p>Application-level usage:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="c1">// Go client - checking uniqueness before insert
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kn">package</span> <span class="nx">main</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="p">(</span>
</span></span><span class="line"><span class="cl"> <span class="s">"context"</span>
</span></span><span class="line"><span class="cl"> <span class="s">"fmt"</span>
</span></span><span class="line"><span class="cl"> <span class="s">"geodedb.com/geode"</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">func</span> <span class="nf">createUser</span><span class="p">(</span><span class="nx">ctx</span> <span class="nx">context</span><span class="p">.</span><span class="nx">Context</span><span class="p">,</span> <span class="nx">db</span> <span class="o">*</span><span class="nx">geode</span><span class="p">.</span><span class="nx">DB</span><span class="p">,</span> <span class="nx">email</span> <span class="kt">string</span><span class="p">)</span> <span class="kt">error</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="c1">// UNIQUE constraint enforced automatically
</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">_</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">db</span><span class="p">.</span><span class="nf">ExecContext</span><span class="p">(</span><span class="nx">ctx</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="s">"INSERT (u:Person {email: $1, name: $2})"</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="nx">email</span><span class="p">,</span> <span class="s">"Alice Smith"</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="nx">geode</span><span class="p">.</span><span class="nf">IsConstraintViolation</span><span class="p">(</span><span class="nx">err</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nx">fmt</span><span class="p">.</span><span class="nf">Errorf</span><span class="p">(</span><span class="s">"email already exists: %s"</span><span class="p">,</span> <span class="nx">email</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"> <span class="p">}</span>
</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nx">err</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div>
<h4 id="check-constraints" class="position-relative d-flex align-items-center group">
<span>CHECK Constraints</span>
<button type="button"
class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1"
data-share-target="check-constraints"
aria-haspopup="dialog"
aria-label="Share link: CHECK Constraints">
<i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i>
<span class="visually-hidden">Share link</span>
</button>
</h4><p>CHECK constraints enforce business rules using boolean expressions. These constraints validate property values against complex conditions, encoding domain logic directly in the schema.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-gql" data-lang="gql"><span class="line"><span class="cl"><span class="err">--</span><span class="w"> </span><span class="py">Simple</span><span class="w"> </span><span class="py">range</span><span class="w"> </span><span class="py">checks</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">CREATE</span><span class="w"> </span><span class="py">NODE</span><span class="w"> </span><span class="py">TYPE</span><span class="w"> </span><span class="py">Person</span><span class="w"> </span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">age</span><span class="w"> </span><span class="py">INTEGER</span><span class="w"> </span><span class="py">CHECK</span><span class="w"> </span><span class="p">(</span><span class="py">age</span><span class="w"> </span><span class="err">></span><span class="p">=</span><span class="w"> </span><span class="py">0</span><span class="w"> </span><span class="py">AND</span><span class="w"> </span><span class="py">age</span><span class="w"> </span><span class="err"><</span><span class="p">=</span><span class="w"> </span><span class="py">150</span><span class="p">),</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">salary</span><span class="w"> </span><span class="py">DECIMAL</span><span class="w"> </span><span class="py">CHECK</span><span class="w"> </span><span class="p">(</span><span class="py">salary</span><span class="w"> </span><span class="err">></span><span class="p">=</span><span class="w"> </span><span class="py">0</span><span class="p">),</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">email</span><span class="w"> </span><span class="py">STRING</span><span class="w"> </span><span class="py">CHECK</span><span class="w"> </span><span class="p">(</span><span class="py">email</span><span class="w"> </span><span class="py">LIKE</span><span class="w"> </span><span class="err">'%@%.%'</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">)</span><span class="err">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="err">--</span><span class="w"> </span><span class="py">Pattern</span><span class="w"> </span><span class="py">validation</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">CREATE</span><span class="w"> </span><span class="py">NODE</span><span class="w"> </span><span class="py">TYPE</span><span class="w"> </span><span class="py">Product</span><span class="w"> </span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">sku</span><span class="w"> </span><span class="py">STRING</span><span class="w"> </span><span class="py">CHECK</span><span class="w"> </span><span class="p">(</span><span class="py">sku</span><span class="w"> </span><span class="err">~</span><span class="w"> </span><span class="err">'^</span><span class="p">[</span><span class="py">A</span><span class="err">-</span><span class="py">Z</span><span class="p">]{</span><span class="py">3</span><span class="p">}</span><span class="err">-</span><span class="p">[</span><span class="py">0</span><span class="err">-</span><span class="py">9</span><span class="p">]{</span><span class="py">6</span><span class="p">}</span><span class="err">$'</span><span class="p">),</span><span class="w"> </span><span class="err">--</span><span class="w"> </span><span class="py">Format</span><span class="p">:</span><span class="w"> </span><span class="nc">ABC</span><span class="err">-</span><span class="py">123456</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">price</span><span class="w"> </span><span class="py">DECIMAL</span><span class="w"> </span><span class="py">CHECK</span><span class="w"> </span><span class="p">(</span><span class="py">price</span><span class="w"> </span><span class="err">></span><span class="w"> </span><span class="py">0</span><span class="p">),</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">discount_pct</span><span class="w"> </span><span class="py">DECIMAL</span><span class="w"> </span><span class="py">CHECK</span><span class="w"> </span><span class="p">(</span><span class="py">discount_pct</span><span class="w"> </span><span class="err">></span><span class="p">=</span><span class="w"> </span><span class="py">0</span><span class="w"> </span><span class="py">AND</span><span class="w"> </span><span class="py">discount_pct</span><span class="w"> </span><span class="err"><</span><span class="p">=</span><span class="w"> </span><span class="py">100</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">)</span><span class="err">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="err">--</span><span class="w"> </span><span class="py">Enumeration</span><span class="w"> </span><span class="py">constraints</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">CREATE</span><span class="w"> </span><span class="py">NODE</span><span class="w"> </span><span class="py">TYPE</span><span class="w"> </span><span class="py">Order</span><span class="w"> </span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">status</span><span class="w"> </span><span class="py">STRING</span><span class="w"> </span><span class="py">CHECK</span><span class="w"> </span><span class="p">(</span><span class="py">status</span><span class="w"> </span><span class="py">IN</span><span class="w"> </span><span class="p">(</span><span class="err">'</span><span class="py">pending</span><span class="err">'</span><span class="p">,</span><span class="w"> </span><span class="err">'</span><span class="py">processing</span><span class="err">'</span><span class="p">,</span><span class="w"> </span><span class="err">'</span><span class="py">shipped</span><span class="err">'</span><span class="p">,</span><span class="w"> </span><span class="err">'</span><span class="py">delivered</span><span class="err">'</span><span class="p">,</span><span class="w"> </span><span class="err">'</span><span class="py">cancelled</span><span class="err">'</span><span class="p">)),</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">priority</span><span class="w"> </span><span class="py">STRING</span><span class="w"> </span><span class="py">CHECK</span><span class="w"> </span><span class="p">(</span><span class="py">priority</span><span class="w"> </span><span class="py">IN</span><span class="w"> </span><span class="p">(</span><span class="err">'</span><span class="py">low</span><span class="err">'</span><span class="p">,</span><span class="w"> </span><span class="err">'</span><span class="py">normal</span><span class="err">'</span><span class="p">,</span><span class="w"> </span><span class="err">'</span><span class="py">high</span><span class="err">'</span><span class="p">,</span><span class="w"> </span><span class="err">'</span><span class="py">urgent</span><span class="err">'</span><span class="p">))</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">)</span><span class="err">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="err">--</span><span class="w"> </span><span class="py">Multi</span><span class="err">-</span><span class="py">property</span><span class="w"> </span><span class="py">constraints</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">CREATE</span><span class="w"> </span><span class="py">NODE</span><span class="w"> </span><span class="py">TYPE</span><span class="w"> </span><span class="py">Booking</span><span class="w"> </span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">check_in</span><span class="w"> </span><span class="py">DATE</span><span class="w"> </span><span class="py">NOT</span><span class="w"> </span><span class="py">NULL</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">check_out</span><span class="w"> </span><span class="py">DATE</span><span class="w"> </span><span class="py">NOT</span><span class="w"> </span><span class="py">NULL</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">guests</span><span class="w"> </span><span class="py">INTEGER</span><span class="w"> </span><span class="py">CHECK</span><span class="w"> </span><span class="p">(</span><span class="py">guests</span><span class="w"> </span><span class="err">></span><span class="w"> </span><span class="py">0</span><span class="w"> </span><span class="py">AND</span><span class="w"> </span><span class="py">guests</span><span class="w"> </span><span class="err"><</span><span class="p">=</span><span class="w"> </span><span class="py">10</span><span class="p">),</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">CONSTRAINT</span><span class="w"> </span><span class="py">valid_date_range</span><span class="w"> </span><span class="py">CHECK</span><span class="w"> </span><span class="p">(</span><span class="py">check_out</span><span class="w"> </span><span class="err">></span><span class="w"> </span><span class="py">check_in</span><span class="p">),</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">CONSTRAINT</span><span class="w"> </span><span class="py">min_stay</span><span class="w"> </span><span class="py">CHECK</span><span class="w"> </span><span class="p">(</span><span class="py">check_out</span><span class="w"> </span><span class="err">></span><span class="p">=</span><span class="w"> </span><span class="py">check_in</span><span class="w"> </span><span class="err">+</span><span class="w"> </span><span class="py">INTERVAL</span><span class="w"> </span><span class="err">'</span><span class="py">1</span><span class="w"> </span><span class="py">day</span><span class="err">'</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">)</span><span class="err">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="err">--</span><span class="w"> </span><span class="py">Conditional</span><span class="w"> </span><span class="py">constraints</span><span class="w"> </span><span class="py">based</span><span class="w"> </span><span class="kd">on</span><span class="w"> </span><span class="py">other</span><span class="w"> </span><span class="py">properties</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">CREATE</span><span class="w"> </span><span class="py">NODE</span><span class="w"> </span><span class="py">TYPE</span><span class="w"> </span><span class="py">Employee</span><span class="w"> </span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="kd">type</span><span class="w"> </span><span class="nc">STRING</span><span class="w"> </span><span class="py">CHECK</span><span class="w"> </span><span class="p">(</span><span class="kd">type</span><span class="w"> </span><span class="nc">IN</span><span class="w"> </span><span class="p">(</span><span class="err">'</span><span class="py">full_time</span><span class="err">'</span><span class="p">,</span><span class="w"> </span><span class="err">'</span><span class="py">part_time</span><span class="err">'</span><span class="p">,</span><span class="w"> </span><span class="err">'</span><span class="py">contractor</span><span class="err">'</span><span class="p">)),</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">salary</span><span class="w"> </span><span class="py">DECIMAL</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">hourly_rate</span><span class="w"> </span><span class="py">DECIMAL</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">benefits_eligible</span><span class="w"> </span><span class="py">BOOLEAN</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">CONSTRAINT</span><span class="w"> </span><span class="py">compensation_model</span><span class="w"> </span><span class="py">CHECK</span><span class="w"> </span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="p">(</span><span class="kd">type</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="err">'</span><span class="nc">full_time</span><span class="err">'</span><span class="w"> </span><span class="py">AND</span><span class="w"> </span><span class="py">salary</span><span class="w"> </span><span class="py">IS</span><span class="w"> </span><span class="py">NOT</span><span class="w"> </span><span class="py">NULL</span><span class="w"> </span><span class="py">AND</span><span class="w"> </span><span class="py">hourly_rate</span><span class="w"> </span><span class="py">IS</span><span class="w"> </span><span class="py">NULL</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">OR</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="p">(</span><span class="kd">type</span><span class="w"> </span><span class="nc">IN</span><span class="w"> </span><span class="p">(</span><span class="err">'</span><span class="py">part_time</span><span class="err">'</span><span class="p">,</span><span class="w"> </span><span class="err">'</span><span class="py">contractor</span><span class="err">'</span><span class="p">)</span><span class="w"> </span><span class="py">AND</span><span class="w"> </span><span class="py">salary</span><span class="w"> </span><span class="py">IS</span><span class="w"> </span><span class="py">NULL</span><span class="w"> </span><span class="py">AND</span><span class="w"> </span><span class="py">hourly_rate</span><span class="w"> </span><span class="py">IS</span><span class="w"> </span><span class="py">NOT</span><span class="w"> </span><span class="py">NULL</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="p">),</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">CONSTRAINT</span><span class="w"> </span><span class="py">benefits_rule</span><span class="w"> </span><span class="py">CHECK</span><span class="w"> </span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="kd">type</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="err">'</span><span class="nc">full_time</span><span class="err">'</span><span class="w"> </span><span class="py">OR</span><span class="w"> </span><span class="py">benefits_eligible</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="py">false</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">)</span><span class="err">;</span><span class="w">
</span></span></span></code></pre></div><p>Geode evaluates CHECK constraints on every INSERT and UPDATE operation, providing immediate feedback:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-rust" data-lang="rust"><span class="line"><span class="cl"><span class="c1">// Rust client - handling CHECK constraint violations
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">use</span><span class="w"> </span><span class="n">geode_client</span>::<span class="p">{</span><span class="n">Client</span><span class="p">,</span><span class="w"> </span><span class="n">Error</span><span class="p">,</span><span class="w"> </span><span class="n">ErrorKind</span><span class="p">};</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="k">async</span><span class="w"> </span><span class="k">fn</span> <span class="nf">create_product</span><span class="p">(</span><span class="n">client</span>: <span class="kp">&</span><span class="nc">Client</span><span class="p">,</span><span class="w"> </span><span class="n">sku</span>: <span class="kp">&</span><span class="kt">str</span><span class="p">,</span><span class="w"> </span><span class="n">price</span>: <span class="kt">f64</span><span class="p">)</span><span class="w"> </span>-> <span class="nb">Result</span><span class="o"><</span><span class="p">(),</span><span class="w"> </span><span class="n">Error</span><span class="o">></span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">result</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">client</span><span class="p">.</span><span class="n">execute</span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="s">"INSERT (p:Product {sku: $sku, price: $price})"</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="o">&</span><span class="p">[(</span><span class="s">"sku"</span><span class="p">,</span><span class="w"> </span><span class="n">sku</span><span class="p">),</span><span class="w"> </span><span class="p">(</span><span class="s">"price"</span><span class="p">,</span><span class="w"> </span><span class="o">&</span><span class="n">price</span><span class="p">)]</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="p">).</span><span class="k">await</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="k">match</span><span class="w"> </span><span class="n">result</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nb">Err</span><span class="p">(</span><span class="n">Error</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">kind</span>: <span class="nc">ErrorKind</span>::<span class="n">ConstraintViolation</span><span class="p">,</span><span class="w"> </span><span class="o">..</span><span class="w"> </span><span class="p">})</span><span class="w"> </span><span class="o">=></span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="fm">eprintln!</span><span class="p">(</span><span class="s">"Invalid product data: SKU format or price constraint failed"</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nb">Err</span><span class="p">(</span><span class="n">Error</span>::<span class="n">validation_failed</span><span class="p">(</span><span class="s">"Product validation failed"</span><span class="p">))</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="n">other</span><span class="w"> </span><span class="o">=></span><span class="w"> </span><span class="n">other</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">}</span><span class="w">
</span></span></span></code></pre></div>
<h4 id="foreign-key-constraints-referential-integrity" class="position-relative d-flex align-items-center group">
<span>FOREIGN KEY Constraints (Referential Integrity)</span>
<button type="button"
class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1"
data-share-target="foreign-key-constraints-referential-integrity"
aria-haspopup="dialog"
aria-label="Share link: FOREIGN KEY Constraints (Referential Integrity)">
<i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i>
<span class="visually-hidden">Share link</span>
</button>
</h4><p>Foreign key constraints ensure that relationships reference existing nodes, maintaining referential integrity across the graph. Geode enforces these constraints by validating that referenced nodes exist before creating edges.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-gql" data-lang="gql"><span class="line"><span class="cl"><span class="err">--</span><span class="w"> </span><span class="py">Edge</span><span class="w"> </span><span class="kd">type</span><span class="w"> </span><span class="nc">with</span><span class="w"> </span><span class="py">foreign</span><span class="w"> </span><span class="py">key</span><span class="w"> </span><span class="py">constraints</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">CREATE</span><span class="w"> </span><span class="py">EDGE</span><span class="w"> </span><span class="py">TYPE</span><span class="w"> </span><span class="py">WORKS_FOR</span><span class="w"> </span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">employee_id</span><span class="w"> </span><span class="py">STRING</span><span class="w"> </span><span class="py">REFERENCES</span><span class="w"> </span><span class="py">Person</span><span class="p">(</span><span class="py">id</span><span class="p">),</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">company_id</span><span class="w"> </span><span class="py">STRING</span><span class="w"> </span><span class="py">REFERENCES</span><span class="w"> </span><span class="py">Company</span><span class="p">(</span><span class="py">id</span><span class="p">),</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">start_date</span><span class="w"> </span><span class="py">DATE</span><span class="w"> </span><span class="py">NOT</span><span class="w"> </span><span class="py">NULL</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">)</span><span class="err">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="err">--</span><span class="w"> </span><span class="py">Cascade</span><span class="w"> </span><span class="py">options</span><span class="w"> </span><span class="py">for</span><span class="w"> </span><span class="py">deletions</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">CREATE</span><span class="w"> </span><span class="py">EDGE</span><span class="w"> </span><span class="py">TYPE</span><span class="w"> </span><span class="py">MANAGES</span><span class="w"> </span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">manager_id</span><span class="w"> </span><span class="py">STRING</span><span class="w"> </span><span class="py">REFERENCES</span><span class="w"> </span><span class="py">Employee</span><span class="p">(</span><span class="py">id</span><span class="p">)</span><span class="w"> </span><span class="py">ON</span><span class="w"> </span><span class="py">DELETE</span><span class="w"> </span><span class="py">CASCADE</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">team_id</span><span class="w"> </span><span class="py">STRING</span><span class="w"> </span><span class="py">REFERENCES</span><span class="w"> </span><span class="py">Team</span><span class="p">(</span><span class="py">id</span><span class="p">)</span><span class="w"> </span><span class="py">ON</span><span class="w"> </span><span class="py">DELETE</span><span class="w"> </span><span class="py">SET</span><span class="w"> </span><span class="py">NULL</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">)</span><span class="err">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="err">--</span><span class="w"> </span><span class="py">Self</span><span class="err">-</span><span class="py">referential</span><span class="w"> </span><span class="py">constraints</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">CREATE</span><span class="w"> </span><span class="py">EDGE</span><span class="w"> </span><span class="py">TYPE</span><span class="w"> </span><span class="py">REPORTS_TO</span><span class="w"> </span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">from_id</span><span class="w"> </span><span class="py">STRING</span><span class="w"> </span><span class="py">REFERENCES</span><span class="w"> </span><span class="py">Employee</span><span class="p">(</span><span class="py">id</span><span class="p">),</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">to_id</span><span class="w"> </span><span class="py">STRING</span><span class="w"> </span><span class="py">REFERENCES</span><span class="w"> </span><span class="py">Employee</span><span class="p">(</span><span class="py">id</span><span class="p">),</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">CONSTRAINT</span><span class="w"> </span><span class="py">no_self_reporting</span><span class="w"> </span><span class="py">CHECK</span><span class="w"> </span><span class="p">(</span><span class="py">from_id</span><span class="w"> </span><span class="p">!=</span><span class="w"> </span><span class="py">to_id</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">)</span><span class="err">;</span><span class="w">
</span></span></span></code></pre></div>
<h3 id="complex-constraint-patterns" class="position-relative d-flex align-items-center group">
<span>Complex Constraint Patterns</span>
<button type="button"
class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1"
data-share-target="complex-constraint-patterns"
aria-haspopup="dialog"
aria-label="Share link: Complex Constraint Patterns">
<i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i>
<span class="visually-hidden">Share link</span>
</button>
</h3>
<h4 id="cross-property-validation" class="position-relative d-flex align-items-center group">
<span>Cross-Property Validation</span>
<button type="button"
class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1"
data-share-target="cross-property-validation"
aria-haspopup="dialog"
aria-label="Share link: Cross-Property Validation">
<i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i>
<span class="visually-hidden">Share link</span>
</button>
</h4><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-gql" data-lang="gql"><span class="line"><span class="cl"><span class="err">--</span><span class="w"> </span><span class="py">Price</span><span class="w"> </span><span class="py">consistency</span><span class="w"> </span><span class="py">across</span><span class="w"> </span><span class="py">currencies</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">CREATE</span><span class="w"> </span><span class="py">NODE</span><span class="w"> </span><span class="py">TYPE</span><span class="w"> </span><span class="py">Product</span><span class="w"> </span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">base_price_usd</span><span class="w"> </span><span class="py">DECIMAL</span><span class="w"> </span><span class="py">NOT</span><span class="w"> </span><span class="py">NULL</span><span class="w"> </span><span class="py">CHECK</span><span class="w"> </span><span class="p">(</span><span class="py">base_price_usd</span><span class="w"> </span><span class="err">></span><span class="w"> </span><span class="py">0</span><span class="p">),</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">price_eur</span><span class="w"> </span><span class="py">DECIMAL</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">price_gbp</span><span class="w"> </span><span class="py">DECIMAL</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">CONSTRAINT</span><span class="w"> </span><span class="py">currency_consistency</span><span class="w"> </span><span class="py">CHECK</span><span class="w"> </span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="p">(</span><span class="py">price_eur</span><span class="w"> </span><span class="py">IS</span><span class="w"> </span><span class="py">NULL</span><span class="w"> </span><span class="py">AND</span><span class="w"> </span><span class="py">price_gbp</span><span class="w"> </span><span class="py">IS</span><span class="w"> </span><span class="py">NULL</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">OR</span><span class="w"> </span><span class="p">(</span><span class="py">price_eur</span><span class="w"> </span><span class="err">></span><span class="w"> </span><span class="py">0</span><span class="w"> </span><span class="py">AND</span><span class="w"> </span><span class="py">price_gbp</span><span class="w"> </span><span class="err">></span><span class="w"> </span><span class="py">0</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">)</span><span class="err">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="err">--</span><span class="w"> </span><span class="py">Temporal</span><span class="w"> </span><span class="py">validity</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">CREATE</span><span class="w"> </span><span class="py">NODE</span><span class="w"> </span><span class="py">TYPE</span><span class="w"> </span><span class="py">Contract</span><span class="w"> </span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">signed_date</span><span class="w"> </span><span class="py">DATE</span><span class="w"> </span><span class="py">NOT</span><span class="w"> </span><span class="py">NULL</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">effective_date</span><span class="w"> </span><span class="py">DATE</span><span class="w"> </span><span class="py">NOT</span><span class="w"> </span><span class="py">NULL</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">expiry_date</span><span class="w"> </span><span class="py">DATE</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">CONSTRAINT</span><span class="w"> </span><span class="py">chronological_order</span><span class="w"> </span><span class="py">CHECK</span><span class="w"> </span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">effective_date</span><span class="w"> </span><span class="err">></span><span class="p">=</span><span class="w"> </span><span class="py">signed_date</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">AND</span><span class="w"> </span><span class="p">(</span><span class="py">expiry_date</span><span class="w"> </span><span class="py">IS</span><span class="w"> </span><span class="py">NULL</span><span class="w"> </span><span class="py">OR</span><span class="w"> </span><span class="py">expiry_date</span><span class="w"> </span><span class="err">></span><span class="w"> </span><span class="py">effective_date</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">)</span><span class="err">;</span><span class="w">
</span></span></span></code></pre></div>
<h4 id="graph-specific-constraints" class="position-relative d-flex align-items-center group">
<span>Graph-Specific Constraints</span>
<button type="button"
class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1"
data-share-target="graph-specific-constraints"
aria-haspopup="dialog"
aria-label="Share link: Graph-Specific Constraints">
<i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i>
<span class="visually-hidden">Share link</span>
</button>
</h4><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-gql" data-lang="gql"><span class="line"><span class="cl"><span class="err">--</span><span class="w"> </span><span class="py">Degree</span><span class="w"> </span><span class="py">constraints</span><span class="w"> </span><span class="kd">on</span><span class="w"> </span><span class="py">relationships</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">CREATE</span><span class="w"> </span><span class="py">NODE</span><span class="w"> </span><span class="py">TYPE</span><span class="w"> </span><span class="py">Person</span><span class="w"> </span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">max_connections</span><span class="w"> </span><span class="py">INTEGER</span><span class="w"> </span><span class="py">DEFAULT</span><span class="w"> </span><span class="py">5000</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">CONSTRAINT</span><span class="w"> </span><span class="py">connection_limit</span><span class="w"> </span><span class="py">CHECK</span><span class="w"> </span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="p">(</span><span class="py">SELECT</span><span class="w"> </span><span class="py">COUNT</span><span class="p">(</span><span class="err">*</span><span class="p">)</span><span class="w"> </span><span class="py">FROM</span><span class="w"> </span><span class="py">MATCH</span><span class="w"> </span><span class="p">(</span><span class="py">this</span><span class="p">)</span><span class="err">-</span><span class="p">[:</span><span class="nc">FOLLOWS</span><span class="p">]</span><span class="err">-></span><span class="p">()</span><span class="w"> </span><span class="p">)</span><span class="w"> </span><span class="err"><</span><span class="p">=</span><span class="w"> </span><span class="py">max_connections</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">)</span><span class="err">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="err">--</span><span class="w"> </span><span class="py">Path</span><span class="w"> </span><span class="py">length</span><span class="w"> </span><span class="py">constraints</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">CREATE</span><span class="w"> </span><span class="py">EDGE</span><span class="w"> </span><span class="py">TYPE</span><span class="w"> </span><span class="py">REFERENCES</span><span class="w"> </span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">depth</span><span class="w"> </span><span class="py">INTEGER</span><span class="w"> </span><span class="py">CHECK</span><span class="w"> </span><span class="p">(</span><span class="py">depth</span><span class="w"> </span><span class="err">></span><span class="p">=</span><span class="w"> </span><span class="py">0</span><span class="w"> </span><span class="py">AND</span><span class="w"> </span><span class="py">depth</span><span class="w"> </span><span class="err"><</span><span class="w"> </span><span class="py">10</span><span class="p">),</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">CONSTRAINT</span><span class="w"> </span><span class="py">no_cycles</span><span class="w"> </span><span class="py">CHECK</span><span class="w"> </span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">NOT</span><span class="w"> </span><span class="py">EXISTS</span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">MATCH</span><span class="w"> </span><span class="p">(</span><span class="py">a</span><span class="p">)</span><span class="err">-</span><span class="p">[:</span><span class="nc">REFERENCES</span><span class="err">*</span><span class="py">1</span><span class="err">.</span><span class="mf">.10</span><span class="p">]</span><span class="err">-></span><span class="p">(</span><span class="py">b</span><span class="p">)</span><span class="err">-</span><span class="p">[:</span><span class="nc">REFERENCES</span><span class="p">]</span><span class="err">-></span><span class="p">(</span><span class="py">a</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">WHERE</span><span class="w"> </span><span class="py">a</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="py">FROM_NODE</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">)</span><span class="err">;</span><span class="w">
</span></span></span></code></pre></div>
<h3 id="managing-constraints-dynamically" class="position-relative d-flex align-items-center group">
<span>Managing Constraints Dynamically</span>
<button type="button"
class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1"
data-share-target="managing-constraints-dynamically"
aria-haspopup="dialog"
aria-label="Share link: Managing Constraints Dynamically">
<i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i>
<span class="visually-hidden">Share link</span>
</button>
</h3>
<h4 id="adding-constraints-to-existing-types" class="position-relative d-flex align-items-center group">
<span>Adding Constraints to Existing Types</span>
<button type="button"
class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1"
data-share-target="adding-constraints-to-existing-types"
aria-haspopup="dialog"
aria-label="Share link: Adding Constraints to Existing Types">
<i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i>
<span class="visually-hidden">Share link</span>
</button>
</h4><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-gql" data-lang="gql"><span class="line"><span class="cl"><span class="err">--</span><span class="w"> </span><span class="py">Add</span><span class="w"> </span><span class="py">new</span><span class="w"> </span><span class="py">constraint</span><span class="w"> </span><span class="py">to</span><span class="w"> </span><span class="py">existing</span><span class="w"> </span><span class="py">node</span><span class="w"> </span><span class="kd">type</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nc">ALTER</span><span class="w"> </span><span class="py">NODE</span><span class="w"> </span><span class="py">TYPE</span><span class="w"> </span><span class="py">Person</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">ADD</span><span class="w"> </span><span class="py">CONSTRAINT</span><span class="w"> </span><span class="py">check_adult</span><span class="w"> </span><span class="py">CHECK</span><span class="w"> </span><span class="p">(</span><span class="py">age</span><span class="w"> </span><span class="err">></span><span class="p">=</span><span class="w"> </span><span class="py">18</span><span class="p">)</span><span class="err">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="err">--</span><span class="w"> </span><span class="py">Add</span><span class="w"> </span><span class="py">uniqueness</span><span class="w"> </span><span class="py">constraint</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">ALTER</span><span class="w"> </span><span class="py">NODE</span><span class="w"> </span><span class="py">TYPE</span><span class="w"> </span><span class="py">Person</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">ADD</span><span class="w"> </span><span class="py">CONSTRAINT</span><span class="w"> </span><span class="py">unique_phone</span><span class="w"> </span><span class="py">UNIQUE</span><span class="w"> </span><span class="p">(</span><span class="py">phone</span><span class="p">)</span><span class="err">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="err">--</span><span class="w"> </span><span class="py">Add</span><span class="w"> </span><span class="py">multi</span><span class="err">-</span><span class="py">column</span><span class="w"> </span><span class="py">constraint</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">ALTER</span><span class="w"> </span><span class="py">NODE</span><span class="w"> </span><span class="py">TYPE</span><span class="w"> </span><span class="py">Employee</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">ADD</span><span class="w"> </span><span class="py">CONSTRAINT</span><span class="w"> </span><span class="py">unique_dept_position</span><span class="w"> </span><span class="py">UNIQUE</span><span class="w"> </span><span class="p">(</span><span class="py">department</span><span class="p">,</span><span class="w"> </span><span class="py">position_id</span><span class="p">)</span><span class="err">;</span><span class="w">
</span></span></span></code></pre></div>
<h4 id="modifying-constraints" class="position-relative d-flex align-items-center group">
<span>Modifying Constraints</span>
<button type="button"
class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1"
data-share-target="modifying-constraints"
aria-haspopup="dialog"
aria-label="Share link: Modifying Constraints">
<i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i>
<span class="visually-hidden">Share link</span>
</button>
</h4><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-gql" data-lang="gql"><span class="line"><span class="cl"><span class="err">--</span><span class="w"> </span><span class="py">Remove</span><span class="w"> </span><span class="py">outdated</span><span class="w"> </span><span class="py">constraint</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">ALTER</span><span class="w"> </span><span class="py">NODE</span><span class="w"> </span><span class="py">TYPE</span><span class="w"> </span><span class="py">Person</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">DROP</span><span class="w"> </span><span class="py">CONSTRAINT</span><span class="w"> </span><span class="py">check_adult</span><span class="err">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="err">--</span><span class="w"> </span><span class="py">Replace</span><span class="w"> </span><span class="py">constraint</span><span class="w"> </span><span class="py">with</span><span class="w"> </span><span class="py">updated</span><span class="w"> </span><span class="py">rule</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">ALTER</span><span class="w"> </span><span class="py">NODE</span><span class="w"> </span><span class="py">TYPE</span><span class="w"> </span><span class="py">Person</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">DROP</span><span class="w"> </span><span class="py">CONSTRAINT</span><span class="w"> </span><span class="py">email_format</span><span class="err">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">ALTER</span><span class="w"> </span><span class="py">NODE</span><span class="w"> </span><span class="py">TYPE</span><span class="w"> </span><span class="py">Person</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">ADD</span><span class="w"> </span><span class="py">CONSTRAINT</span><span class="w"> </span><span class="py">email_format_v2</span><span class="w"> </span><span class="py">CHECK</span><span class="w"> </span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">email</span><span class="w"> </span><span class="err">~</span><span class="w"> </span><span class="err">'^</span><span class="p">[</span><span class="py">a</span><span class="err">-</span><span class="py">zA</span><span class="err">-</span><span class="py">Z0</span><span class="err">-</span><span class="py">9</span><span class="err">.</span><span class="py">_</span><span class="err">%+-</span><span class="p">]</span><span class="err">+@</span><span class="p">[</span><span class="py">a</span><span class="err">-</span><span class="py">zA</span><span class="err">-</span><span class="py">Z0</span><span class="err">-</span><span class="py">9</span><span class="err">.-</span><span class="p">]</span><span class="err">+\.</span><span class="p">[</span><span class="py">a</span><span class="err">-</span><span class="py">zA</span><span class="err">-</span><span class="py">Z</span><span class="p">]{</span><span class="py">2</span><span class="p">,}</span><span class="err">$'</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">)</span><span class="err">;</span><span class="w">
</span></span></span></code></pre></div>
<h4 id="bulk-operations-with-constraint-suspension" class="position-relative d-flex align-items-center group">
<span>Bulk Operations with Constraint Suspension</span>
<button type="button"
class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1"
data-share-target="bulk-operations-with-constraint-suspension"
aria-haspopup="dialog"
aria-label="Share link: Bulk Operations with Constraint Suspension">
<i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i>
<span class="visually-hidden">Share link</span>
</button>
</h4><p>For large data migrations, temporarily disable constraints:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="c1"># Python - bulk load with constraint management</span>
</span></span><span class="line"><span class="cl"><span class="k">async</span> <span class="k">def</span> <span class="nf">bulk_migrate_users</span><span class="p">(</span><span class="n">client</span><span class="p">,</span> <span class="n">user_data</span><span class="p">):</span>
</span></span><span class="line"><span class="cl"> <span class="k">async</span> <span class="k">with</span> <span class="n">client</span><span class="o">.</span><span class="n">connection</span><span class="p">()</span> <span class="k">as</span> <span class="n">tx</span><span class="p">:</span>
</span></span><span class="line"><span class="cl"> <span class="k">await</span> <span class="n">tx</span><span class="o">.</span><span class="n">begin</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"> <span class="c1"># Disable constraints for bulk operation</span>
</span></span><span class="line"><span class="cl"> <span class="k">await</span> <span class="n">tx</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="s2">"ALTER NODE TYPE Person DISABLE CONSTRAINTS"</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"> <span class="k">try</span><span class="p">:</span>
</span></span><span class="line"><span class="cl"> <span class="c1"># Bulk insert</span>
</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">batch</span> <span class="ow">in</span> <span class="n">chunked</span><span class="p">(</span><span class="n">user_data</span><span class="p">,</span> <span class="mi">1000</span><span class="p">):</span>
</span></span><span class="line"><span class="cl"> <span class="k">await</span> <span class="n">tx</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="s2">"""
</span></span></span><span class="line"><span class="cl"><span class="s2"> UNWIND $batch AS row
</span></span></span><span class="line"><span class="cl"><span class="s2"> CREATE (p:Person {
</span></span></span><span class="line"><span class="cl"><span class="s2"> id: row.id,
</span></span></span><span class="line"><span class="cl"><span class="s2"> email: row.email,
</span></span></span><span class="line"><span class="cl"><span class="s2"> age: row.age
</span></span></span><span class="line"><span class="cl"><span class="s2"> })
</span></span></span><span class="line"><span class="cl"><span class="s2"> """</span><span class="p">,</span> <span class="p">{</span><span class="s2">"batch"</span><span class="p">:</span> <span class="n">batch</span><span class="p">})</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"> <span class="c1"># Re-enable and validate</span>
</span></span><span class="line"><span class="cl"> <span class="k">await</span> <span class="n">tx</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="s2">"ALTER NODE TYPE Person ENABLE CONSTRAINTS"</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"> <span class="c1"># Check for violations</span>
</span></span><span class="line"><span class="cl"> <span class="n">violations</span><span class="p">,</span> <span class="n">_</span> <span class="o">=</span> <span class="k">await</span> <span class="n">tx</span><span class="o">.</span><span class="n">query</span><span class="p">(</span><span class="s2">"""
</span></span></span><span class="line"><span class="cl"><span class="s2"> MATCH (p:Person)
</span></span></span><span class="line"><span class="cl"><span class="s2"> WHERE p.age < 0 OR p.age > 150 OR p.email NOT LIKE '%@%.%'
</span></span></span><span class="line"><span class="cl"><span class="s2"> RETURN p.id, p.email, p.age
</span></span></span><span class="line"><span class="cl"><span class="s2"> """</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">violations</span><span class="o">.</span><span class="n">rows</span><span class="p">:</span>
</span></span><span class="line"><span class="cl"> <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Found </span><span class="si">{</span><span class="nb">len</span><span class="p">(</span><span class="n">violations</span><span class="p">)</span><span class="si">}</span><span class="s2"> constraint violations"</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"> <span class="k">await</span> <span class="n">tx</span><span class="o">.</span><span class="n">commit</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"> <span class="k">except</span> <span class="ne">Exception</span><span class="p">:</span>
</span></span><span class="line"><span class="cl"> <span class="k">await</span> <span class="n">tx</span><span class="o">.</span><span class="n">rollback</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"> <span class="k">raise</span>
</span></span></code></pre></div>
<h3 id="constraint-violation-handling" class="position-relative d-flex align-items-center group">
<span>Constraint Violation Handling</span>
<button type="button"
class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1"
data-share-target="constraint-violation-handling"
aria-haspopup="dialog"
aria-label="Share link: Constraint Violation Handling">
<i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i>
<span class="visually-hidden">Share link</span>
</button>
</h3>
<h4 id="error-responses" class="position-relative d-flex align-items-center group">
<span>Error Responses</span>
<button type="button"
class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1"
data-share-target="error-responses"
aria-haspopup="dialog"
aria-label="Share link: Error Responses">
<i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i>
<span class="visually-hidden">Share link</span>
</button>
</h4><p>Geode provides detailed error information when constraints fail:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nt">"type"</span><span class="p">:</span> <span class="s2">"ERROR"</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="nt">"code"</span><span class="p">:</span> <span class="s2">"22001"</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="nt">"message"</span><span class="p">:</span> <span class="s2">"CHECK constraint violation"</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="nt">"constraint"</span><span class="p">:</span> <span class="s2">"check_adult"</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="nt">"field"</span><span class="p">:</span> <span class="s2">"age"</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="nt">"value"</span><span class="p">:</span> <span class="mi">15</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="nt">"query"</span><span class="p">:</span> <span class="s2">"INSERT (p:Person {name: 'Bob', age: 15})"</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div>
<h4 id="client-side-error-handling" class="position-relative d-flex align-items-center group">
<span>Client-Side Error Handling</span>
<button type="button"
class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1"
data-share-target="client-side-error-handling"
aria-haspopup="dialog"
aria-label="Share link: Client-Side Error Handling">
<i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i>
<span class="visually-hidden">Share link</span>
</button>
</h4><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="c1">// Go - comprehensive constraint error handling
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kd">type</span> <span class="nx">ConstraintError</span> <span class="kd">struct</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">Constraint</span> <span class="kt">string</span>
</span></span><span class="line"><span class="cl"> <span class="nx">Field</span> <span class="kt">string</span>
</span></span><span class="line"><span class="cl"> <span class="nx">Value</span> <span class="kd">interface</span><span class="p">{}</span>
</span></span><span class="line"><span class="cl"> <span class="nx">Message</span> <span class="kt">string</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">func</span> <span class="p">(</span><span class="nx">e</span> <span class="o">*</span><span class="nx">ConstraintError</span><span class="p">)</span> <span class="nf">Error</span><span class="p">()</span> <span class="kt">string</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nx">fmt</span><span class="p">.</span><span class="nf">Sprintf</span><span class="p">(</span><span class="s">"constraint %s violated on field %s: %s"</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="nx">e</span><span class="p">.</span><span class="nx">Constraint</span><span class="p">,</span> <span class="nx">e</span><span class="p">.</span><span class="nx">Field</span><span class="p">,</span> <span class="nx">e</span><span class="p">.</span><span class="nx">Message</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">func</span> <span class="nf">parseConstraintError</span><span class="p">(</span><span class="nx">err</span> <span class="kt">error</span><span class="p">)</span> <span class="o">*</span><span class="nx">ConstraintError</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="nx">dbErr</span><span class="p">,</span> <span class="nx">ok</span> <span class="o">:=</span> <span class="nx">err</span><span class="p">.(</span><span class="o">*</span><span class="nx">geode</span><span class="p">.</span><span class="nx">Error</span><span class="p">);</span> <span class="nx">ok</span> <span class="o">&&</span> <span class="nx">dbErr</span><span class="p">.</span><span class="nx">Code</span> <span class="o">==</span> <span class="s">"22001"</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">&</span><span class="nx">ConstraintError</span><span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">Constraint</span><span class="p">:</span> <span class="nx">dbErr</span><span class="p">.</span><span class="nx">Constraint</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="nx">Field</span><span class="p">:</span> <span class="nx">dbErr</span><span class="p">.</span><span class="nx">Field</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="nx">Value</span><span class="p">:</span> <span class="nx">dbErr</span><span class="p">.</span><span class="nx">Value</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="nx">Message</span><span class="p">:</span> <span class="nx">dbErr</span><span class="p">.</span><span class="nx">Message</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="p">}</span>
</span></span><span class="line"><span class="cl"> <span class="p">}</span>
</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="kc">nil</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div>
<h3 id="performance-considerations" class="position-relative d-flex align-items-center group">
<span>Performance Considerations</span>
<button type="button"
class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1"
data-share-target="performance-considerations"
aria-haspopup="dialog"
aria-label="Share link: Performance Considerations">
<i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i>
<span class="visually-hidden">Share link</span>
</button>
</h3><p>Constraints impact write performance but improve overall system reliability:</p>
<ul>
<li><strong>NOT NULL</strong>: Minimal overhead, checked in memory</li>
<li><strong>UNIQUE</strong>: O(log n) index lookup per insert</li>
<li><strong>CHECK</strong>: Expression evaluation overhead, typically microseconds</li>
<li><strong>FOREIGN KEY</strong>: Node existence check, index lookup</li>
</ul>
<p>To optimize constraint checking:</p>
<ol>
<li><strong>Index UNIQUE Columns</strong>: Geode auto-indexes, but verify with EXPLAIN</li>
<li><strong>Simple CHECK Expressions</strong>: Avoid subqueries in CHECK constraints</li>
<li><strong>Batch Operations</strong>: Use transactions to amortize constraint checking</li>
<li><strong>Deferred Constraints</strong>: Validate at transaction commit for complex rules</li>
</ol>
<h3 id="best-practices" class="position-relative d-flex align-items-center group">
<span>Best Practices</span>
<button type="button"
class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1"
data-share-target="best-practices"
aria-haspopup="dialog"
aria-label="Share link: Best Practices">
<i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i>
<span class="visually-hidden">Share link</span>
</button>
</h3><ol>
<li><strong>Define Constraints Early</strong>: Add constraints during schema design, not as afterthoughts</li>
<li><strong>Document Business Rules</strong>: Use meaningful constraint names that explain the rule</li>
<li><strong>Test Constraint Violations</strong>: Write tests that verify constraints properly reject invalid data</li>
<li><strong>Prefer Schema Constraints</strong>: Choose schema-level constraints over application validation when possible</li>
<li><strong>Use Appropriate Types</strong>: Match constraint type to data requirement (NOT NULL vs DEFAULT)</li>
<li><strong>Version Constraints</strong>: Track constraint changes in migration scripts</li>
<li><strong>Monitor Violations</strong>: Log constraint failures to detect data quality issues</li>
<li><strong>Balance Strictness</strong>: Too many constraints can hinder legitimate operations</li>
</ol>
<h3 id="troubleshooting" class="position-relative d-flex align-items-center group">
<span>Troubleshooting</span>
<button type="button"
class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1"
data-share-target="troubleshooting"
aria-haspopup="dialog"
aria-label="Share link: Troubleshooting">
<i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i>
<span class="visually-hidden">Share link</span>
</button>
</h3><p><strong>Constraint preventing legitimate inserts</strong>: Review CHECK expressions for edge cases</p>
<p><strong>Performance degradation on writes</strong>: Analyze constraint evaluation with EXPLAIN PROFILE</p>
<p><strong>Cascade failures on deletes</strong>: Review ON DELETE policies for foreign keys</p>
<p><strong>Bulk load failures</strong>: Consider temporarily disabling constraints for validated migration</p>
<h3 id="related-topics" class="position-relative d-flex align-items-center group">
<span>Related Topics</span>
<button type="button"
class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1"
data-share-target="related-topics"
aria-haspopup="dialog"
aria-label="Share link: Related Topics">
<i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i>
<span class="visually-hidden">Share link</span>
</button>
</h3><ul>
<li><a
href="/tags/validation"
>Validation</a>
- Application-level data validation patterns</li>
<li><a
href="/tags/data-quality"
>Data Quality</a>
- Comprehensive data quality management</li>
<li><a
href="/tags/nullable"
>Nullable</a>
- NULL handling and optional fields</li>
<li><a
href="/tags/defaults"
>Defaults</a>
- Default property values</li>
<li><a
href="/tags/indexes"
>Indexes</a>
- Index management for constraint enforcement</li>
<li><a
href="/tags/transactions"
>Transactions</a>
- Constraint checking in transactional context</li>
</ul>
Tag
1 article
Schema Constraints
Enforcing data integrity rules and constraints in Geode graph schemas using GQL standard constraint types