<!-- CANARY: REQ=REQ-DOCS-001; FEATURE="Docs"; ASPECT=Documentation; STATUS=TESTED; OWNER=docs; UPDATED=2026-01-15 -->
<h2 id="database-hooks--triggers" class="position-relative d-flex align-items-center group">
<span>Database Hooks &amp; Triggers</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="database-hooks--triggers"
aria-haspopup="dialog"
aria-label="Share link: Database Hooks &amp; Triggers">
<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>Database hooks and triggers are mechanisms that automatically execute custom logic in response to specific database events. Geode’s hooks and triggers enable reactive data management, constraint enforcement, and workflow automation without requiring application-level code.</p>
<h3 id="trigger-fundamentals" class="position-relative d-flex align-items-center group">
<span>Trigger Fundamentals</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="trigger-fundamentals"
aria-haspopup="dialog"
aria-label="Share link: Trigger Fundamentals">
<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="what-are-triggers" class="position-relative d-flex align-items-center group">
<span>What are Triggers?</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="what-are-triggers"
aria-haspopup="dialog"
aria-label="Share link: What are Triggers?">
<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>Triggers are stored procedures that execute automatically when specific events occur:</p>
<p><strong>BEFORE Triggers</strong> - Execute before the operation
<strong>AFTER Triggers</strong> - Execute after the operation
<strong>INSTEAD OF Triggers</strong> - Replace the original operation</p>
<h4 id="trigger-events" class="position-relative d-flex align-items-center group">
<span>Trigger Events</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="trigger-events"
aria-haspopup="dialog"
aria-label="Share link: Trigger Events">
<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>Triggers respond to DML operations:</p>
<ul>
<li><strong>INSERT</strong> - New nodes or edges created</li>
<li><strong>UPDATE</strong> - Properties modified</li>
<li><strong>DELETE</strong> - Nodes or edges removed</li>
</ul>
<h3 id="creating-triggers" class="position-relative d-flex align-items-center group">
<span>Creating Triggers</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="creating-triggers"
aria-haspopup="dialog"
aria-label="Share link: Creating Triggers">
<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="basic-trigger-syntax" class="position-relative d-flex align-items-center group">
<span>Basic Trigger Syntax</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="basic-trigger-syntax"
aria-haspopup="dialog"
aria-label="Share link: Basic Trigger Syntax">
<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">After</span><span class="w"> </span><span class="py">insert</span><span class="w"> </span><span class="py">trigger</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">TRIGGER</span><span class="w"> </span><span class="py">audit_new_users</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">AFTER</span><span class="w"> </span><span class="py">INSERT</span><span class="w"> </span><span class="py">ON</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">FOR</span><span class="w"> </span><span class="py">EACH</span><span class="w"> </span><span class="py">ROW</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">EXECUTE</span><span class="w"> </span><span class="py">GQL</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">INSERT</span><span class="w"> </span><span class="p">(</span><span class="py">a</span><span class="p">:</span><span class="nc">AuditLog</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">action</span><span class="p">:</span><span class="w"> </span><span class="err">'</span><span class="nc">user_created</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">user_id</span><span class="p">:</span><span class="w"> </span><span class="nc">NEW</span><span class="err">.</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">timestamp</span><span class="p">:</span><span class="w"> </span><span class="nc">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">details</span><span class="p">:</span><span class="w"> </span><span class="nc">NEW</span><span class="err">.</span><span class="py">properties</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="before-update-trigger" class="position-relative d-flex align-items-center group">
<span>Before Update Trigger</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="before-update-trigger"
aria-haspopup="dialog"
aria-label="Share link: Before Update Trigger">
<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>Validate or modify data before update:</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">Prevent</span><span class="w"> </span><span class="py">negative</span><span class="w"> </span><span class="py">balance</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">TRIGGER</span><span class="w"> </span><span class="py">check_balance</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">BEFORE</span><span class="w"> </span><span class="py">UPDATE</span><span class="w"> </span><span class="py">ON</span><span class="w"> </span><span class="py">Account</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">FOR</span><span class="w"> </span><span class="py">EACH</span><span class="w"> </span><span class="py">ROW</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">WHEN</span><span class="w"> </span><span class="p">(</span><span class="py">NEW</span><span class="err">.</span><span class="py">balance</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">EXECUTE</span><span class="w"> </span><span class="py">GQL</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">SIGNAL</span><span class="w"> </span><span class="err">'</span><span class="py">Insufficient</span><span class="w"> </span><span class="py">funds</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">Auto</span><span class="err">-</span><span class="py">update</span><span class="w"> </span><span class="py">modification</span><span class="w"> </span><span class="py">time</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">TRIGGER</span><span class="w"> </span><span class="py">update_modified_time</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">BEFORE</span><span class="w"> </span><span class="py">UPDATE</span><span class="w"> </span><span class="py">ON</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">FOR</span><span class="w"> </span><span class="py">EACH</span><span class="w"> </span><span class="py">ROW</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">EXECUTE</span><span class="w"> </span><span class="py">GQL</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">SET</span><span class="w"> </span><span class="py">NEW</span><span class="err">.</span><span class="py">modified_at</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="py">NOW</span><span class="p">()</span><span class="err">;</span><span class="w">
</span></span></span></code></pre></div>
<h4 id="after-delete-trigger" class="position-relative d-flex align-items-center group">
<span>After Delete Trigger</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="after-delete-trigger"
aria-haspopup="dialog"
aria-label="Share link: After Delete Trigger">
<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>Cascade operations after deletion:</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">Archive</span><span class="w"> </span><span class="py">deleted</span><span class="w"> </span><span class="py">users</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">TRIGGER</span><span class="w"> </span><span class="py">archive_deleted_users</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">AFTER</span><span class="w"> </span><span class="py">DELETE</span><span class="w"> </span><span class="py">ON</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">FOR</span><span class="w"> </span><span class="py">EACH</span><span class="w"> </span><span class="py">ROW</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">EXECUTE</span><span class="w"> </span><span class="py">GQL</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">INSERT</span><span class="w"> </span><span class="p">(</span><span class="py">a</span><span class="p">:</span><span class="nc">ArchivedPerson</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">original_id</span><span class="p">:</span><span class="w"> </span><span class="nc">OLD</span><span class="err">.</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">data</span><span class="p">:</span><span class="w"> </span><span class="nc">OLD</span><span class="err">.</span><span class="py">properties</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">deleted_at</span><span class="p">:</span><span class="w"> </span><span class="nc">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">deleted_by</span><span class="p">:</span><span class="w"> </span><span class="nc">CURRENT_USER</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">Clean</span><span class="w"> </span><span class="py">up</span><span class="w"> </span><span class="py">orphaned</span><span class="w"> </span><span class="py">data</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">TRIGGER</span><span class="w"> </span><span class="py">cleanup_user_data</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">AFTER</span><span class="w"> </span><span class="py">DELETE</span><span class="w"> </span><span class="py">ON</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">FOR</span><span class="w"> </span><span class="py">EACH</span><span class="w"> </span><span class="py">ROW</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">EXECUTE</span><span class="w"> </span><span class="py">GQL</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">DELETE</span><span class="w"> </span><span class="py">FROM</span><span class="w"> </span><span class="py">Post</span><span class="w"> </span><span class="py">WHERE</span><span class="w"> </span><span class="py">author_id</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="py">OLD</span><span class="err">.</span><span class="py">id</span><span class="err">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">DELETE</span><span class="w"> </span><span class="py">FROM</span><span class="w"> </span><span class="py">Comment</span><span class="w"> </span><span class="py">WHERE</span><span class="w"> </span><span class="py">author_id</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="py">OLD</span><span class="err">.</span><span class="py">id</span><span class="err">;</span><span class="w">
</span></span></span></code></pre></div>
<h3 id="hook-types" class="position-relative d-flex align-items-center group">
<span>Hook 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="hook-types"
aria-haspopup="dialog"
aria-label="Share link: Hook 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="lifecycle-hooks" class="position-relative d-flex align-items-center group">
<span>Lifecycle Hooks</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="lifecycle-hooks"
aria-haspopup="dialog"
aria-label="Share link: Lifecycle Hooks">
<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>Execute at specific points in entity lifecycle:</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">Before</span><span class="w"> </span><span class="py">creation</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">HOOK</span><span class="w"> </span><span class="py">before_create_person</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">BEFORE</span><span class="w"> </span><span class="py">INSERT</span><span class="w"> </span><span class="py">ON</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">EXECUTE</span><span class="w"> </span><span class="py">FUNCTION</span><span class="w"> </span><span class="py">validate_user_data</span><span class="p">(</span><span class="py">NEW</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">After</span><span class="w"> </span><span class="py">creation</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">HOOK</span><span class="w"> </span><span class="py">after_create_person</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">AFTER</span><span class="w"> </span><span class="py">INSERT</span><span class="w"> </span><span class="py">ON</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">EXECUTE</span><span class="w"> </span><span class="py">FUNCTION</span><span class="w"> </span><span class="py">send_welcome_email</span><span class="p">(</span><span class="py">NEW</span><span class="err">.</span><span class="py">email</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">Before</span><span class="w"> </span><span class="py">update</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">HOOK</span><span class="w"> </span><span class="py">before_update_person</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">BEFORE</span><span class="w"> </span><span class="py">UPDATE</span><span class="w"> </span><span class="py">ON</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">EXECUTE</span><span class="w"> </span><span class="py">FUNCTION</span><span class="w"> </span><span class="py">validate_changes</span><span class="p">(</span><span class="py">OLD</span><span class="p">,</span><span class="w"> </span><span class="py">NEW</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">After</span><span class="w"> </span><span class="py">update</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">HOOK</span><span class="w"> </span><span class="py">after_update_person</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">AFTER</span><span class="w"> </span><span class="py">UPDATE</span><span class="w"> </span><span class="py">ON</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">EXECUTE</span><span class="w"> </span><span class="py">FUNCTION</span><span class="w"> </span><span class="py">notify_profile_change</span><span class="p">(</span><span class="py">NEW</span><span class="p">)</span><span class="err">;</span><span class="w">
</span></span></span></code></pre></div>
<h4 id="validation-hooks" class="position-relative d-flex align-items-center group">
<span>Validation Hooks</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="validation-hooks"
aria-haspopup="dialog"
aria-label="Share link: Validation Hooks">
<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>Enforce business rules:</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">Age</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">TRIGGER</span><span class="w"> </span><span class="py">validate_age</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">BEFORE</span><span class="w"> </span><span class="py">INSERT</span><span class="w"> </span><span class="py">OR</span><span class="w"> </span><span class="py">UPDATE</span><span class="w"> </span><span class="py">ON</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">FOR</span><span class="w"> </span><span class="py">EACH</span><span class="w"> </span><span class="py">ROW</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">WHEN</span><span class="w"> </span><span class="p">(</span><span class="py">NEW</span><span class="err">.</span><span class="py">age</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">OR</span><span class="w"> </span><span class="py">NEW</span><span class="err">.</span><span class="py">age</span><span class="w"> </span><span class="err">></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">EXECUTE</span><span class="w"> </span><span class="py">GQL</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">SIGNAL</span><span class="w"> </span><span class="err">'</span><span class="py">Invalid</span><span class="w"> </span><span class="py">age</span><span class="w"> </span><span class="py">value</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">Email</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">TRIGGER</span><span class="w"> </span><span class="py">ensure_unique_email</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">BEFORE</span><span class="w"> </span><span class="py">INSERT</span><span class="w"> </span><span class="py">ON</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">FOR</span><span class="w"> </span><span class="py">EACH</span><span class="w"> </span><span class="py">ROW</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">WHEN</span><span class="w"> </span><span class="py">EXISTS</span><span class="w"> </span><span class="p">(</span><span class="py">SELECT</span><span class="w"> </span><span class="py">1</span><span class="w"> </span><span class="py">FROM</span><span class="w"> </span><span class="py">Person</span><span class="w"> </span><span class="py">WHERE</span><span class="w"> </span><span class="py">email</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="py">NEW</span><span class="err">.</span><span class="py">email</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">EXECUTE</span><span class="w"> </span><span class="py">GQL</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">SIGNAL</span><span class="w"> </span><span class="err">'</span><span class="py">Email</span><span class="w"> </span><span class="py">already</span><span class="w"> </span><span class="py">in</span><span class="w"> </span><span class="py">use</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">Required</span><span class="w"> </span><span class="py">fields</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">TRIGGER</span><span class="w"> </span><span class="py">check_required_fields</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">BEFORE</span><span class="w"> </span><span class="py">INSERT</span><span class="w"> </span><span class="py">ON</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">FOR</span><span class="w"> </span><span class="py">EACH</span><span class="w"> </span><span class="py">ROW</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">WHEN</span><span class="w"> </span><span class="p">(</span><span class="py">NEW</span><span class="err">.</span><span class="py">name</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">NEW</span><span class="err">.</span><span class="py">email</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">EXECUTE</span><span class="w"> </span><span class="py">GQL</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">SIGNAL</span><span class="w"> </span><span class="err">'</span><span class="py">Required</span><span class="w"> </span><span class="py">fields</span><span class="w"> </span><span class="py">missing</span><span class="err">';</span><span class="w">
</span></span></span></code></pre></div>
<h4 id="computed-properties" class="position-relative d-flex align-items-center group">
<span>Computed Properties</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="computed-properties"
aria-haspopup="dialog"
aria-label="Share link: Computed Properties">
<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>Auto-calculate derived values:</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">Full</span><span class="w"> </span><span class="py">name</span><span class="w"> </span><span class="py">from</span><span class="w"> </span><span class="py">first</span><span class="w"> </span><span class="py">and</span><span class="w"> </span><span class="py">last</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">TRIGGER</span><span class="w"> </span><span class="py">compute_full_name</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">BEFORE</span><span class="w"> </span><span class="py">INSERT</span><span class="w"> </span><span class="py">OR</span><span class="w"> </span><span class="py">UPDATE</span><span class="w"> </span><span class="py">ON</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">FOR</span><span class="w"> </span><span class="py">EACH</span><span class="w"> </span><span class="py">ROW</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">EXECUTE</span><span class="w"> </span><span class="py">GQL</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">SET</span><span class="w"> </span><span class="py">NEW</span><span class="err">.</span><span class="py">full_name</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="py">NEW</span><span class="err">.</span><span class="py">first_name</span><span class="w"> </span><span class="p">||</span><span class="w"> </span><span class="err">'</span><span class="w"> </span><span class="err">'</span><span class="w"> </span><span class="p">||</span><span class="w"> </span><span class="py">NEW</span><span class="err">.</span><span class="py">last_name</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">Age</span><span class="w"> </span><span class="py">from</span><span class="w"> </span><span class="py">birthdate</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">TRIGGER</span><span class="w"> </span><span class="py">compute_age</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">BEFORE</span><span class="w"> </span><span class="py">INSERT</span><span class="w"> </span><span class="py">OR</span><span class="w"> </span><span class="py">UPDATE</span><span class="w"> </span><span class="py">ON</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">FOR</span><span class="w"> </span><span class="py">EACH</span><span class="w"> </span><span class="py">ROW</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">EXECUTE</span><span class="w"> </span><span class="py">GQL</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">SET</span><span class="w"> </span><span class="py">NEW</span><span class="err">.</span><span class="py">age</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="py">YEAR</span><span class="p">(</span><span class="py">NOW</span><span class="p">())</span><span class="w"> </span><span class="err">-</span><span class="w"> </span><span class="py">YEAR</span><span class="p">(</span><span class="py">NEW</span><span class="err">.</span><span class="py">birthdate</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">Order</span><span class="w"> </span><span class="py">total</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">TRIGGER</span><span class="w"> </span><span class="py">compute_order_total</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">BEFORE</span><span class="w"> </span><span class="py">INSERT</span><span class="w"> </span><span class="py">OR</span><span class="w"> </span><span class="py">UPDATE</span><span class="w"> </span><span class="py">ON</span><span class="w"> </span><span class="py">Order</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">FOR</span><span class="w"> </span><span class="py">EACH</span><span class="w"> </span><span class="py">ROW</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">EXECUTE</span><span class="w"> </span><span class="py">GQL</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">SET</span><span class="w"> </span><span class="py">NEW</span><span class="err">.</span><span class="py">total</span><span class="w"> </span><span class="p">=</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">SELECT</span><span class="w"> </span><span class="py">SUM</span><span class="p">(</span><span class="py">quantity</span><span class="w"> </span><span class="err">*</span><span class="w"> </span><span class="py">price</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</span><span class="w"> </span><span class="py">OrderItem</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">order_id</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="py">NEW</span><span class="err">.</span><span class="py">id</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="audit-logging" class="position-relative d-flex align-items-center group">
<span>Audit Logging</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="audit-logging"
aria-haspopup="dialog"
aria-label="Share link: Audit Logging">
<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>Track all data changes:</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">Comprehensive</span><span class="w"> </span><span class="py">audit</span><span class="w"> </span><span class="py">trail</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">TRIGGER</span><span class="w"> </span><span class="py">audit_all_changes</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">AFTER</span><span class="w"> </span><span class="py">INSERT</span><span class="w"> </span><span class="py">OR</span><span class="w"> </span><span class="py">UPDATE</span><span class="w"> </span><span class="py">OR</span><span class="w"> </span><span class="py">DELETE</span><span class="w"> </span><span class="py">ON</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">FOR</span><span class="w"> </span><span class="py">EACH</span><span class="w"> </span><span class="py">ROW</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">EXECUTE</span><span class="w"> </span><span class="py">GQL</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">INSERT</span><span class="w"> </span><span class="p">(</span><span class="py">log</span><span class="p">:</span><span class="nc">AuditLog</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">table_name</span><span class="p">:</span><span class="w"> </span><span class="err">'</span><span class="nc">Person</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">operation</span><span class="p">:</span><span class="w"> </span><span class="nc">CASE</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">WHEN</span><span class="w"> </span><span class="py">INSERTING</span><span class="w"> </span><span class="py">THEN</span><span class="w"> </span><span class="err">'</span><span class="py">INSERT</span><span class="err">'</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">WHEN</span><span class="w"> </span><span class="py">UPDATING</span><span class="w"> </span><span class="py">THEN</span><span class="w"> </span><span class="err">'</span><span class="py">UPDATE</span><span class="err">'</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">WHEN</span><span class="w"> </span><span class="py">DELETING</span><span class="w"> </span><span class="py">THEN</span><span class="w"> </span><span class="err">'</span><span class="py">DELETE</span><span class="err">'</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">END</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">record_id</span><span class="p">:</span><span class="w"> </span><span class="nc">COALESCE</span><span class="p">(</span><span class="py">NEW</span><span class="err">.</span><span class="py">id</span><span class="p">,</span><span class="w"> </span><span class="py">OLD</span><span class="err">.</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">old_value</span><span class="p">:</span><span class="w"> </span><span class="nc">OLD</span><span class="err">.</span><span class="py">properties</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">new_value</span><span class="p">:</span><span class="w"> </span><span class="nc">NEW</span><span class="err">.</span><span class="py">properties</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">changed_by</span><span class="p">:</span><span class="w"> </span><span class="nc">CURRENT_USER</span><span class="p">(),</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">changed_at</span><span class="p">:</span><span class="w"> </span><span class="nc">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">ip_address</span><span class="p">:</span><span class="w"> </span><span class="nc">CURRENT_IP</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="advanced-patterns" class="position-relative d-flex align-items-center group">
<span>Advanced 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="advanced-patterns"
aria-haspopup="dialog"
aria-label="Share link: Advanced 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="conditional-triggers" class="position-relative d-flex align-items-center group">
<span>Conditional Triggers</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="conditional-triggers"
aria-haspopup="dialog"
aria-label="Share link: Conditional Triggers">
<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>Execute only when conditions met:</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">Only</span><span class="w"> </span><span class="py">trigger</span><span class="w"> </span><span class="py">for</span><span class="w"> </span><span class="py">significant</span><span class="w"> </span><span class="py">changes</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">TRIGGER</span><span class="w"> </span><span class="py">notify_major_update</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">AFTER</span><span class="w"> </span><span class="py">UPDATE</span><span class="w"> </span><span class="py">ON</span><span class="w"> </span><span class="py">Account</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">FOR</span><span class="w"> </span><span class="py">EACH</span><span class="w"> </span><span class="py">ROW</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">WHEN</span><span class="w"> </span><span class="p">(</span><span class="py">ABS</span><span class="p">(</span><span class="py">NEW</span><span class="err">.</span><span class="py">balance</span><span class="w"> </span><span class="err">-</span><span class="w"> </span><span class="py">OLD</span><span class="err">.</span><span class="py">balance</span><span class="p">)</span><span class="w"> </span><span class="err">></span><span class="w"> </span><span class="py">10000</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">EXECUTE</span><span class="w"> </span><span class="py">GQL</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">INSERT</span><span class="w"> </span><span class="p">(</span><span class="py">n</span><span class="p">:</span><span class="nc">Notification</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="p">:</span><span class="w"> </span><span class="err">'</span><span class="nc">large_transaction</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="nc">account_id</span><span class="p">:</span><span class="w"> </span><span class="nc">NEW</span><span class="err">.</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">old_balance</span><span class="p">:</span><span class="w"> </span><span class="nc">OLD</span><span class="err">.</span><span class="py">balance</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">new_balance</span><span class="p">:</span><span class="w"> </span><span class="nc">NEW</span><span class="err">.</span><span class="py">balance</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">difference</span><span class="p">:</span><span class="w"> </span><span class="nc">NEW</span><span class="err">.</span><span class="py">balance</span><span class="w"> </span><span class="err">-</span><span class="w"> </span><span class="py">OLD</span><span class="err">.</span><span class="py">balance</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">timestamp</span><span class="p">:</span><span class="w"> </span><span class="nc">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">Status</span><span class="err">-</span><span class="py">based</span><span class="w"> </span><span class="py">triggers</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">TRIGGER</span><span class="w"> </span><span class="py">handle_order_completion</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">AFTER</span><span class="w"> </span><span class="py">UPDATE</span><span class="w"> </span><span class="py">ON</span><span class="w"> </span><span class="py">Order</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">FOR</span><span class="w"> </span><span class="py">EACH</span><span class="w"> </span><span class="py">ROW</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">WHEN</span><span class="w"> </span><span class="p">(</span><span class="py">OLD</span><span class="err">.</span><span class="py">status</span><span class="w"> </span><span class="p">!=</span><span class="w"> </span><span class="err">'</span><span class="py">completed</span><span class="err">'</span><span class="w"> </span><span class="py">AND</span><span class="w"> </span><span class="py">NEW</span><span class="err">.</span><span class="py">status</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="err">'</span><span class="py">completed</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">EXECUTE</span><span class="w"> </span><span class="py">GQL</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">INSERT</span><span class="w"> </span><span class="p">(</span><span class="py">e</span><span class="p">:</span><span class="nc">Event</span><span class="w"> </span><span class="p">{</span><span class="kd">type</span><span class="p">:</span><span class="w"> </span><span class="err">'</span><span class="nc">order_completed</span><span class="err">'</span><span class="p">,</span><span class="w"> </span><span class="nc">order_id</span><span class="p">:</span><span class="w"> </span><span class="nc">NEW</span><span class="err">.</span><span class="py">id</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="py">UPDATE</span><span class="w"> </span><span class="py">Customer</span><span class="w"> </span><span class="py">SET</span><span class="w"> </span><span class="py">total_orders</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="py">total_orders</span><span class="w"> </span><span class="err">+</span><span class="w"> </span><span class="py">1</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">id</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="py">NEW</span><span class="err">.</span><span class="py">customer_id</span><span class="err">;</span><span class="w">
</span></span></span></code></pre></div>
<h4 id="multi-table-triggers" class="position-relative d-flex align-items-center group">
<span>Multi-Table Triggers</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="multi-table-triggers"
aria-haspopup="dialog"
aria-label="Share link: Multi-Table Triggers">
<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>Affect multiple tables:</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">Cascade</span><span class="w"> </span><span class="py">inventory</span><span class="w"> </span><span class="py">update</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">TRIGGER</span><span class="w"> </span><span class="py">update_inventory</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">AFTER</span><span class="w"> </span><span class="py">INSERT</span><span class="w"> </span><span class="py">ON</span><span class="w"> </span><span class="py">OrderItem</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">FOR</span><span class="w"> </span><span class="py">EACH</span><span class="w"> </span><span class="py">ROW</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">EXECUTE</span><span class="w"> </span><span class="py">GQL</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">UPDATE</span><span class="w"> </span><span class="py">Product</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">SET</span><span class="w"> </span><span class="py">stock_quantity</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="py">stock_quantity</span><span class="w"> </span><span class="err">-</span><span class="w"> </span><span class="py">NEW</span><span class="err">.</span><span class="py">quantity</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">last_ordered</span><span class="w"> </span><span class="p">=</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">WHERE</span><span class="w"> </span><span class="py">id</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="py">NEW</span><span class="err">.</span><span class="py">product_id</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">INSERT</span><span class="w"> </span><span class="p">(</span><span class="py">h</span><span class="p">:</span><span class="nc">InventoryHistory</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">product_id</span><span class="p">:</span><span class="w"> </span><span class="nc">NEW</span><span class="err">.</span><span class="py">product_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">change</span><span class="p">:</span><span class="w"> </span><span class="err">-</span><span class="nc">NEW</span><span class="err">.</span><span class="py">quantity</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">reason</span><span class="p">:</span><span class="w"> </span><span class="err">'</span><span class="nc">order_placed</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">order_id</span><span class="p">:</span><span class="w"> </span><span class="nc">NEW</span><span class="err">.</span><span class="py">order_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">timestamp</span><span class="p">:</span><span class="w"> </span><span class="nc">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></code></pre></div>
<h4 id="recursive-triggers" class="position-relative d-flex align-items-center group">
<span>Recursive Triggers</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="recursive-triggers"
aria-haspopup="dialog"
aria-label="Share link: Recursive Triggers">
<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>Triggers that may trigger themselves:</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">Set</span><span class="w"> </span><span class="py">recursion</span><span class="w"> </span><span class="py">limit</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">SET</span><span class="w"> </span><span class="py">max_trigger_recursion</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="py">10</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">Hierarchical</span><span class="w"> </span><span class="py">update</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">TRIGGER</span><span class="w"> </span><span class="py">propagate_category_update</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">AFTER</span><span class="w"> </span><span class="py">UPDATE</span><span class="w"> </span><span class="py">ON</span><span class="w"> </span><span class="py">Category</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">FOR</span><span class="w"> </span><span class="py">EACH</span><span class="w"> </span><span class="py">ROW</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">EXECUTE</span><span class="w"> </span><span class="py">GQL</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">UPDATE</span><span class="w"> </span><span class="py">Category</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">SET</span><span class="w"> </span><span class="py">parent_updated_at</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="py">NEW</span><span class="err">.</span><span class="py">updated_at</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">parent_id</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="py">NEW</span><span class="err">.</span><span class="py">id</span><span class="err">;</span><span class="w">
</span></span></span></code></pre></div>
<h3 id="trigger-management" class="position-relative d-flex align-items-center group">
<span>Trigger Management</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="trigger-management"
aria-haspopup="dialog"
aria-label="Share link: Trigger Management">
<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="enablingdisabling-triggers" class="position-relative d-flex align-items-center group">
<span>Enabling/Disabling Triggers</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="enablingdisabling-triggers"
aria-haspopup="dialog"
aria-label="Share link: Enabling/Disabling Triggers">
<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>Control trigger execution:</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">Disable</span><span class="w"> </span><span class="py">trigger</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">TRIGGER</span><span class="w"> </span><span class="py">audit_new_users</span><span class="w"> </span><span class="py">DISABLE</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">Enable</span><span class="w"> </span><span class="py">trigger</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">TRIGGER</span><span class="w"> </span><span class="py">audit_new_users</span><span class="w"> </span><span class="py">ENABLE</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">Disable</span><span class="w"> </span><span class="py">all</span><span class="w"> </span><span class="py">triggers</span><span class="w"> </span><span class="kd">on</span><span class="w"> </span><span class="py">table</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">TABLE</span><span class="w"> </span><span class="py">Person</span><span class="w"> </span><span class="py">DISABLE</span><span class="w"> </span><span class="py">ALL</span><span class="w"> </span><span class="py">TRIGGERS</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">Enable</span><span class="w"> </span><span class="py">all</span><span class="w"> </span><span class="py">triggers</span><span class="w"> </span><span class="kd">on</span><span class="w"> </span><span class="py">table</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">TABLE</span><span class="w"> </span><span class="py">Person</span><span class="w"> </span><span class="py">ENABLE</span><span class="w"> </span><span class="py">ALL</span><span class="w"> </span><span class="py">TRIGGERS</span><span class="err">;</span><span class="w">
</span></span></span></code></pre></div>
<h4 id="dropping-triggers" class="position-relative d-flex align-items-center group">
<span>Dropping Triggers</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="dropping-triggers"
aria-haspopup="dialog"
aria-label="Share link: Dropping Triggers">
<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>Remove triggers:</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">Drop</span><span class="w"> </span><span class="py">specific</span><span class="w"> </span><span class="py">trigger</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">TRIGGER</span><span class="w"> </span><span class="py">IF</span><span class="w"> </span><span class="py">EXISTS</span><span class="w"> </span><span class="py">audit_new_users</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">Drop</span><span class="w"> </span><span class="py">all</span><span class="w"> </span><span class="py">triggers</span><span class="w"> </span><span class="kd">on</span><span class="w"> </span><span class="py">table</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">ALL</span><span class="w"> </span><span class="py">TRIGGERS</span><span class="w"> </span><span class="py">ON</span><span class="w"> </span><span class="py">Person</span><span class="err">;</span><span class="w">
</span></span></span></code></pre></div>
<h4 id="trigger-inspection" class="position-relative d-flex align-items-center group">
<span>Trigger Inspection</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="trigger-inspection"
aria-haspopup="dialog"
aria-label="Share link: Trigger Inspection">
<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>Query trigger metadata:</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">List</span><span class="w"> </span><span class="py">all</span><span class="w"> </span><span class="py">triggers</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">SELECT</span><span class="w"> </span><span class="py">trigger_name</span><span class="p">,</span><span class="w"> </span><span class="py">table_name</span><span class="p">,</span><span class="w"> </span><span class="py">event</span><span class="p">,</span><span class="w"> </span><span class="py">timing</span><span class="p">,</span><span class="w"> </span><span class="py">enabled</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">FROM</span><span class="w"> </span><span class="py">SYSTEM</span><span class="err">.</span><span class="py">triggers</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">Get</span><span class="w"> </span><span class="py">trigger</span><span class="w"> </span><span class="py">definition</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">SELECT</span><span class="w"> </span><span class="py">trigger_name</span><span class="p">,</span><span class="w"> </span><span class="py">definition</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">FROM</span><span class="w"> </span><span class="py">SYSTEM</span><span class="err">.</span><span class="py">triggers</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">trigger_name</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="err">'</span><span class="py">audit_new_users</span><span class="err">';</span><span class="w">
</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>
<h4 id="trigger-overhead" class="position-relative d-flex align-items-center group">
<span>Trigger Overhead</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="trigger-overhead"
aria-haspopup="dialog"
aria-label="Share link: Trigger Overhead">
<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>Minimize impact on write performance:</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">Batch</span><span class="w"> </span><span class="py">audit</span><span class="w"> </span><span class="py">logging</span><span class="w"> </span><span class="py">instead</span><span class="w"> </span><span class="py">of</span><span class="w"> </span><span class="py">per</span><span class="err">-</span><span class="py">row</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">TRIGGER</span><span class="w"> </span><span class="py">batch_audit</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">AFTER</span><span class="w"> </span><span class="py">INSERT</span><span class="w"> </span><span class="py">ON</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">FOR</span><span class="w"> </span><span class="py">EACH</span><span class="w"> </span><span class="py">STATEMENT</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">EXECUTE</span><span class="w"> </span><span class="py">GQL</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">INSERT</span><span class="w"> </span><span class="py">INTO</span><span class="w"> </span><span class="py">audit_log</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">SELECT</span><span class="w"> </span><span class="err">'</span><span class="py">INSERT</span><span class="err">'</span><span class="p">,</span><span class="w"> </span><span class="py">NEW</span><span class="err">.</span><span class="py">id</span><span class="p">,</span><span class="w"> </span><span class="py">NEW</span><span class="err">.</span><span class="py">properties</span><span class="p">,</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">FROM</span><span class="w"> </span><span class="py">NEW</span><span class="err">;</span><span class="w">
</span></span></span></code></pre></div>
<h4 id="async-triggers" class="position-relative d-flex align-items-center group">
<span>Async Triggers</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="async-triggers"
aria-haspopup="dialog"
aria-label="Share link: Async Triggers">
<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>Defer non-critical work:</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">Queue</span><span class="w"> </span><span class="py">for</span><span class="w"> </span><span class="py">async</span><span class="w"> </span><span class="py">processing</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">TRIGGER</span><span class="w"> </span><span class="py">queue_email</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">AFTER</span><span class="w"> </span><span class="py">INSERT</span><span class="w"> </span><span class="py">ON</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">FOR</span><span class="w"> </span><span class="py">EACH</span><span class="w"> </span><span class="py">ROW</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">EXECUTE</span><span class="w"> </span><span class="py">GQL</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">INSERT</span><span class="w"> </span><span class="py">INTO</span><span class="w"> </span><span class="py">email_queue</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="p">:</span><span class="w"> </span><span class="err">'</span><span class="nc">welcome</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="nc">recipient</span><span class="p">:</span><span class="w"> </span><span class="nc">NEW</span><span class="err">.</span><span class="py">email</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">data</span><span class="p">:</span><span class="w"> </span><span class="nc">NEW</span><span class="err">.</span><span class="py">properties</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">queued_at</span><span class="p">:</span><span class="w"> </span><span class="nc">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></code></pre></div>
<h4 id="trigger-ordering" class="position-relative d-flex align-items-center group">
<span>Trigger Ordering</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="trigger-ordering"
aria-haspopup="dialog"
aria-label="Share link: Trigger Ordering">
<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>Control execution order:</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">Explicit</span><span class="w"> </span><span class="py">ordering</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">TRIGGER</span><span class="w"> </span><span class="py">validate_first</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">BEFORE</span><span class="w"> </span><span class="py">INSERT</span><span class="w"> </span><span class="py">ON</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">ORDER</span><span class="w"> </span><span class="py">1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">EXECUTE</span><span class="w"> </span><span class="py">GQL</span><span class="w"> </span><span class="kd">...</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">CREATE</span><span class="w"> </span><span class="py">TRIGGER</span><span class="w"> </span><span class="py">audit_second</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">BEFORE</span><span class="w"> </span><span class="py">INSERT</span><span class="w"> </span><span class="py">ON</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">ORDER</span><span class="w"> </span><span class="py">2</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">EXECUTE</span><span class="w"> </span><span class="py">GQL</span><span class="w"> </span><span class="kd">...</span><span class="err">;</span><span class="w">
</span></span></span></code></pre></div>
<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>
<h4 id="trigger-design" class="position-relative d-flex align-items-center group">
<span>Trigger Design</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="trigger-design"
aria-haspopup="dialog"
aria-label="Share link: Trigger Design">
<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><ul>
<li>Keep triggers simple and focused</li>
<li>Avoid complex business logic</li>
<li>Document trigger purpose</li>
<li>Test thoroughly</li>
<li>Monitor performance impact</li>
</ul>
<h4 id="error-handling" class="position-relative d-flex align-items-center group">
<span>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="error-handling"
aria-haspopup="dialog"
aria-label="Share link: 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><ul>
<li>Use SIGNAL for validation errors</li>
<li>Provide meaningful error messages</li>
<li>Log errors for debugging</li>
<li>Consider compensation logic</li>
</ul>
<h4 id="security" class="position-relative d-flex align-items-center group">
<span>Security</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="security"
aria-haspopup="dialog"
aria-label="Share link: Security">
<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><ul>
<li>Validate all inputs</li>
<li>Check permissions</li>
<li>Prevent SQL injection</li>
<li>Audit trigger execution</li>
<li>Limit trigger recursion</li>
</ul>
<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/events"
>Events</a>
- Event-driven architecture</li>
<li><a
href="/tags/validation"
>Validation</a>
- Data validation</li>
<li><a
href="/tags/constraints"
>Constraints</a>
- Schema constraints</li>
</ul>
<h3 id="real-world-hook-implementations" class="position-relative d-flex align-items-center group">
<span>Real-World Hook Implementations</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="real-world-hook-implementations"
aria-haspopup="dialog"
aria-label="Share link: Real-World Hook Implementations">
<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="multi-tenancy-enforcement" class="position-relative d-flex align-items-center group">
<span>Multi-Tenancy Enforcement</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="multi-tenancy-enforcement"
aria-haspopup="dialog"
aria-label="Share link: Multi-Tenancy Enforcement">
<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>Automatically add tenant context to all data:</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">Inject</span><span class="w"> </span><span class="py">tenant_id</span><span class="w"> </span><span class="kd">on</span><span class="w"> </span><span class="py">all</span><span class="w"> </span><span class="py">creates</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">TRIGGER</span><span class="w"> </span><span class="py">enforce_tenancy</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">BEFORE</span><span class="w"> </span><span class="py">INSERT</span><span class="w"> </span><span class="py">ON</span><span class="w"> </span><span class="py">Person</span><span class="p">,</span><span class="w"> </span><span class="py">Company</span><span class="p">,</span><span class="w"> </span><span class="py">Product</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">FOR</span><span class="w"> </span><span class="py">EACH</span><span class="w"> </span><span class="py">ROW</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">EXECUTE</span><span class="w"> </span><span class="py">GQL</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">SET</span><span class="w"> </span><span class="py">NEW</span><span class="err">.</span><span class="py">tenant_id</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="py">CURRENT_TENANT_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">NEW</span><span class="err">.</span><span class="py">created_by</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="py">CURRENT_USER</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">Prevent</span><span class="w"> </span><span class="py">cross</span><span class="err">-</span><span class="py">tenant</span><span class="w"> </span><span class="py">access</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">TRIGGER</span><span class="w"> </span><span class="py">validate_tenant_access</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">BEFORE</span><span class="w"> </span><span class="py">UPDATE</span><span class="w"> </span><span class="py">OR</span><span class="w"> </span><span class="py">DELETE</span><span class="w"> </span><span class="py">ON</span><span class="w"> </span><span class="py">Person</span><span class="p">,</span><span class="w"> </span><span class="py">Company</span><span class="p">,</span><span class="w"> </span><span class="py">Product</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">FOR</span><span class="w"> </span><span class="py">EACH</span><span class="w"> </span><span class="py">ROW</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">WHEN</span><span class="w"> </span><span class="p">(</span><span class="py">OLD</span><span class="err">.</span><span class="py">tenant_id</span><span class="w"> </span><span class="p">!=</span><span class="w"> </span><span class="py">CURRENT_TENANT_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">EXECUTE</span><span class="w"> </span><span class="py">GQL</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">SIGNAL</span><span class="w"> </span><span class="err">'</span><span class="py">Access</span><span class="w"> </span><span class="py">denied</span><span class="p">:</span><span class="w"> </span><span class="nc">cross</span><span class="err">-</span><span class="py">tenant</span><span class="w"> </span><span class="py">operation</span><span class="w"> </span><span class="py">not</span><span class="w"> </span><span class="py">allowed</span><span class="err">';</span><span class="w">
</span></span></span></code></pre></div>
<h4 id="data-retention-policy" class="position-relative d-flex align-items-center group">
<span>Data Retention Policy</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="data-retention-policy"
aria-haspopup="dialog"
aria-label="Share link: Data Retention Policy">
<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>Automatically archive or delete old data:</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">Archive</span><span class="w"> </span><span class="py">records</span><span class="w"> </span><span class="py">older</span><span class="w"> </span><span class="py">than</span><span class="w"> </span><span class="py">7</span><span class="w"> </span><span class="py">years</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">TRIGGER</span><span class="w"> </span><span class="py">enforce_retention_policy</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">AFTER</span><span class="w"> </span><span class="py">UPDATE</span><span class="w"> </span><span class="py">ON</span><span class="w"> </span><span class="py">Event</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">FOR</span><span class="w"> </span><span class="py">EACH</span><span class="w"> </span><span class="py">ROW</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">WHEN</span><span class="w"> </span><span class="p">(</span><span class="py">NEW</span><span class="err">.</span><span class="py">timestamp</span><span class="w"> </span><span class="err"><</span><span class="w"> </span><span class="py">datetime</span><span class="p">()</span><span class="err">.</span><span class="py">minusYears</span><span class="p">(</span><span class="py">7</span><span class="p">))</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">EXECUTE</span><span class="w"> </span><span class="py">GQL</span><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">Move</span><span class="w"> </span><span class="py">to</span><span class="w"> </span><span class="py">archive</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="p">(</span><span class="py">a</span><span class="p">:</span><span class="nc">ArchivedEvent</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">original_id</span><span class="p">:</span><span class="w"> </span><span class="nc">NEW</span><span class="err">.</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">data</span><span class="p">:</span><span class="w"> </span><span class="nc">NEW</span><span class="err">.</span><span class="py">properties</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">archived_at</span><span class="p">:</span><span class="w"> </span><span class="nc">datetime</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">IN</span><span class="w"> </span><span class="py">GRAPH</span><span class="w"> </span><span class="py">archive_db</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">Delete</span><span class="w"> </span><span class="py">from</span><span class="w"> </span><span class="py">active</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">DELETE</span><span class="w"> </span><span class="py">NEW</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">Schedule</span><span class="w"> </span><span class="py">periodic</span><span class="w"> </span><span class="py">retention</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">SCHEDULED</span><span class="w"> </span><span class="py">TRIGGER</span><span class="w"> </span><span class="py">retention_cleanup</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">EVERY</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="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">EXECUTE</span><span class="w"> </span><span class="py">GQL</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">e</span><span class="p">:</span><span class="nc">Event</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">e</span><span class="err">.</span><span class="py">timestamp</span><span class="w"> </span><span class="err"><</span><span class="w"> </span><span class="py">datetime</span><span class="p">()</span><span class="err">.</span><span class="py">minusYears</span><span class="p">(</span><span class="py">7</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">WITH</span><span class="w"> </span><span class="py">e</span><span class="w"> </span><span class="py">LIMIT</span><span class="w"> </span><span class="py">1000</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">DELETE</span><span class="w"> </span><span class="py">e</span><span class="err">;</span><span class="w">
</span></span></span></code></pre></div>
<h4 id="bi-directional-relationship-sync" class="position-relative d-flex align-items-center group">
<span>Bi-Directional Relationship Sync</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="bi-directional-relationship-sync"
aria-haspopup="dialog"
aria-label="Share link: Bi-Directional Relationship Sync">
<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>Maintain symmetric relationships:</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">When</span><span class="w"> </span><span class="py">A</span><span class="w"> </span><span class="py">friends</span><span class="w"> </span><span class="py">B</span><span class="p">,</span><span class="w"> </span><span class="py">also</span><span class="w"> </span><span class="py">create</span><span class="w"> </span><span class="py">B</span><span class="w"> </span><span class="py">friends</span><span class="w"> </span><span class="py">A</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">TRIGGER</span><span class="w"> </span><span class="py">bidirectional_friendship</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">AFTER</span><span class="w"> </span><span class="py">INSERT</span><span class="w"> </span><span class="py">ON</span><span class="w"> </span><span class="p">[:</span><span class="nc">FRIEND</span><span class="p">]</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">FOR</span><span class="w"> </span><span class="py">EACH</span><span class="w"> </span><span class="py">RELATIONSHIP</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">WHEN</span><span class="w"> </span><span class="py">NOT</span><span class="w"> </span><span class="py">EXISTS</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">MATCH</span><span class="w"> </span><span class="p">(</span><span class="py">target</span><span class="p">)</span><span class="err">-</span><span class="p">[:</span><span class="nc">FRIEND</span><span class="p">]</span><span class="err">-></span><span class="p">(</span><span class="py">source</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">source</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="py">startNode</span><span class="p">(</span><span class="py">NEW</span><span class="p">)</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="py">target</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="py">endNode</span><span class="p">(</span><span class="py">NEW</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">EXECUTE</span><span class="w"> </span><span class="py">GQL</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="w"> </span><span class="p">(</span><span class="py">b</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">id</span><span class="p">(</span><span class="py">a</span><span class="p">)</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="py">id</span><span class="p">(</span><span class="py">startNode</span><span class="p">(</span><span class="py">NEW</span><span class="p">))</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="py">id</span><span class="p">(</span><span class="py">b</span><span class="p">)</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="py">id</span><span class="p">(</span><span class="py">endNode</span><span class="p">(</span><span class="py">NEW</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="p">(</span><span class="py">b</span><span class="p">)</span><span class="err">-</span><span class="p">[:</span><span class="nc">FRIEND</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">created_at</span><span class="p">:</span><span class="w"> </span><span class="nc">NEW</span><span class="err">.</span><span class="py">created_at</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">bidirectional</span><span class="p">:</span><span class="w"> </span><span class="nc">true</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="p">(</span><span class="py">a</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">When</span><span class="w"> </span><span class="py">A</span><span class="w"> </span><span class="py">unfriends</span><span class="w"> </span><span class="py">B</span><span class="p">,</span><span class="w"> </span><span class="py">also</span><span class="w"> </span><span class="py">remove</span><span class="w"> </span><span class="py">B</span><span class="w"> </span><span class="py">friends</span><span class="w"> </span><span class="py">A</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">TRIGGER</span><span class="w"> </span><span class="py">bidirectional_unfriend</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">AFTER</span><span class="w"> </span><span class="py">DELETE</span><span class="w"> </span><span class="py">ON</span><span class="w"> </span><span class="p">[:</span><span class="nc">FRIEND</span><span class="p">]</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">FOR</span><span class="w"> </span><span class="py">EACH</span><span class="w"> </span><span class="py">RELATIONSHIP</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">EXECUTE</span><span class="w"> </span><span class="py">GQL</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">target</span><span class="p">)</span><span class="err">-</span><span class="p">[</span><span class="py">r</span><span class="p">:</span><span class="nc">FRIEND</span><span class="p">]</span><span class="err">-></span><span class="p">(</span><span class="py">source</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">source</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="py">startNode</span><span class="p">(</span><span class="py">OLD</span><span class="p">)</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="py">target</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="py">endNode</span><span class="p">(</span><span class="py">OLD</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">DELETE</span><span class="w"> </span><span class="py">r</span><span class="err">;</span><span class="w">
</span></span></span></code></pre></div>
<h4 id="denormalization-maintenance" class="position-relative d-flex align-items-center group">
<span>Denormalization Maintenance</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="denormalization-maintenance"
aria-haspopup="dialog"
aria-label="Share link: Denormalization Maintenance">
<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>Keep denormalized data in sync:</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">Update</span><span class="w"> </span><span class="py">user</span><span class="err">'</span><span class="py">s</span><span class="w"> </span><span class="py">post</span><span class="w"> </span><span class="py">count</span><span class="w"> </span><span class="py">when</span><span class="w"> </span><span class="py">posts</span><span class="w"> </span><span class="py">created</span><span class="err">/</span><span class="py">deleted</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">TRIGGER</span><span class="w"> </span><span class="py">maintain_post_count</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">AFTER</span><span class="w"> </span><span class="py">INSERT</span><span class="w"> </span><span class="py">OR</span><span class="w"> </span><span class="py">DELETE</span><span class="w"> </span><span class="py">ON</span><span class="w"> </span><span class="py">Post</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">FOR</span><span class="w"> </span><span class="py">EACH</span><span class="w"> </span><span class="py">ROW</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">EXECUTE</span><span class="w"> </span><span class="py">GQL</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">u</span><span class="p">:</span><span class="nc">User</span><span class="w"> </span><span class="p">{</span><span class="py">id</span><span class="p">:</span><span class="w"> </span><span class="nc">COALESCE</span><span class="p">(</span><span class="py">NEW</span><span class="err">.</span><span class="py">author_id</span><span class="p">,</span><span class="w"> </span><span class="py">OLD</span><span class="err">.</span><span class="py">author_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">WITH</span><span class="w"> </span><span class="py">u</span><span class="p">,</span><span class="w"> </span><span class="py">CASE</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">WHEN</span><span class="w"> </span><span class="py">INSERTING</span><span class="w"> </span><span class="py">THEN</span><span class="w"> </span><span class="py">1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">WHEN</span><span class="w"> </span><span class="py">DELETING</span><span class="w"> </span><span class="py">THEN</span><span class="w"> </span><span class="err">-</span><span class="py">1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">END</span><span class="w"> </span><span class="py">AS</span><span class="w"> </span><span class="py">delta</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">SET</span><span class="w"> </span><span class="py">u</span><span class="err">.</span><span class="py">post_count</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="py">u</span><span class="err">.</span><span class="py">post_count</span><span class="w"> </span><span class="err">+</span><span class="w"> </span><span class="py">delta</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">u</span><span class="err">.</span><span class="py">last_post_at</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="py">CASE</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">WHEN</span><span class="w"> </span><span class="py">INSERTING</span><span class="w"> </span><span class="py">THEN</span><span class="w"> </span><span class="py">datetime</span><span class="p">()</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">ELSE</span><span class="w"> </span><span class="py">u</span><span class="err">.</span><span class="py">last_post_at</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">END</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">Maintain</span><span class="w"> </span><span class="py">aggregated</span><span class="w"> </span><span class="py">statistics</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">TRIGGER</span><span class="w"> </span><span class="py">update_category_stats</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">AFTER</span><span class="w"> </span><span class="py">INSERT</span><span class="w"> </span><span class="py">OR</span><span class="w"> </span><span class="py">UPDATE</span><span class="w"> </span><span class="py">OR</span><span class="w"> </span><span class="py">DELETE</span><span class="w"> </span><span class="py">ON</span><span class="w"> </span><span class="py">Product</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">FOR</span><span class="w"> </span><span class="py">EACH</span><span class="w"> </span><span class="py">ROW</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">EXECUTE</span><span class="w"> </span><span class="py">GQL</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">c</span><span class="p">:</span><span class="nc">Category</span><span class="w"> </span><span class="p">{</span><span class="py">id</span><span class="p">:</span><span class="w"> </span><span class="nc">COALESCE</span><span class="p">(</span><span class="py">NEW</span><span class="err">.</span><span class="py">category_id</span><span class="p">,</span><span class="w"> </span><span class="py">OLD</span><span class="err">.</span><span class="py">category_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">WITH</span><span class="w"> </span><span class="py">c</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">COUNT</span><span class="p">{(</span><span class="py">c</span><span class="p">)</span><span class="err"><-</span><span class="p">[:</span><span class="nc">IN_CATEGORY</span><span class="p">]</span><span class="err">-</span><span class="p">(</span><span class="py">p</span><span class="p">:</span><span class="nc">Product</span><span class="p">)}</span><span class="w"> </span><span class="py">AS</span><span class="w"> </span><span class="py">product_count</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">AVG</span><span class="p">{(</span><span class="py">c</span><span class="p">)</span><span class="err"><-</span><span class="p">[:</span><span class="nc">IN_CATEGORY</span><span class="p">]</span><span class="err">-</span><span class="p">(</span><span class="py">p</span><span class="p">:</span><span class="nc">Product</span><span class="p">)</span><span class="w"> </span><span class="p">|</span><span class="w"> </span><span class="py">p</span><span class="err">.</span><span class="py">price</span><span class="p">}</span><span class="w"> </span><span class="py">AS</span><span class="w"> </span><span class="py">avg_price</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">SET</span><span class="w"> </span><span class="py">c</span><span class="err">.</span><span class="py">product_count</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="py">product_count</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">c</span><span class="err">.</span><span class="py">average_price</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="py">avg_price</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">c</span><span class="err">.</span><span class="py">last_updated</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="py">datetime</span><span class="p">()</span><span class="err">;</span><span class="w">
</span></span></span></code></pre></div>
<h4 id="soft-delete-implementation" class="position-relative d-flex align-items-center group">
<span>Soft Delete Implementation</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="soft-delete-implementation"
aria-haspopup="dialog"
aria-label="Share link: Soft Delete Implementation">
<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>Mark records as deleted instead of removing them:</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">Intercept</span><span class="w"> </span><span class="py">deletes</span><span class="w"> </span><span class="py">and</span><span class="w"> </span><span class="py">convert</span><span class="w"> </span><span class="py">to</span><span class="w"> </span><span class="py">soft</span><span class="w"> </span><span class="py">delete</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">TRIGGER</span><span class="w"> </span><span class="py">soft_delete_user</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">INSTEAD</span><span class="w"> </span><span class="py">OF</span><span class="w"> </span><span class="py">DELETE</span><span class="w"> </span><span class="py">ON</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">FOR</span><span class="w"> </span><span class="py">EACH</span><span class="w"> </span><span class="py">ROW</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">EXECUTE</span><span class="w"> </span><span class="py">GQL</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">p</span><span class="p">:</span><span class="nc">Person</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">id</span><span class="p">(</span><span class="py">p</span><span class="p">)</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="py">id</span><span class="p">(</span><span class="py">OLD</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">SET</span><span class="w"> </span><span class="py">p</span><span class="err">.</span><span class="py">deleted_at</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="py">datetime</span><span class="p">(),</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">p</span><span class="err">.</span><span class="py">deleted_by</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="py">CURRENT_USER</span><span class="p">(),</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">p</span><span class="err">.</span><span class="py">status</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="err">'</span><span class="py">deleted</span><span class="err">'</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">REMOVE</span><span class="w"> </span><span class="py">p</span><span class="p">:</span><span class="nc">Active</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">SET</span><span class="w"> </span><span class="py">p</span><span class="p">:</span><span class="nc">Deleted</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">Hide</span><span class="w"> </span><span class="py">soft</span><span class="err">-</span><span class="py">deleted</span><span class="w"> </span><span class="py">records</span><span class="w"> </span><span class="py">from</span><span class="w"> </span><span class="py">normal</span><span class="w"> </span><span class="py">queries</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">VIEW</span><span class="w"> </span><span class="py">ActivePersons</span><span class="w"> </span><span class="py">AS</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">p</span><span class="p">:</span><span class="nc">Person</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">p</span><span class="err">.</span><span class="py">deleted_at</span><span class="w"> </span><span class="py">IS</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">RETURN</span><span class="w"> </span><span class="py">p</span><span class="err">;</span><span class="w">
</span></span></span></code></pre></div>
<h3 id="hook-performance-optimization" class="position-relative d-flex align-items-center group">
<span>Hook Performance Optimization</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="hook-performance-optimization"
aria-haspopup="dialog"
aria-label="Share link: Hook Performance Optimization">
<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="conditional-execution" class="position-relative d-flex align-items-center group">
<span>Conditional Execution</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="conditional-execution"
aria-haspopup="dialog"
aria-label="Share link: Conditional Execution">
<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>Minimize trigger overhead:</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">Only</span><span class="w"> </span><span class="py">execute</span><span class="w"> </span><span class="py">for</span><span class="w"> </span><span class="py">significant</span><span class="w"> </span><span class="py">changes</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">TRIGGER</span><span class="w"> </span><span class="py">notify_price_change</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">AFTER</span><span class="w"> </span><span class="py">UPDATE</span><span class="w"> </span><span class="py">ON</span><span class="w"> </span><span class="py">Product</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">FOR</span><span class="w"> </span><span class="py">EACH</span><span class="w"> </span><span class="py">ROW</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">WHEN</span><span class="w"> </span><span class="p">(</span><span class="py">ABS</span><span class="p">(</span><span class="py">NEW</span><span class="err">.</span><span class="py">price</span><span class="w"> </span><span class="err">-</span><span class="w"> </span><span class="py">OLD</span><span class="err">.</span><span class="py">price</span><span class="p">)</span><span class="w"> </span><span class="err">/</span><span class="w"> </span><span class="py">OLD</span><span class="err">.</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="mf">.1</span><span class="p">)</span><span class="w"> </span><span class="err">--</span><span class="w"> </span><span class="err">></span><span class="py">10</span><span class="err">%</span><span class="w"> </span><span class="py">change</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">EXECUTE</span><span class="w"> </span><span class="py">GQL</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="p">(</span><span class="py">n</span><span class="p">:</span><span class="nc">PriceChangeNotification</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">product_id</span><span class="p">:</span><span class="w"> </span><span class="nc">NEW</span><span class="err">.</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">old_price</span><span class="p">:</span><span class="w"> </span><span class="nc">OLD</span><span class="err">.</span><span class="py">price</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">new_price</span><span class="p">:</span><span class="w"> </span><span class="nc">NEW</span><span class="err">.</span><span class="py">price</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">change_percent</span><span class="p">:</span><span class="w"> </span><span class="p">(</span><span class="nc">NEW</span><span class="err">.</span><span class="py">price</span><span class="w"> </span><span class="err">-</span><span class="w"> </span><span class="py">OLD</span><span class="err">.</span><span class="py">price</span><span class="p">)</span><span class="w"> </span><span class="err">/</span><span class="w"> </span><span class="py">OLD</span><span class="err">.</span><span class="py">price</span><span class="w"> </span><span class="err">*</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="py">timestamp</span><span class="p">:</span><span class="w"> </span><span class="nc">datetime</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="batching-hook-actions" class="position-relative d-flex align-items-center group">
<span>Batching Hook Actions</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="batching-hook-actions"
aria-haspopup="dialog"
aria-label="Share link: Batching Hook Actions">
<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>Process multiple rows efficiently:</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">Per</span><span class="err">-</span><span class="py">statement</span><span class="w"> </span><span class="py">trigger</span><span class="w"> </span><span class="p">(</span><span class="py">not</span><span class="w"> </span><span class="py">per</span><span class="err">-</span><span class="py">row</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">TRIGGER</span><span class="w"> </span><span class="py">batch_audit_inserts</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">AFTER</span><span class="w"> </span><span class="py">INSERT</span><span class="w"> </span><span class="py">ON</span><span class="w"> </span><span class="py">User</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">FOR</span><span class="w"> </span><span class="py">EACH</span><span class="w"> </span><span class="py">STATEMENT</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">EXECUTE</span><span class="w"> </span><span class="py">GQL</span><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">NEW</span><span class="w"> </span><span class="py">represents</span><span class="w"> </span><span class="py">all</span><span class="w"> </span><span class="py">inserted</span><span class="w"> </span><span class="py">rows</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">WITH</span><span class="w"> </span><span class="py">NEW</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">UNWIND</span><span class="w"> </span><span class="py">NEW</span><span class="w"> </span><span class="py">AS</span><span class="w"> </span><span class="py">user</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="p">(</span><span class="py">a</span><span class="p">:</span><span class="nc">AuditLog</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">action</span><span class="p">:</span><span class="w"> </span><span class="err">'</span><span class="nc">user_created</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">user_ids</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="nc">u</span><span class="w"> </span><span class="py">IN</span><span class="w"> </span><span class="py">NEW</span><span class="w"> </span><span class="p">|</span><span class="w"> </span><span class="py">u</span><span class="err">.</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">count</span><span class="p">:</span><span class="w"> </span><span class="nc">SIZE</span><span class="p">(</span><span class="py">NEW</span><span class="p">),</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">timestamp</span><span class="p">:</span><span class="w"> </span><span class="nc">datetime</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="async-hook-execution" class="position-relative d-flex align-items-center group">
<span>Async Hook Execution</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="async-hook-execution"
aria-haspopup="dialog"
aria-label="Share link: Async Hook Execution">
<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>Defer non-critical work:</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">Queue</span><span class="w"> </span><span class="py">for</span><span class="w"> </span><span class="py">async</span><span class="w"> </span><span class="py">processing</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">TRIGGER</span><span class="w"> </span><span class="py">queue_welcome_email</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">AFTER</span><span class="w"> </span><span class="py">INSERT</span><span class="w"> </span><span class="py">ON</span><span class="w"> </span><span class="py">User</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">FOR</span><span class="w"> </span><span class="py">EACH</span><span class="w"> </span><span class="py">ROW</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">EXECUTE</span><span class="w"> </span><span class="py">GQL</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="p">(</span><span class="py">job</span><span class="p">:</span><span class="nc">AsyncJob</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="p">:</span><span class="w"> </span><span class="err">'</span><span class="nc">send_welcome_email</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="nc">user_id</span><span class="p">:</span><span class="w"> </span><span class="nc">NEW</span><span class="err">.</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">user_email</span><span class="p">:</span><span class="w"> </span><span class="nc">NEW</span><span class="err">.</span><span class="py">email</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">queued_at</span><span class="p">:</span><span class="w"> </span><span class="nc">datetime</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="p">:</span><span class="w"> </span><span class="err">'</span><span class="nc">pending</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><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">Background</span><span class="w"> </span><span class="py">worker</span><span class="w"> </span><span class="py">processes</span><span class="w"> </span><span class="py">jobs</span><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="p">(</span><span class="py">separate</span><span class="w"> </span><span class="py">process</span><span class="p">,</span><span class="w"> </span><span class="py">no</span><span class="w"> </span><span class="py">blocking</span><span class="w"> </span><span class="kd">on</span><span class="w"> </span><span class="py">insert</span><span class="p">)</span><span class="w">
</span></span></span></code></pre></div>
<h3 id="hook-testing-strategies" class="position-relative d-flex align-items-center group">
<span>Hook Testing Strategies</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="hook-testing-strategies"
aria-haspopup="dialog"
aria-label="Share link: Hook Testing Strategies">
<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="unit-testing-hooks" class="position-relative d-flex align-items-center group">
<span>Unit Testing Hooks</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="unit-testing-hooks"
aria-haspopup="dialog"
aria-label="Share link: Unit Testing Hooks">
<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>Test trigger logic in isolation:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">pytest</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></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nd">@pytest.fixture</span>
</span></span><span class="line"><span class="cl"><span class="k">async</span> <span class="k">def</span> <span class="nf">client</span><span class="p">():</span>
</span></span><span class="line"><span class="cl"> <span class="n">client</span> <span class="o">=</span> <span class="k">await</span> <span class="n">Client</span><span class="o">.</span><span class="n">connect</span><span class="p">(</span><span class="s2">"localhost:3141"</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"> <span class="k">yield</span> <span class="n">client</span>
</span></span><span class="line"><span class="cl"> <span class="k">await</span> <span class="n">client</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nd">@pytest.mark.asyncio</span>
</span></span><span class="line"><span class="cl"><span class="k">async</span> <span class="k">def</span> <span class="nf">test_audit_trigger</span><span class="p">(</span><span class="n">client</span><span class="p">):</span>
</span></span><span class="line"><span class="cl"> <span class="s2">"""Test audit log trigger creates entries"""</span>
</span></span><span class="line"><span class="cl"> <span class="c1"># Insert user (triggers audit hook)</span>
</span></span><span class="line"><span class="cl"> <span class="k">await</span> <span class="n">client</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"> CREATE (:User {id: 123, name: 'Test User', email: '[email protected]'})
</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="c1"># Verify audit log created</span>
</span></span><span class="line"><span class="cl"> <span class="n">result</span><span class="p">,</span> <span class="n">_</span> <span class="o">=</span> <span class="k">await</span> <span class="n">client</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 (a:AuditLog)
</span></span></span><span class="line"><span class="cl"><span class="s2"> WHERE a.action = 'user_created'
</span></span></span><span class="line"><span class="cl"><span class="s2"> AND a.record_id = 123
</span></span></span><span class="line"><span class="cl"><span class="s2"> RETURN a
</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">assert</span> <span class="nb">len</span><span class="p">(</span><span class="n">result</span><span class="o">.</span><span class="n">bindings</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span>
</span></span><span class="line"><span class="cl"> <span class="n">audit</span> <span class="o">=</span> <span class="n">result</span><span class="o">.</span><span class="n">bindings</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="s1">'a'</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"> <span class="k">assert</span> <span class="n">audit</span><span class="p">[</span><span class="s1">'action'</span><span class="p">]</span> <span class="o">==</span> <span class="s1">'user_created'</span>
</span></span><span class="line"><span class="cl"> <span class="k">assert</span> <span class="s1">'[email protected]'</span> <span class="ow">in</span> <span class="n">audit</span><span class="p">[</span><span class="s1">'details'</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nd">@pytest.mark.asyncio</span>
</span></span><span class="line"><span class="cl"><span class="k">async</span> <span class="k">def</span> <span class="nf">test_validation_trigger</span><span class="p">(</span><span class="n">client</span><span class="p">):</span>
</span></span><span class="line"><span class="cl"> <span class="s2">"""Test validation trigger rejects invalid data"""</span>
</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="n">pytest</span><span class="o">.</span><span class="n">raises</span><span class="p">(</span><span class="ne">Exception</span><span class="p">,</span> <span class="k">match</span><span class="o">=</span><span class="s2">"Invalid age value"</span><span class="p">):</span>
</span></span><span class="line"><span class="cl"> <span class="k">await</span> <span class="n">client</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"> CREATE (:Person {id: 456, name: 'Invalid', age: -5})
</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="c1"># Verify no record created</span>
</span></span><span class="line"><span class="cl"> <span class="n">result</span><span class="p">,</span> <span class="n">_</span> <span class="o">=</span> <span class="k">await</span> <span class="n">client</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 class="si">{id: 456}</span><span class="s2">) RETURN p
</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 class="k">assert</span> <span class="nb">len</span><span class="p">(</span><span class="n">result</span><span class="o">.</span><span class="n">bindings</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span>
</span></span></code></pre></div>
<h4 id="integration-testing" class="position-relative d-flex align-items-center group">
<span>Integration Testing</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="integration-testing"
aria-haspopup="dialog"
aria-label="Share link: Integration Testing">
<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>Test hooks with full workflows:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="nd">@pytest.mark.asyncio</span>
</span></span><span class="line"><span class="cl"><span class="k">async</span> <span class="k">def</span> <span class="nf">test_bidirectional_friendship</span><span class="p">(</span><span class="n">client</span><span class="p">):</span>
</span></span><span class="line"><span class="cl"> <span class="s2">"""Test bidirectional friendship trigger"""</span>
</span></span><span class="line"><span class="cl"> <span class="c1"># Create users</span>
</span></span><span class="line"><span class="cl"> <span class="k">await</span> <span class="n">client</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"> CREATE (:User {id: 1, name: 'Alice'})
</span></span></span><span class="line"><span class="cl"><span class="s2"> CREATE (:User {id: 2, name: 'Bob'})
</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="c1"># Create friendship (triggers bidirectional hook)</span>
</span></span><span class="line"><span class="cl"> <span class="k">await</span> <span class="n">client</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"> MATCH (a:User </span><span class="si">{id: 1}</span><span class="s2">), (b:User </span><span class="si">{id: 2}</span><span class="s2">)
</span></span></span><span class="line"><span class="cl"><span class="s2"> CREATE (a)-[:FRIEND {created_at: datetime()}]->(b)
</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="c1"># Verify both directions exist</span>
</span></span><span class="line"><span class="cl"> <span class="n">result</span><span class="p">,</span> <span class="n">_</span> <span class="o">=</span> <span class="k">await</span> <span class="n">client</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 (a:User </span><span class="si">{id: 1}</span><span class="s2">)-[:FRIEND]->(b:User </span><span class="si">{id: 2}</span><span class="s2">),
</span></span></span><span class="line"><span class="cl"><span class="s2"> (b)-[:FRIEND]->(a)
</span></span></span><span class="line"><span class="cl"><span class="s2"> RETURN a.name, b.name
</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">assert</span> <span class="nb">len</span><span class="p">(</span><span class="n">result</span><span class="o">.</span><span class="n">bindings</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span>
</span></span></code></pre></div>
<h3 id="debugging-hooks" class="position-relative d-flex align-items-center group">
<span>Debugging Hooks</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="debugging-hooks"
aria-haspopup="dialog"
aria-label="Share link: Debugging Hooks">
<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="trigger-execution-log" class="position-relative d-flex align-items-center group">
<span>Trigger Execution Log</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="trigger-execution-log"
aria-haspopup="dialog"
aria-label="Share link: Trigger Execution Log">
<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>Track trigger executions:</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">Enable</span><span class="w"> </span><span class="py">trigger</span><span class="w"> </span><span class="py">logging</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">SET</span><span class="w"> </span><span class="py">trigger_logging</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="py">true</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">Execute</span><span class="w"> </span><span class="py">operation</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="p">(:</span><span class="nc">User</span><span class="w"> </span><span class="p">{</span><span class="py">id</span><span class="p">:</span><span class="w"> </span><span class="nc">789</span><span class="p">,</span><span class="w"> </span><span class="py">name</span><span class="p">:</span><span class="w"> </span><span class="err">'</span><span class="nc">Debug</span><span class="w"> </span><span class="py">User</span><span class="err">'</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">View</span><span class="w"> </span><span class="py">trigger</span><span class="w"> </span><span class="py">log</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">SELECT</span><span class="w"> </span><span class="py">trigger_name</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">execution_time_ms</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="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">error_message</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">FROM</span><span class="w"> </span><span class="py">SYSTEM</span><span class="err">.</span><span class="py">trigger_execution_log</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">timestamp</span><span class="w"> </span><span class="err">></span><span class="w"> </span><span class="py">datetime</span><span class="p">()</span><span class="err">.</span><span class="py">minusMinutes</span><span class="p">(</span><span class="py">5</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">ORDER</span><span class="w"> </span><span class="py">BY</span><span class="w"> </span><span class="py">timestamp</span><span class="w"> </span><span class="py">DESC</span><span class="err">;</span><span class="w">
</span></span></span></code></pre></div>
<h4 id="trigger-profiling" class="position-relative d-flex align-items-center group">
<span>Trigger Profiling</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="trigger-profiling"
aria-haspopup="dialog"
aria-label="Share link: Trigger Profiling">
<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>Identify slow triggers:</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">Profile</span><span class="w"> </span><span class="py">trigger</span><span class="w"> </span><span class="py">execution</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">PROFILE</span><span class="w"> </span><span class="py">TRIGGER</span><span class="w"> </span><span class="py">audit_new_users</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">Returns</span><span class="p">:</span><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="nc">Trigger</span><span class="p">:</span><span class="w"> </span><span class="nc">audit_new_users</span><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">Execution</span><span class="w"> </span><span class="py">time</span><span class="p">:</span><span class="w"> </span><span class="nc">2</span><span class="mf">.5</span><span class="py">ms</span><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">Breakdown</span><span class="p">:</span><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="nc">Pattern</span><span class="w"> </span><span class="py">matching</span><span class="p">:</span><span class="w"> </span><span class="nc">0</span><span class="mf">.3</span><span class="py">ms</span><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">Property</span><span class="w"> </span><span class="py">access</span><span class="p">:</span><span class="w"> </span><span class="nc">0</span><span class="mf">.1</span><span class="py">ms</span><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">Insert</span><span class="w"> </span><span class="py">operation</span><span class="p">:</span><span class="w"> </span><span class="nc">2</span><span class="mf">.1</span><span class="py">ms</span><span class="w">
</span></span></span></code></pre></div>
<h3 id="migration-strategies" class="position-relative d-flex align-items-center group">
<span>Migration Strategies</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="migration-strategies"
aria-haspopup="dialog"
aria-label="Share link: Migration Strategies">
<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-hooks-to-existing-data" class="position-relative d-flex align-items-center group">
<span>Adding Hooks to Existing Data</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-hooks-to-existing-data"
aria-haspopup="dialog"
aria-label="Share link: Adding Hooks to Existing Data">
<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>Apply triggers to historical data:</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">Create</span><span class="w"> </span><span class="py">trigger</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">TRIGGER</span><span class="w"> </span><span class="py">compute_full_name</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">BEFORE</span><span class="w"> </span><span class="py">INSERT</span><span class="w"> </span><span class="py">OR</span><span class="w"> </span><span class="py">UPDATE</span><span class="w"> </span><span class="py">ON</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">FOR</span><span class="w"> </span><span class="py">EACH</span><span class="w"> </span><span class="py">ROW</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">EXECUTE</span><span class="w"> </span><span class="py">GQL</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">SET</span><span class="w"> </span><span class="py">NEW</span><span class="err">.</span><span class="py">full_name</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="py">NEW</span><span class="err">.</span><span class="py">first_name</span><span class="w"> </span><span class="p">||</span><span class="w"> </span><span class="err">'</span><span class="w"> </span><span class="err">'</span><span class="w"> </span><span class="p">||</span><span class="w"> </span><span class="py">NEW</span><span class="err">.</span><span class="py">last_name</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">Backfill</span><span class="w"> </span><span class="py">existing</span><span class="w"> </span><span class="py">data</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">p</span><span class="p">:</span><span class="nc">Person</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">p</span><span class="err">.</span><span class="py">full_name</span><span class="w"> </span><span class="py">IS</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">WITH</span><span class="w"> </span><span class="py">p</span><span class="w"> </span><span class="py">LIMIT</span><span class="w"> </span><span class="py">1000</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">SET</span><span class="w"> </span><span class="py">p</span><span class="err">.</span><span class="py">full_name</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="py">p</span><span class="err">.</span><span class="py">first_name</span><span class="w"> </span><span class="p">||</span><span class="w"> </span><span class="err">'</span><span class="w"> </span><span class="err">'</span><span class="w"> </span><span class="p">||</span><span class="w"> </span><span class="py">p</span><span class="err">.</span><span class="py">last_name</span><span class="err">;</span><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">Repeat</span><span class="w"> </span><span class="py">until</span><span class="w"> </span><span class="py">all</span><span class="w"> </span><span class="py">records</span><span class="w"> </span><span class="py">updated</span><span class="w">
</span></span></span></code></pre></div>
<h4 id="versioning-hooks" class="position-relative d-flex align-items-center group">
<span>Versioning Hooks</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="versioning-hooks"
aria-haspopup="dialog"
aria-label="Share link: Versioning Hooks">
<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>Manage hook changes over time:</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">Drop</span><span class="w"> </span><span class="py">old</span><span class="w"> </span><span class="py">trigger</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">TRIGGER</span><span class="w"> </span><span class="py">IF</span><span class="w"> </span><span class="py">EXISTS</span><span class="w"> </span><span class="py">audit_new_users_v1</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">Create</span><span class="w"> </span><span class="py">new</span><span class="w"> </span><span class="py">version</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">TRIGGER</span><span class="w"> </span><span class="py">audit_new_users_v2</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">AFTER</span><span class="w"> </span><span class="py">INSERT</span><span class="w"> </span><span class="py">ON</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">FOR</span><span class="w"> </span><span class="py">EACH</span><span class="w"> </span><span class="py">ROW</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">EXECUTE</span><span class="w"> </span><span class="py">GQL</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">INSERT</span><span class="w"> </span><span class="p">(</span><span class="py">a</span><span class="p">:</span><span class="nc">AuditLog</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">version</span><span class="p">:</span><span class="w"> </span><span class="nc">2</span><span class="p">,</span><span class="w"> </span><span class="err">--</span><span class="w"> </span><span class="py">Track</span><span class="w"> </span><span class="py">trigger</span><span class="w"> </span><span class="py">version</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">action</span><span class="p">:</span><span class="w"> </span><span class="err">'</span><span class="nc">user_created</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">user_id</span><span class="p">:</span><span class="w"> </span><span class="nc">NEW</span><span class="err">.</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">timestamp</span><span class="p">:</span><span class="w"> </span><span class="nc">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">details</span><span class="p">:</span><span class="w"> </span><span class="nc">NEW</span><span class="err">.</span><span class="py">properties</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">ip_address</span><span class="p">:</span><span class="w"> </span><span class="nc">CURRENT_IP</span><span class="p">(),</span><span class="w"> </span><span class="err">--</span><span class="w"> </span><span class="py">New</span><span class="w"> </span><span class="py">field</span><span class="w"> </span><span class="py">in</span><span class="w"> </span><span class="py">v2</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">user_agent</span><span class="p">:</span><span class="w"> </span><span class="nc">CURRENT_USER_AGENT</span><span class="p">()</span><span class="w"> </span><span class="err">--</span><span class="w"> </span><span class="py">New</span><span class="w"> </span><span class="py">field</span><span class="w"> </span><span class="py">in</span><span class="w"> </span><span class="py">v2</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="learn-more" class="position-relative d-flex align-items-center group">
<span>Learn More</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="learn-more"
aria-haspopup="dialog"
aria-label="Share link: Learn More">
<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="https://www.postgresql.org/docs/current/triggers.html"
aria-label="Database Triggers (PostgreSQL) – opens in new window"
target="_blank" rel="noopener noreferrer"
>Database Triggers (PostgreSQL)
<span aria-hidden="true" class="external-icon">↗</span>
</a>
</li>
<li><a
href="https://use-the-index-luke.com/sql/dml/insert"
aria-label="Trigger Design Patterns – opens in new window"
target="_blank" rel="noopener noreferrer"
>Trigger Design Patterns
<span aria-hidden="true" class="external-icon">↗</span>
</a>
</li>
<li><a
href="https://docs.oracle.com/en/database/oracle/oracle-database/19/lnpls/plsql-triggers.html"
aria-label="Oracle Triggers Documentation – opens in new window"
target="_blank" rel="noopener noreferrer"
>Oracle Triggers Documentation
<span aria-hidden="true" class="external-icon">↗</span>
</a>
</li>
<li><a
href="https://martinfowler.com/articles/201701-event-driven.html"
aria-label="Event-Driven Architecture – opens in new window"
target="_blank" rel="noopener noreferrer"
>Event-Driven Architecture
<span aria-hidden="true" class="external-icon">↗</span>
</a>
</li>
<li><a
href="https://www.postgresql.org/docs/current/plpgsql-trigger.html"
aria-label="Database Automation Best Practices – opens in new window"
target="_blank" rel="noopener noreferrer"
>Database Automation Best Practices
<span aria-hidden="true" class="external-icon">↗</span>
</a>
</li>
</ul>
Related Articles
No articles found with this tag yet.
Back to Home