blob: 1c634472acd63a22934ba01fc096f3bf2a4b8a89 [file] [log] [blame]
<!doctype html>
<html lang="en-US" data-theme="light">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<meta name="generator" content="VuePress 2.0.0-rc.9" />
<meta name="theme" content="VuePress Theme Hope 2.0.0-rc.34" />
<style>
html {
background: var(--bg-color, #fff);
}
html[data-theme="dark"] {
background: var(--bg-color, #1d1e1f);
}
body {
background: var(--bg-color);
}
</style>
<script>
const userMode = localStorage.getItem("vuepress-theme-hope-scheme");
const systemDarkMode =
window.matchMedia &&
window.matchMedia("(prefers-color-scheme: dark)").matches;
if (userMode === "dark" || (userMode !== "light" && systemDarkMode)) {
document.documentElement.setAttribute("data-theme", "dark");
}
</script>
<link rel="alternate" hreflang="zh-cn" href="https://iotdb.apache.org/zh/UserGuide/latest/User-Manual/Database-Programming.html"><meta property="og:url" content="https://iotdb.apache.org/UserGuide/latest/User-Manual/Database-Programming.html"><meta property="og:site_name" content="IoTDB Website"><meta property="og:title" content="Database Programming"><meta property="og:description" content="Database Programming TRIGGER 1. Instructions The trigger provides a mechanism for listening to changes in time series data. With user-defined logic, tasks such as alerting and d..."><meta property="og:type" content="article"><meta property="og:image" content="https://alioss.timecho.com/docs/img/UserGuide/Process-Data/Continuous-Query/pic1.png?raw=true"><meta property="og:locale" content="en-US"><meta property="og:locale:alternate" content="zh-CN"><meta property="og:updated_time" content="2024-03-29T10:50:02.000Z"><meta property="article:modified_time" content="2024-03-29T10:50:02.000Z"><script type="application/ld+json">{"@context":"https://schema.org","@type":"Article","headline":"Database Programming","image":["https://alioss.timecho.com/docs/img/UserGuide/Process-Data/Continuous-Query/pic1.png?raw=true","https://alioss.timecho.com/docs/img/UserGuide/Process-Data/Continuous-Query/pic2.png?raw=true","https://alioss.timecho.com/docs/img/UserGuide/Process-Data/Continuous-Query/pic3.png?raw=true","https://alioss.timecho.com/docs/img/UserGuide/Process-Data/Continuous-Query/pic4.png?raw=true"],"dateModified":"2024-03-29T10:50:02.000Z","author":[]}</script><link rel="icon" href="/favicon.ico"><meta name="Description" content="Apache IoTDB: Time Series Database for IoT"><meta name="Keywords" content="TSDB, time series, time series database, IoTDB, IoT database, IoT data management,时序数据库, 时间序列管理, IoTDB, 物联网数据库, 实时数据库, 物联网数据管理, 物联网数据"><meta name="baidu-site-verification" content="wfKETzB3OT"><meta name="google-site-verification" content="mZWAoRY0yj_HAr-s47zHCGHzx5Ju-RVm5wDbPnwQYFo"><script type="text/javascript">
var _paq = window._paq = window._paq || [];
/* tracker methods like "setCustomDimension" should be called before "trackPageView" */
_paq.push(["setDoNotTrack", true]);
_paq.push(["disableCookies"]);
_paq.push(['trackPageView']);
_paq.push(['enableLinkTracking']);
(function() {
var u="https://analytics.apache.org/";
_paq.push(['setTrackerUrl', u+'matomo.php']);
_paq.push(['setSiteId', '56']);
var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s);
})();
</script><title>Database Programming | IoTDB Website</title><meta name="description" content="Database Programming TRIGGER 1. Instructions The trigger provides a mechanism for listening to changes in time series data. With user-defined logic, tasks such as alerting and d...">
<link rel="preload" href="/assets/style-DnEHAOmf.css" as="style"><link rel="stylesheet" href="/assets/style-DnEHAOmf.css">
<link rel="modulepreload" href="/assets/app-DrPcRZG6.js"><link rel="modulepreload" href="/assets/Database-Programming.html-CKR6BU8s.js">
</head>
<body>
<div id="app"><!--[--><!--[--><!--[--><span tabindex="-1"></span><a href="#main-content" class="vp-skip-link sr-only">Skip to main content</a><!--]--><!--[--><div class="theme-container has-toc"><!--[--><header id="navbar" class="vp-navbar hide-icon"><div class="vp-navbar-start"><button type="button" class="vp-toggle-sidebar-button" title="Toggle Sidebar"><span class="icon"></span></button><!--[--><!----><!--]--><!--[--><a class="route-link vp-brand" href="/"><img class="vp-nav-logo" src="/logo.png" alt><!----><span class="vp-site-name hide-in-pad">IoTDB Website</span></a><!--]--><!--[--><!----><!--]--></div><div class="vp-navbar-center"><!--[--><!----><!--]--><!--[--><!--]--><!--[--><!----><!--]--></div><div class="vp-navbar-end"><!--[--><!----><!--]--><!--[--><!--[--><div id="docsearch-container" style="display:none;"></div><div><button type="button" class="DocSearch DocSearch-Button" aria-label="Search"><span class="DocSearch-Button-Container"><svg width="20" height="20" class="DocSearch-Search-Icon" viewBox="0 0 20 20"><path d="M14.386 14.386l4.0877 4.0877-4.0877-4.0877c-2.9418 2.9419-7.7115 2.9419-10.6533 0-2.9419-2.9418-2.9419-7.7115 0-10.6533 2.9418-2.9419 7.7115-2.9419 10.6533 0 2.9419 2.9418 2.9419 7.7115 0 10.6533z" stroke="currentColor" fill="none" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round"></path></svg><span class="DocSearch-Button-Placeholder">Search</span></span><span class="DocSearch-Button-Keys"><kbd class="DocSearch-Button-Key"><svg width="15" height="15" class="DocSearch-Control-Key-Icon"><path d="M4.505 4.496h2M5.505 5.496v5M8.216 4.496l.055 5.993M10 7.5c.333.333.5.667.5 1v2M12.326 4.5v5.996M8.384 4.496c1.674 0 2.116 0 2.116 1.5s-.442 1.5-2.116 1.5M3.205 9.303c-.09.448-.277 1.21-1.241 1.203C1 10.5.5 9.513.5 8V7c0-1.57.5-2.5 1.464-2.494.964.006 1.134.598 1.24 1.342M12.553 10.5h1.953" stroke-width="1.2" stroke="currentColor" fill="none" stroke-linecap="square"></path></svg></kbd><kbd class="DocSearch-Button-Key">K</kbd></span></button></div><!--]--><nav class="vp-nav-links"><div class="vp-nav-item hide-in-mobile"><div class="dropdown-wrapper"><button type="button" class="dropdown-title" aria-label="Documentation"><span class="title"><!---->Documentation</span><span class="arrow"></span><ul class="nav-dropdown"><li class="dropdown-item"><a class="route-link nav-link" href="/UserGuide/latest/QuickStart/QuickStart.html" aria-label="v1.3.x"><!---->v1.3.x<!----></a></li><li class="dropdown-item"><a class="route-link nav-link" href="/UserGuide/V1.2.x/QuickStart/QuickStart.html" aria-label="v1.2.x"><!---->v1.2.x<!----></a></li><li class="dropdown-item"><a class="route-link nav-link" href="/UserGuide/V1.1.x/QuickStart/QuickStart.html" aria-label="v1.1.x"><!---->v1.1.x<!----></a></li><li class="dropdown-item"><a class="route-link nav-link" href="/UserGuide/V1.0.x/QuickStart/QuickStart.html" aria-label="v1.0.x"><!---->v1.0.x<!----></a></li><li class="dropdown-item"><a class="route-link nav-link" href="/UserGuide/V0.13.x/QuickStart/QuickStart.html" aria-label="v0.13.x"><!---->v0.13.x<!----></a></li></ul></button></div></div><div class="vp-nav-item hide-in-mobile"><a href="https://cwiki.apache.org/confluence/display/IOTDB/System+Design" rel="noopener noreferrer" target="_blank" aria-label="Design" class="nav-link"><!---->Design<span><svg class="external-link-icon" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg><span class="external-link-icon-sr-only">open in new window</span></span><!----></a></div><div class="vp-nav-item hide-in-mobile"><a class="route-link nav-link" href="/Download/" aria-label="Download"><!---->Download<!----></a></div><div class="vp-nav-item hide-in-mobile"><div class="dropdown-wrapper"><button type="button" class="dropdown-title" aria-label="Community"><span class="title"><!---->Community</span><span class="arrow"></span><ul class="nav-dropdown"><li class="dropdown-item"><a class="route-link nav-link" href="/Community/About.html" aria-label="About"><!---->About<!----></a></li><li class="dropdown-item"><a href="https://cwiki.apache.org/confluence/display/iotdb" rel="noopener noreferrer" target="_blank" aria-label="Wiki" class="nav-link"><!---->Wiki<span><svg class="external-link-icon" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg><span class="external-link-icon-sr-only">open in new window</span></span><!----></a></li><li class="dropdown-item"><a class="route-link nav-link" href="/Community/Community-Project-Committers.html" aria-label="People"><!---->People<!----></a></li><li class="dropdown-item"><a class="route-link nav-link" href="/Community/Community-Powered-By.html" aria-label="Powered By"><!---->Powered By<!----></a></li><li class="dropdown-item"><a class="route-link nav-link" href="/Community/Materials.html" aria-label="Resources"><!---->Resources<!----></a></li><li class="dropdown-item"><a class="route-link nav-link" href="/Community/Feedback.html" aria-label="Feedback"><!---->Feedback<!----></a></li></ul></button></div></div><div class="vp-nav-item hide-in-mobile"><div class="dropdown-wrapper"><button type="button" class="dropdown-title" aria-label="Development"><span class="title"><!---->Development</span><span class="arrow"></span><ul class="nav-dropdown"><li class="dropdown-item"><a class="route-link nav-link" href="/Development/VoteRelease.html" aria-label="How to vote"><!---->How to vote<!----></a></li><li class="dropdown-item"><a class="route-link nav-link" href="/Development/HowToCommit.html" aria-label="How to Commit"><!---->How to Commit<!----></a></li><li class="dropdown-item"><a class="route-link nav-link" href="/Development/HowToJoin.html" aria-label="Become a Contributor"><!---->Become a Contributor<!----></a></li><li class="dropdown-item"><a class="route-link nav-link" href="/Development/Committer.html" aria-label="Become a Committer"><!---->Become a Committer<!----></a></li><li class="dropdown-item"><a class="route-link nav-link" href="/Development/ContributeGuide.html" aria-label="ContributeGuide"><!---->ContributeGuide<!----></a></li><li class="dropdown-item"><a class="route-link nav-link" href="/Development/HowtoContributeCode.html" aria-label="How to Contribute Code"><!---->How to Contribute Code<!----></a></li><li class="dropdown-item"><a class="route-link nav-link" href="/Development/format-changelist.html" aria-label="Changelist of TsFile"><!---->Changelist of TsFile<!----></a></li><li class="dropdown-item"><a class="route-link nav-link" href="/Development/rpc-changelist.html" aria-label="Changelist of RPC"><!---->Changelist of RPC<!----></a></li></ul></button></div></div><div class="vp-nav-item hide-in-mobile"><div class="dropdown-wrapper"><button type="button" class="dropdown-title" aria-label="ASF"><span class="title"><!---->ASF</span><span class="arrow"></span><ul class="nav-dropdown"><li class="dropdown-item"><a href="https://www.apache.org/" rel="noopener noreferrer" target="_blank" aria-label="Foundation" class="nav-link"><!---->Foundation<span><svg class="external-link-icon" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg><span class="external-link-icon-sr-only">open in new window</span></span><!----></a></li><li class="dropdown-item"><a href="https://www.apache.org/licenses/" rel="noopener noreferrer" target="_blank" aria-label="License" class="nav-link"><!---->License<span><svg class="external-link-icon" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg><span class="external-link-icon-sr-only">open in new window</span></span><!----></a></li><li class="dropdown-item"><a href="https://www.apache.org/security/" rel="noopener noreferrer" target="_blank" aria-label="Security" class="nav-link"><!---->Security<span><svg class="external-link-icon" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg><span class="external-link-icon-sr-only">open in new window</span></span><!----></a></li><li class="dropdown-item"><a href="https://www.apache.org/foundation/sponsorship.html" rel="noopener noreferrer" target="_blank" aria-label="Sponsorship" class="nav-link"><!---->Sponsorship<span><svg class="external-link-icon" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg><span class="external-link-icon-sr-only">open in new window</span></span><!----></a></li><li class="dropdown-item"><a href="https://www.apache.org/foundation/thanks.html" rel="noopener noreferrer" target="_blank" aria-label="Thanks" class="nav-link"><!---->Thanks<span><svg class="external-link-icon" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg><span class="external-link-icon-sr-only">open in new window</span></span><!----></a></li><li class="dropdown-item"><a href="https://www.apache.org/events/current-event" rel="noopener noreferrer" target="_blank" aria-label="Current Events" class="nav-link"><!---->Current Events<span><svg class="external-link-icon" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg><span class="external-link-icon-sr-only">open in new window</span></span><!----></a></li><li class="dropdown-item"><a href="https://privacy.apache.org/policies/privacy-policy-public.html" rel="noopener noreferrer" target="_blank" aria-label="Privacy" class="nav-link"><!---->Privacy<span><svg class="external-link-icon" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg><span class="external-link-icon-sr-only">open in new window</span></span><!----></a></li></ul></button></div></div></nav><div class="vp-nav-item"><div class="dropdown-wrapper"><button type="button" class="dropdown-title" aria-label="Select language"><!--[--><svg xmlns="http://www.w3.org/2000/svg" class="icon i18n-icon" viewBox="0 0 1024 1024" fill="currentColor" aria-label="i18n icon" style="width:1rem;height:1rem;vertical-align:middle;"><path d="M379.392 460.8 494.08 575.488l-42.496 102.4L307.2 532.48 138.24 701.44l-71.68-72.704L234.496 460.8l-45.056-45.056c-27.136-27.136-51.2-66.56-66.56-108.544h112.64c7.68 14.336 16.896 27.136 26.112 35.84l45.568 46.08 45.056-45.056C382.976 312.32 409.6 247.808 409.6 204.8H0V102.4h256V0h102.4v102.4h256v102.4H512c0 70.144-37.888 161.28-87.04 210.944L378.88 460.8zM576 870.4 512 1024H409.6l256-614.4H768l256 614.4H921.6l-64-153.6H576zM618.496 768h196.608L716.8 532.48 618.496 768z"></path></svg><!--]--><span class="arrow"></span><ul class="nav-dropdown"><li class="dropdown-item"><a class="route-link nav-link active" href="/UserGuide/latest/User-Manual/Database-Programming.html" aria-label="English"><!---->English<!----></a></li><li class="dropdown-item"><a class="route-link nav-link" href="/zh/UserGuide/latest/User-Manual/Database-Programming.html" aria-label="简体中文"><!---->简体中文<!----></a></li></ul></button></div></div><div class="vp-nav-item hide-in-mobile"><button type="button" id="appearance-switch"><svg xmlns="http://www.w3.org/2000/svg" class="icon auto-icon" viewBox="0 0 1024 1024" fill="currentColor" aria-label="auto icon" style="display:none;"><path d="M512 992C246.92 992 32 777.08 32 512S246.92 32 512 32s480 214.92 480 480-214.92 480-480 480zm0-840c-198.78 0-360 161.22-360 360 0 198.84 161.22 360 360 360s360-161.16 360-360c0-198.78-161.22-360-360-360zm0 660V212c165.72 0 300 134.34 300 300 0 165.72-134.28 300-300 300z"></path></svg><svg xmlns="http://www.w3.org/2000/svg" class="icon dark-icon" viewBox="0 0 1024 1024" fill="currentColor" aria-label="dark icon" style="display:none;"><path d="M524.8 938.667h-4.267a439.893 439.893 0 0 1-313.173-134.4 446.293 446.293 0 0 1-11.093-597.334A432.213 432.213 0 0 1 366.933 90.027a42.667 42.667 0 0 1 45.227 9.386 42.667 42.667 0 0 1 10.24 42.667 358.4 358.4 0 0 0 82.773 375.893 361.387 361.387 0 0 0 376.747 82.774 42.667 42.667 0 0 1 54.187 55.04 433.493 433.493 0 0 1-99.84 154.88 438.613 438.613 0 0 1-311.467 128z"></path></svg><svg xmlns="http://www.w3.org/2000/svg" class="icon light-icon" viewBox="0 0 1024 1024" fill="currentColor" aria-label="light icon" style="display:block;"><path d="M952 552h-80a40 40 0 0 1 0-80h80a40 40 0 0 1 0 80zM801.88 280.08a41 41 0 0 1-57.96-57.96l57.96-58a41.04 41.04 0 0 1 58 58l-58 57.96zM512 752a240 240 0 1 1 0-480 240 240 0 0 1 0 480zm0-560a40 40 0 0 1-40-40V72a40 40 0 0 1 80 0v80a40 40 0 0 1-40 40zm-289.88 88.08-58-57.96a41.04 41.04 0 0 1 58-58l57.96 58a41 41 0 0 1-57.96 57.96zM192 512a40 40 0 0 1-40 40H72a40 40 0 0 1 0-80h80a40 40 0 0 1 40 40zm30.12 231.92a41 41 0 0 1 57.96 57.96l-57.96 58a41.04 41.04 0 0 1-58-58l58-57.96zM512 832a40 40 0 0 1 40 40v80a40 40 0 0 1-80 0v-80a40 40 0 0 1 40-40zm289.88-88.08 58 57.96a41.04 41.04 0 0 1-58 58l-57.96-58a41 41 0 0 1 57.96-57.96z"></path></svg></button></div><div class="vp-nav-item vp-action"><a class="vp-action-link" href="https://github.com/apache/iotdb" target="_blank" rel="noopener noreferrer" aria-label="GitHub"><svg xmlns="http://www.w3.org/2000/svg" class="icon github-icon" viewBox="0 0 1024 1024" fill="currentColor" aria-label="github icon" style="width:1.25rem;height:1.25rem;vertical-align:middle;"><path d="M511.957 21.333C241.024 21.333 21.333 240.981 21.333 512c0 216.832 140.544 400.725 335.574 465.664 24.49 4.395 32.256-10.07 32.256-23.083 0-11.69.256-44.245 0-85.205-136.448 29.61-164.736-64.64-164.736-64.64-22.315-56.704-54.4-71.765-54.4-71.765-44.587-30.464 3.285-29.824 3.285-29.824 49.195 3.413 75.179 50.517 75.179 50.517 43.776 75.008 114.816 53.333 142.762 40.79 4.523-31.66 17.152-53.377 31.19-65.537-108.971-12.458-223.488-54.485-223.488-242.602 0-53.547 19.114-97.323 50.517-131.67-5.035-12.33-21.93-62.293 4.779-129.834 0 0 41.258-13.184 134.912 50.346a469.803 469.803 0 0 1 122.88-16.554c41.642.213 83.626 5.632 122.88 16.554 93.653-63.488 134.784-50.346 134.784-50.346 26.752 67.541 9.898 117.504 4.864 129.834 31.402 34.347 50.474 78.123 50.474 131.67 0 188.586-114.73 230.016-224.042 242.09 17.578 15.232 33.578 44.672 33.578 90.454v135.85c0 13.142 7.936 27.606 32.854 22.87C862.25 912.597 1002.667 728.747 1002.667 512c0-271.019-219.648-490.667-490.71-490.667z"></path></svg></a></div><!--]--><!--[--><!----><!--]--><button type="button" class="vp-toggle-navbar-button" aria-label="Toggle Navbar" aria-expanded="false" aria-controls="nav-screen"><span><span class="vp-top"></span><span class="vp-middle"></span><span class="vp-bottom"></span></span></button></div></header><!----><!--]--><!----><div class="toggle-sidebar-wrapper"><span class="arrow start"></span></div><aside id="sidebar" class="vp-sidebar"><!--[--><!----><!--]--><ul class="vp-sidebar-links"><li><section class="vp-sidebar-group"><p class="vp-sidebar-header"><!----><span class="vp-sidebar-title">IoTDB User Guide (V1.3.x)</span><!----></p><ul class="vp-sidebar-links"></ul></section></li><li><section class="vp-sidebar-group"><button class="vp-sidebar-header clickable" type="button"><!----><span class="vp-sidebar-title">About IoTDB</span><span class="vp-arrow end"></span></button><!----></section></li><li><section class="vp-sidebar-group"><button class="vp-sidebar-header clickable" type="button"><!----><span class="vp-sidebar-title">Quick Start</span><span class="vp-arrow end"></span></button><!----></section></li><li><section class="vp-sidebar-group"><button class="vp-sidebar-header clickable" type="button"><!----><span class="vp-sidebar-title">Basic Concept</span><span class="vp-arrow end"></span></button><!----></section></li><li><section class="vp-sidebar-group"><button class="vp-sidebar-header clickable" type="button"><!----><span class="vp-sidebar-title">Deployment &amp; Maintenance</span><span class="vp-arrow end"></span></button><!----></section></li><li><section class="vp-sidebar-group"><button class="vp-sidebar-header clickable active" type="button"><!----><span class="vp-sidebar-title">User Manual</span><span class="vp-arrow down"></span></button><ul class="vp-sidebar-links"><li><a class="route-link nav-link vp-sidebar-link vp-sidebar-page" href="/UserGuide/latest/User-Manual/Syntax-Rule.html" aria-label="Syntax Rule"><!---->Syntax Rule<!----></a></li><li><a class="route-link nav-link vp-sidebar-link vp-sidebar-page" href="/UserGuide/latest/User-Manual/Operate-Metadata.html" aria-label="Operate Metadata"><!---->Operate Metadata<!----></a></li><li><a class="route-link nav-link vp-sidebar-link vp-sidebar-page" href="/UserGuide/latest/User-Manual/Write-Delete-Data.html" aria-label="Write Delete Data"><!---->Write Delete Data<!----></a></li><li><a class="route-link nav-link vp-sidebar-link vp-sidebar-page" href="/UserGuide/latest/User-Manual/Query-Data.html" aria-label="Query Data"><!---->Query Data<!----></a></li><li><a class="route-link nav-link vp-sidebar-link vp-sidebar-page" href="/UserGuide/latest/User-Manual/Operator-and-Expression.html" aria-label="Operator and Expression"><!---->Operator and Expression<!----></a></li><li><a class="route-link nav-link vp-sidebar-link vp-sidebar-page" href="/UserGuide/latest/User-Manual/Streaming.html" aria-label="Streaming"><!---->Streaming<!----></a></li><li><a class="route-link nav-link vp-sidebar-link vp-sidebar-page" href="/UserGuide/latest/User-Manual/Data-Sync.html" aria-label="Data Sync"><!---->Data Sync<!----></a></li><li><a class="route-link nav-link active vp-sidebar-link vp-sidebar-page active" href="/UserGuide/latest/User-Manual/Database-Programming.html" aria-label="Database Programming"><!---->Database Programming<!----></a></li><li><a class="route-link nav-link vp-sidebar-link vp-sidebar-page" href="/UserGuide/latest/User-Manual/Authority-Management.html" aria-label="Authority Management"><!---->Authority Management<!----></a></li><li><a class="route-link nav-link vp-sidebar-link vp-sidebar-page" href="/UserGuide/latest/User-Manual/Maintennance.html" aria-label="Maintennance"><!---->Maintennance<!----></a></li></ul></section></li><li><section class="vp-sidebar-group"><button class="vp-sidebar-header clickable" type="button"><!----><span class="vp-sidebar-title">Tools System</span><span class="vp-arrow end"></span></button><!----></section></li><li><section class="vp-sidebar-group"><button class="vp-sidebar-header clickable" type="button"><!----><span class="vp-sidebar-title">API</span><span class="vp-arrow end"></span></button><!----></section></li><li><section class="vp-sidebar-group"><button class="vp-sidebar-header clickable" type="button"><!----><span class="vp-sidebar-title">Ecosystem Integration</span><span class="vp-arrow end"></span></button><!----></section></li><li><section class="vp-sidebar-group"><button class="vp-sidebar-header clickable" type="button"><!----><span class="vp-sidebar-title">SQL Manual</span><span class="vp-arrow end"></span></button><!----></section></li><li><section class="vp-sidebar-group"><button class="vp-sidebar-header clickable" type="button"><!----><span class="vp-sidebar-title">FAQ</span><span class="vp-arrow end"></span></button><!----></section></li><li><section class="vp-sidebar-group"><button class="vp-sidebar-header clickable" type="button"><!----><span class="vp-sidebar-title">Reference</span><span class="vp-arrow end"></span></button><!----></section></li></ul><!--[--><!----><!--]--></aside><!--[--><main id="main-content" class="vp-page"><!--[--><!--[--><!----><!--]--><!----><nav class="vp-breadcrumb disable"></nav><div class="vp-page-title"><h1><!---->Database Programming</h1><div class="page-info"><!----><!----><span class="page-date-info" aria-label="Writing Date"><svg xmlns="http://www.w3.org/2000/svg" class="icon calendar-icon" viewBox="0 0 1024 1024" fill="currentColor" aria-label="calendar icon"><path d="M716.4 110.137c0-18.753-14.72-33.473-33.472-33.473-18.753 0-33.473 14.72-33.473 33.473v33.473h66.993v-33.473zm-334.87 0c0-18.753-14.72-33.473-33.473-33.473s-33.52 14.72-33.52 33.473v33.473h66.993v-33.473zm468.81 33.52H716.4v100.465c0 18.753-14.72 33.473-33.472 33.473a33.145 33.145 0 01-33.473-33.473V143.657H381.53v100.465c0 18.753-14.72 33.473-33.473 33.473a33.145 33.145 0 01-33.473-33.473V143.657H180.6A134.314 134.314 0 0046.66 277.595v535.756A134.314 134.314 0 00180.6 947.289h669.74a134.36 134.36 0 00133.94-133.938V277.595a134.314 134.314 0 00-133.94-133.938zm33.473 267.877H147.126a33.145 33.145 0 01-33.473-33.473c0-18.752 14.72-33.473 33.473-33.473h736.687c18.752 0 33.472 14.72 33.472 33.473a33.145 33.145 0 01-33.472 33.473z"></path></svg><span><!----></span><meta property="datePublished" content="2023-08-01T06:02:08.000Z"></span><span class="page-pageview-info" aria-label="Page views"><svg xmlns="http://www.w3.org/2000/svg" class="icon eye-icon" viewBox="0 0 1024 1024" fill="currentColor" aria-label="eye icon"><path d="M992 512.096c0-5.76-.992-10.592-1.28-11.136-.192-2.88-1.152-8.064-2.08-10.816-.256-.672-.544-1.376-.832-2.08-.48-1.568-1.024-3.104-1.6-4.32C897.664 290.112 707.104 160 512 160c-195.072 0-385.632 130.016-473.76 322.592-1.056 2.112-1.792 4.096-2.272 5.856a55.512 55.512 0 00-.64 1.6c-1.76 5.088-1.792 8.64-1.632 7.744-.832 3.744-1.568 11.168-1.568 11.168-.224 2.272-.224 4.032.032 6.304 0 0 .736 6.464 1.088 7.808.128 1.824.576 4.512 1.12 6.976h-.032c.448 2.08 1.12 4.096 1.984 6.08.48 1.536.992 2.976 1.472 4.032C126.432 733.856 316.992 864 512 864c195.136 0 385.696-130.048 473.216-321.696 1.376-2.496 2.24-4.832 2.848-6.912.256-.608.48-1.184.672-1.728 1.536-4.48 1.856-8.32 1.728-8.32l-.032.032c.608-3.104 1.568-7.744 1.568-13.28zM512 672c-88.224 0-160-71.776-160-160s71.776-160 160-160 160 71.776 160 160-71.776 160-160 160z"></path></svg><span id="ArtalkPV" class="vp-pageview waline-pageview-count" data-path="/UserGuide/latest/User-Manual/Database-Programming.html" data-page-key="/UserGuide/latest/User-Manual/Database-Programming.html">...</span></span><span class="page-reading-time-info" aria-label="Reading Time"><svg xmlns="http://www.w3.org/2000/svg" class="icon timer-icon" viewBox="0 0 1024 1024" fill="currentColor" aria-label="timer icon"><path d="M799.387 122.15c4.402-2.978 7.38-7.897 7.38-13.463v-1.165c0-8.933-7.38-16.312-16.312-16.312H256.33c-8.933 0-16.311 7.38-16.311 16.312v1.165c0 5.825 2.977 10.874 7.637 13.592 4.143 194.44 97.22 354.963 220.201 392.763-122.204 37.542-214.893 196.511-220.2 389.397-4.661 5.049-7.638 11.651-7.638 19.03v5.825h566.49v-5.825c0-7.379-2.849-13.981-7.509-18.9-5.049-193.016-97.867-351.985-220.2-389.527 123.24-37.67 216.446-198.453 220.588-392.892zM531.16 450.445v352.632c117.674 1.553 211.787 40.778 211.787 88.676H304.097c0-48.286 95.149-87.382 213.728-88.676V450.445c-93.077-3.107-167.901-81.297-167.901-177.093 0-8.803 6.99-15.793 15.793-15.793 8.803 0 15.794 6.99 15.794 15.793 0 80.261 63.69 145.635 142.01 145.635s142.011-65.374 142.011-145.635c0-8.803 6.99-15.793 15.794-15.793s15.793 6.99 15.793 15.793c0 95.019-73.789 172.82-165.96 177.093z"></path></svg><span>About 46 min</span><meta property="timeRequired" content="PT46M"></span><!----><!----></div><hr></div><div class="vp-toc-placeholder"><aside id="toc"><!--[--><!----><!--]--><div class="vp-toc-header">On This Page<button type="button" class="print-button" title="Print"><svg xmlns="http://www.w3.org/2000/svg" class="icon print-icon" viewBox="0 0 1024 1024" fill="currentColor" aria-label="print icon"><path d="M819.2 364.8h-44.8V128c0-17.067-14.933-32-32-32H281.6c-17.067 0-32 14.933-32 32v236.8h-44.8C145.067 364.8 96 413.867 96 473.6v192c0 59.733 49.067 108.8 108.8 108.8h44.8V896c0 17.067 14.933 32 32 32h460.8c17.067 0 32-14.933 32-32V774.4h44.8c59.733 0 108.8-49.067 108.8-108.8v-192c0-59.733-49.067-108.8-108.8-108.8zM313.6 160h396.8v204.8H313.6V160zm396.8 704H313.6V620.8h396.8V864zM864 665.6c0 25.6-19.2 44.8-44.8 44.8h-44.8V588.8c0-17.067-14.933-32-32-32H281.6c-17.067 0-32 14.933-32 32v121.6h-44.8c-25.6 0-44.8-19.2-44.8-44.8v-192c0-25.6 19.2-44.8 44.8-44.8h614.4c25.6 0 44.8 19.2 44.8 44.8v192z"></path></svg></button><div class="arrow end"></div></div><div class="vp-toc-wrapper"><ul class="vp-toc-list"><!--[--><li class="vp-toc-item"><a class="route-link vp-toc-link level2" href="#trigger">TRIGGER</a></li><li><ul class="vp-toc-list"><!--[--><li class="vp-toc-item"><a class="route-link vp-toc-link level3" href="#_1-instructions">1. Instructions</a></li><!----><!--]--><!--[--><li class="vp-toc-item"><a class="route-link vp-toc-link level3" href="#_2-how-to-implement-a-trigger">2. How to Implement a Trigger</a></li><!----><!--]--><!--[--><li class="vp-toc-item"><a class="route-link vp-toc-link level3" href="#_3-trigger-management">3. Trigger Management</a></li><!----><!--]--><!--[--><li class="vp-toc-item"><a class="route-link vp-toc-link level3" href="#_4-notes">4. Notes</a></li><!----><!--]--><!--[--><li class="vp-toc-item"><a class="route-link vp-toc-link level3" href="#_5-configuration-parameters">5. Configuration Parameters</a></li><!----><!--]--></ul></li><!--]--><!--[--><li class="vp-toc-item"><a class="route-link vp-toc-link level2" href="#continuous-query-cq">CONTINUOUS QUERY (CQ)</a></li><li><ul class="vp-toc-list"><!--[--><li class="vp-toc-item"><a class="route-link vp-toc-link level3" href="#_1-introduction">1. Introduction</a></li><!----><!--]--><!--[--><li class="vp-toc-item"><a class="route-link vp-toc-link level3" href="#_2-syntax">2. Syntax</a></li><!----><!--]--><!--[--><li class="vp-toc-item"><a class="route-link vp-toc-link level3" href="#_3-examples-of-cq">3. Examples of CQ</a></li><!----><!--]--><!--[--><li class="vp-toc-item"><a class="route-link vp-toc-link level3" href="#_4-cq-management">4. CQ Management</a></li><!----><!--]--><!--[--><li class="vp-toc-item"><a class="route-link vp-toc-link level3" href="#_5-cq-use-cases">5. CQ Use Cases</a></li><!----><!--]--><!--[--><li class="vp-toc-item"><a class="route-link vp-toc-link level3" href="#_6-system-parameter-configuration">6. System Parameter Configuration</a></li><!----><!--]--></ul></li><!--]--><!--[--><li class="vp-toc-item"><a class="route-link vp-toc-link level2" href="#user-defined-function-udf">USER-DEFINED FUNCTION (UDF)</a></li><li><ul class="vp-toc-list"><!--[--><li class="vp-toc-item"><a class="route-link vp-toc-link level3" href="#udf-types">UDF Types</a></li><!----><!--]--><!--[--><li class="vp-toc-item"><a class="route-link vp-toc-link level3" href="#udf-development-dependencies">UDF Development Dependencies</a></li><!----><!--]--><!--[--><li class="vp-toc-item"><a class="route-link vp-toc-link level3" href="#udtf-user-defined-timeseries-generating-function">UDTF(User Defined Timeseries Generating Function)</a></li><!----><!--]--><!--[--><li class="vp-toc-item"><a class="route-link vp-toc-link level3" href="#udaf-user-defined-aggregation-function">UDAF (User Defined Aggregation Function)</a></li><!----><!--]--><!--[--><li class="vp-toc-item"><a class="route-link vp-toc-link level3" href="#maven-project-example">Maven Project Example</a></li><!----><!--]--><!--[--><li class="vp-toc-item"><a class="route-link vp-toc-link level3" href="#udf-registration">UDF Registration</a></li><!----><!--]--><!--[--><li class="vp-toc-item"><a class="route-link vp-toc-link level3" href="#udf-deregistration">UDF Deregistration</a></li><!----><!--]--><!--[--><li class="vp-toc-item"><a class="route-link vp-toc-link level3" href="#udf-queries">UDF Queries</a></li><!----><!--]--><!--[--><li class="vp-toc-item"><a class="route-link vp-toc-link level3" href="#show-all-registered-udfs">Show All Registered UDFs</a></li><!----><!--]--><!--[--><li class="vp-toc-item"><a class="route-link vp-toc-link level3" href="#user-permission-management">User Permission Management</a></li><!----><!--]--><!--[--><li class="vp-toc-item"><a class="route-link vp-toc-link level3" href="#configurable-properties">Configurable Properties</a></li><!----><!--]--><!--[--><li class="vp-toc-item"><a class="route-link vp-toc-link level3" href="#contribute-udf">Contribute UDF</a></li><!----><!--]--><!--[--><li class="vp-toc-item"><a class="route-link vp-toc-link level3" href="#known-implementations">Known Implementations</a></li><!----><!--]--><!--[--><li class="vp-toc-item"><a class="route-link vp-toc-link level3" href="#q-a">Q&amp;A</a></li><!----><!--]--></ul></li><!--]--></ul><div class="vp-toc-marker" style="top:-1.7rem;"></div></div><!--[--><!----><!--]--></aside></div><!--[--><!----><!--]--><div class="theme-hope-content"><h1 id="database-programming" tabindex="-1"><a class="header-anchor" href="#database-programming"><span>Database Programming</span></a></h1><h2 id="trigger" tabindex="-1"><a class="header-anchor" href="#trigger"><span>TRIGGER</span></a></h2><h3 id="_1-instructions" tabindex="-1"><a class="header-anchor" href="#_1-instructions"><span>1. Instructions</span></a></h3><p>The trigger provides a mechanism for listening to changes in time series data. With user-defined logic, tasks such as alerting and data forwarding can be conducted.</p><p>The trigger is implemented based on the reflection mechanism. Users can monitor data changes by implementing the Java interfaces. IoTDB allows users to dynamically register and drop triggers without restarting the server.</p><p>The document will help you learn to define and manage triggers.</p><h4 id="pattern-for-listening" tabindex="-1"><a class="header-anchor" href="#pattern-for-listening"><span>Pattern for Listening</span></a></h4><p>A single trigger can be used to listen for data changes in a time series that match a specific pattern. For example, a trigger can listen for the data changes of time series <code>root.sg.a</code>, or time series that match the pattern <code>root.sg.*</code>. When you register a trigger, you can specify the path pattern that the trigger listens on through an SQL statement.</p><h4 id="trigger-type" tabindex="-1"><a class="header-anchor" href="#trigger-type"><span>Trigger Type</span></a></h4><p>There are currently two types of triggers, and you can specify the type through an SQL statement when registering a trigger:</p><ul><li>Stateful triggers: The execution logic of this type of trigger may depend on data from multiple insertion statement . The framework will aggregate the data written by different nodes into the same trigger instance for calculation to retain context information. This type of trigger is usually used for sampling or statistical data aggregation for a period of time. information. Only one node in the cluster holds an instance of a stateful trigger.</li><li>Stateless triggers: The execution logic of the trigger is only related to the current input data. The framework does not need to aggregate the data of different nodes into the same trigger instance. This type of trigger is usually used for calculation of single row data and abnormal detection. Each node in the cluster holds an instance of a stateless trigger.</li></ul><h4 id="trigger-event" tabindex="-1"><a class="header-anchor" href="#trigger-event"><span>Trigger Event</span></a></h4><p>There are currently two trigger events for the trigger, and other trigger events will be expanded in the future. When you register a trigger, you can specify the trigger event through an SQL statement:</p><ul><li>BEFORE INSERT: Fires before the data is persisted. <strong>Please note that currently the trigger does not support data cleaning and will not change the data to be persisted itself.</strong></li><li>AFTER INSERT: Fires after the data is persisted.</li></ul><h3 id="_2-how-to-implement-a-trigger" tabindex="-1"><a class="header-anchor" href="#_2-how-to-implement-a-trigger"><span>2. How to Implement a Trigger</span></a></h3><p>You need to implement the trigger by writing a Java class, where the dependency shown below is required. If you use <a href="http://search.maven.org/" target="_blank" rel="noopener noreferrer">Maven<span><svg class="external-link-icon" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg><span class="external-link-icon-sr-only">open in new window</span></span></a>, you can search for them directly from the <a href="http://search.maven.org/" target="_blank" rel="noopener noreferrer">Maven repository<span><svg class="external-link-icon" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg><span class="external-link-icon-sr-only">open in new window</span></span></a>.</p><h4 id="dependency" tabindex="-1"><a class="header-anchor" href="#dependency"><span>Dependency</span></a></h4><div class="language-xml line-numbers-mode" data-ext="xml" data-title="xml"><pre class="language-xml"><code><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dependency</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>groupId</span><span class="token punctuation">&gt;</span></span>org.apache.iotdb<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>groupId</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">&gt;</span></span>iotdb-server<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>version</span><span class="token punctuation">&gt;</span></span>1.0.0<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>version</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>scope</span><span class="token punctuation">&gt;</span></span>provided<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>scope</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dependency</span><span class="token punctuation">&gt;</span></span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>Note that the dependency version should be correspondent to the target server version.</p><h4 id="interface-description" tabindex="-1"><a class="header-anchor" href="#interface-description"><span>Interface Description</span></a></h4><p>To implement a trigger, you need to implement the <code>org.apache.iotdb.trigger.api.Trigger</code> class.</p><div class="language-java line-numbers-mode" data-ext="java" data-title="java"><pre class="language-java"><code><span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>apache<span class="token punctuation">.</span>iotdb<span class="token punctuation">.</span>trigger<span class="token punctuation">.</span>api<span class="token punctuation">.</span>enums<span class="token punctuation">.</span></span><span class="token class-name">FailureStrategy</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>apache<span class="token punctuation">.</span>iotdb<span class="token punctuation">.</span>tsfile<span class="token punctuation">.</span>write<span class="token punctuation">.</span>record<span class="token punctuation">.</span></span><span class="token class-name">Tablet</span></span><span class="token punctuation">;</span>
<span class="token keyword">public</span> <span class="token keyword">interface</span> <span class="token class-name">Trigger</span> <span class="token punctuation">{</span>
<span class="token doc-comment comment">/**
* This method is mainly used to validate <span class="token punctuation">{</span><span class="token keyword">@link</span> <span class="token reference"><span class="token class-name">TriggerAttributes</span></span><span class="token punctuation">}</span> before calling <span class="token punctuation">{</span><span class="token keyword">@link</span>
* <span class="token reference"><span class="token class-name">Trigger</span><span class="token punctuation">#</span><span class="token function">onCreate</span><span class="token punctuation">(</span><span class="token class-name">TriggerAttributes</span><span class="token punctuation">)</span></span><span class="token punctuation">}</span>.
*
* <span class="token keyword">@param</span> <span class="token parameter">attributes</span> TriggerAttributes
* <span class="token keyword">@throws</span> <span class="token reference"><span class="token class-name">Exception</span></span> e
*/</span>
<span class="token keyword">default</span> <span class="token keyword">void</span> <span class="token function">validate</span><span class="token punctuation">(</span><span class="token class-name">TriggerAttributes</span> attributes<span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">Exception</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>
<span class="token doc-comment comment">/**
* This method will be called when creating a trigger after validation.
*
* <span class="token keyword">@param</span> <span class="token parameter">attributes</span> TriggerAttributes
* <span class="token keyword">@throws</span> <span class="token reference"><span class="token class-name">Exception</span></span> e
*/</span>
<span class="token keyword">default</span> <span class="token keyword">void</span> <span class="token function">onCreate</span><span class="token punctuation">(</span><span class="token class-name">TriggerAttributes</span> attributes<span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">Exception</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>
<span class="token doc-comment comment">/**
* This method will be called when dropping a trigger.
*
* <span class="token keyword">@throws</span> <span class="token reference"><span class="token class-name">Exception</span></span> e
*/</span>
<span class="token keyword">default</span> <span class="token keyword">void</span> <span class="token function">onDrop</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">Exception</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>
<span class="token doc-comment comment">/**
* When restarting a DataNode, Triggers that have been registered will be restored and this method
* will be called during the process of restoring.
*
* <span class="token keyword">@throws</span> <span class="token reference"><span class="token class-name">Exception</span></span> e
*/</span>
<span class="token keyword">default</span> <span class="token keyword">void</span> <span class="token function">restore</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">Exception</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>
<span class="token doc-comment comment">/**
* Overrides this method to set the expected FailureStrategy, <span class="token punctuation">{</span><span class="token keyword">@link</span> <span class="token reference"><span class="token class-name">FailureStrategy</span><span class="token punctuation">#</span><span class="token field">OPTIMISTIC</span></span><span class="token punctuation">}</span>
* is the default strategy.
*
* <span class="token keyword">@return</span> <span class="token punctuation">{</span><span class="token keyword">@link</span> <span class="token reference"><span class="token class-name">FailureStrategy</span></span><span class="token punctuation">}</span>
*/</span>
<span class="token keyword">default</span> <span class="token class-name">FailureStrategy</span> <span class="token function">getFailureStrategy</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token class-name">FailureStrategy</span><span class="token punctuation">.</span><span class="token constant">OPTIMISTIC</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token doc-comment comment">/**
* <span class="token keyword">@param</span> <span class="token parameter">tablet</span> see <span class="token punctuation">{</span><span class="token keyword">@link</span> <span class="token reference"><span class="token class-name">Tablet</span></span><span class="token punctuation">}</span> for detailed information of data structure. Data that is
* inserted will be constructed as a Tablet and you can define process logic with <span class="token punctuation">{</span><span class="token keyword">@link</span>
* <span class="token reference"><span class="token class-name">Tablet</span></span><span class="token punctuation">}</span>.
* <span class="token keyword">@return</span> true if successfully fired
* <span class="token keyword">@throws</span> <span class="token reference"><span class="token class-name">Exception</span></span> e
*/</span>
<span class="token keyword">default</span> <span class="token keyword">boolean</span> <span class="token function">fire</span><span class="token punctuation">(</span><span class="token class-name">Tablet</span> tablet<span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">Exception</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token boolean">true</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>This class provides two types of programming interfaces: <strong>Lifecycle related interfaces</strong> and <strong>data change listening related interfaces</strong>. All the interfaces in this class are not required to be implemented. When the interfaces are not implemented, the trigger will not respond to the data changes. You can implement only some of these interfaces according to your needs.</p><p>Descriptions of the interfaces are as followed.</p><h5 id="lifecycle-related-interfaces" tabindex="-1"><a class="header-anchor" href="#lifecycle-related-interfaces"><span>Lifecycle Related Interfaces</span></a></h5><table><thead><tr><th>Interface</th><th>Description</th></tr></thead><tbody><tr><td><em>default void validate(TriggerAttributes attributes) throws Exception {}</em></td><td>When you creates a trigger using the <code>CREATE TRIGGER</code> statement, you can specify the parameters that the trigger needs to use, and this interface will be used to verify the correctness of the parameters。</td></tr><tr><td><em>default void onCreate(TriggerAttributes attributes) throws Exception {}</em></td><td>This interface is called once when you create a trigger using the <code>CREATE TRIGGER</code> statement. During the lifetime of each trigger instance, this interface will be called only once. This interface is mainly used for the following functions: helping users to parse custom attributes in SQL statements (using <code>TriggerAttributes</code>). You can create or apply for resources, such as establishing external links, opening files, etc.</td></tr><tr><td><em>default void onDrop() throws Exception {}</em></td><td>This interface is called when you drop a trigger using the <code>DROP TRIGGER</code> statement. During the lifetime of each trigger instance, this interface will be called only once. This interface mainly has the following functions: it can perform the operation of resource release and can be used to persist the results of trigger calculations.</td></tr><tr><td><em>default void restore() throws Exception {}</em></td><td>When the DataNode is restarted, the cluster will restore the trigger instance registered on the DataNode, and this interface will be called once for stateful trigger during the process. After the DataNode where the stateful trigger instance is located goes down, the cluster will restore the trigger instance on another available DataNode, calling this interface once in the process. This interface can be used to customize recovery logic.</td></tr></tbody></table><h5 id="data-change-listening-related-interfaces" tabindex="-1"><a class="header-anchor" href="#data-change-listening-related-interfaces"><span>Data Change Listening Related Interfaces</span></a></h5><h6 id="listening-interface" tabindex="-1"><a class="header-anchor" href="#listening-interface"><span>Listening Interface</span></a></h6><div class="language-java line-numbers-mode" data-ext="java" data-title="java"><pre class="language-java"><code><span class="token doc-comment comment">/**
* <span class="token keyword">@param</span> <span class="token parameter">tablet</span> see <span class="token punctuation">{</span><span class="token keyword">@link</span> <span class="token reference"><span class="token class-name">Tablet</span></span><span class="token punctuation">}</span> for detailed information of data structure. Data that is
* inserted will be constructed as a Tablet and you can define process logic with <span class="token punctuation">{</span><span class="token keyword">@link</span>
* <span class="token reference"><span class="token class-name">Tablet</span></span><span class="token punctuation">}</span>.
* <span class="token keyword">@return</span> true if successfully fired
* <span class="token keyword">@throws</span> <span class="token reference"><span class="token class-name">Exception</span></span> e
*/</span>
<span class="token keyword">default</span> <span class="token keyword">boolean</span> <span class="token function">fire</span><span class="token punctuation">(</span><span class="token class-name">Tablet</span> tablet<span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">Exception</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token boolean">true</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>When the data changes, the trigger uses the Tablet as the unit of firing operation. You can obtain the metadata and data of the corresponding sequence through Tablet, and then perform the corresponding trigger operation. If the fire process is successful, the return value should be true. If the interface returns false or throws an exception, we consider the trigger fire process as failed. When the trigger fire process fails, we will perform corresponding operations according to the listening strategy interface.</p><p>When performing an INSERT operation, for each time series in it, we will detect whether there is a trigger that listens to the path pattern, and then assemble the time series data that matches the path pattern listened by the same trigger into a new Tablet for trigger fire interface. Can be understood as:</p><div class="language-java line-numbers-mode" data-ext="java" data-title="java"><pre class="language-java"><code><span class="token class-name">Map</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">PartialPath</span><span class="token punctuation">,</span> <span class="token class-name">List</span><span class="token punctuation">&lt;</span><span class="token class-name">Trigger</span><span class="token punctuation">&gt;</span><span class="token punctuation">&gt;</span></span> pathToTriggerListMap <span class="token operator">=</span><span class="token operator">&gt;</span> <span class="token class-name">Map</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">Trigger</span><span class="token punctuation">,</span> <span class="token class-name">Tablet</span><span class="token punctuation">&gt;</span></span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div></div></div><p><strong>Note that currently we do not make any guarantees about the order in which triggers fire.</strong></p><p>Here is an example:</p><p>Suppose there are three triggers, and the trigger event of the triggers are all BEFORE INSERT:</p><ul><li>Trigger1 listens on <code>root.sg.*</code></li><li>Trigger2 listens on <code>root.sg.a</code></li><li>Trigger3 listens on <code>root.sg.b</code></li></ul><p>Insertion statement:</p><div class="language-sql line-numbers-mode" data-ext="sql" data-title="sql"><pre class="language-sql"><code><span class="token keyword">insert</span> <span class="token keyword">into</span> root<span class="token punctuation">.</span>sg<span class="token punctuation">(</span><span class="token keyword">time</span><span class="token punctuation">,</span> a<span class="token punctuation">,</span> b<span class="token punctuation">)</span> <span class="token keyword">values</span> <span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div></div></div><p>The time series <code>root.sg.a</code> matches Trigger1 and Trigger2, and the sequence <code>root.sg.b</code> matches Trigger1 and Trigger3, then:</p><ul><li>The data of <code>root.sg.a</code> and <code>root.sg.b</code> will be assembled into a new tablet1, and Trigger1.fire(tablet1) will be executed at the corresponding Trigger Event.</li><li>The data of <code>root.sg.a</code> will be assembled into a new tablet2, and Trigger2.fire(tablet2) will be executed at the corresponding Trigger Event.</li><li>The data of <code>root.sg.b</code> will be assembled into a new tablet3, and Trigger3.fire(tablet3) will be executed at the corresponding Trigger Event.</li></ul><h6 id="listening-strategy-interface" tabindex="-1"><a class="header-anchor" href="#listening-strategy-interface"><span>Listening Strategy Interface</span></a></h6><p>When the trigger fails to fire, we will take corresponding actions according to the strategy set by the listening strategy interface. You can set <code>org.apache.iotdb.trigger.api.enums.FailureStrategy</code>. There are currently two strategies, optimistic and pessimistic:</p><ul><li>Optimistic strategy: The trigger that fails to fire does not affect the firing of subsequent triggers, nor does it affect the writing process, that is, we do not perform additional processing on the sequence involved in the trigger failure, only log the failure to record the failure, and finally inform user that data insertion is successful, but the trigger fire part failed.</li><li>Pessimistic strategy: The failure trigger affects the processing of all subsequent Pipelines, that is, we believe that the firing failure of the trigger will cause all subsequent triggering processes to no longer be carried out. If the trigger event of the trigger is BEFORE INSERT, then the insertion will no longer be performed, and the insertion failure will be returned directly.</li></ul><div class="language-java line-numbers-mode" data-ext="java" data-title="java"><pre class="language-java"><code> <span class="token doc-comment comment">/**
* Overrides this method to set the expected FailureStrategy, <span class="token punctuation">{</span><span class="token keyword">@link</span> <span class="token reference"><span class="token class-name">FailureStrategy</span><span class="token punctuation">#</span><span class="token field">OPTIMISTIC</span></span><span class="token punctuation">}</span>
* is the default strategy.
*
* <span class="token keyword">@return</span> <span class="token punctuation">{</span><span class="token keyword">@link</span> <span class="token reference"><span class="token class-name">FailureStrategy</span></span><span class="token punctuation">}</span>
*/</span>
<span class="token keyword">default</span> <span class="token class-name">FailureStrategy</span> <span class="token function">getFailureStrategy</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token class-name">FailureStrategy</span><span class="token punctuation">.</span><span class="token constant">OPTIMISTIC</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h4 id="example" tabindex="-1"><a class="header-anchor" href="#example"><span>Example</span></a></h4><p>If you use <a href="http://search.maven.org/" target="_blank" rel="noopener noreferrer">Maven<span><svg class="external-link-icon" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg><span class="external-link-icon-sr-only">open in new window</span></span></a>, you can refer to our sample project <strong>trigger-example</strong>.</p><p>You can find it <a href="https://github.com/apache/iotdb/tree/master/example/trigger" target="_blank" rel="noopener noreferrer">here<span><svg class="external-link-icon" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg><span class="external-link-icon-sr-only">open in new window</span></span></a>.</p><p>Here is the code from one of the sample projects:</p><div class="language-java line-numbers-mode" data-ext="java" data-title="java"><pre class="language-java"><code><span class="token comment">/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* &quot;License&quot;); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* &quot;AS IS&quot; BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/</span>
<span class="token keyword">package</span> <span class="token namespace">org<span class="token punctuation">.</span>apache<span class="token punctuation">.</span>iotdb<span class="token punctuation">.</span>trigger</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>apache<span class="token punctuation">.</span>iotdb<span class="token punctuation">.</span>db<span class="token punctuation">.</span>storageengine<span class="token punctuation">.</span>trigger<span class="token punctuation">.</span>sink<span class="token punctuation">.</span>alertmanager<span class="token punctuation">.</span></span><span class="token class-name">AlertManagerConfiguration</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>apache<span class="token punctuation">.</span>iotdb<span class="token punctuation">.</span>db<span class="token punctuation">.</span>storageengine<span class="token punctuation">.</span>trigger<span class="token punctuation">.</span>sink<span class="token punctuation">.</span>alertmanager<span class="token punctuation">.</span></span><span class="token class-name">AlertManagerEvent</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>apache<span class="token punctuation">.</span>iotdb<span class="token punctuation">.</span>db<span class="token punctuation">.</span>storageengine<span class="token punctuation">.</span>trigger<span class="token punctuation">.</span>sink<span class="token punctuation">.</span>alertmanager<span class="token punctuation">.</span></span><span class="token class-name">AlertManagerHandler</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>apache<span class="token punctuation">.</span>iotdb<span class="token punctuation">.</span>trigger<span class="token punctuation">.</span>api<span class="token punctuation">.</span></span><span class="token class-name">Trigger</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>apache<span class="token punctuation">.</span>iotdb<span class="token punctuation">.</span>trigger<span class="token punctuation">.</span>api<span class="token punctuation">.</span></span><span class="token class-name">TriggerAttributes</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>apache<span class="token punctuation">.</span>iotdb<span class="token punctuation">.</span>tsfile<span class="token punctuation">.</span>file<span class="token punctuation">.</span>metadata<span class="token punctuation">.</span>enums<span class="token punctuation">.</span></span><span class="token class-name">TSDataType</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>apache<span class="token punctuation">.</span>iotdb<span class="token punctuation">.</span>tsfile<span class="token punctuation">.</span>write<span class="token punctuation">.</span>record<span class="token punctuation">.</span></span><span class="token class-name">Tablet</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>apache<span class="token punctuation">.</span>iotdb<span class="token punctuation">.</span>tsfile<span class="token punctuation">.</span>write<span class="token punctuation">.</span>schema<span class="token punctuation">.</span></span><span class="token class-name">MeasurementSchema</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>slf4j<span class="token punctuation">.</span></span><span class="token class-name">Logger</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>slf4j<span class="token punctuation">.</span></span><span class="token class-name">LoggerFactory</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">java<span class="token punctuation">.</span>io<span class="token punctuation">.</span></span><span class="token class-name">IOException</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">java<span class="token punctuation">.</span>util<span class="token punctuation">.</span></span><span class="token class-name">HashMap</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">java<span class="token punctuation">.</span>util<span class="token punctuation">.</span></span><span class="token class-name">List</span></span><span class="token punctuation">;</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">ClusterAlertingExample</span> <span class="token keyword">implements</span> <span class="token class-name">Trigger</span> <span class="token punctuation">{</span>
<span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token keyword">final</span> <span class="token class-name">Logger</span> <span class="token constant">LOGGER</span> <span class="token operator">=</span> <span class="token class-name">LoggerFactory</span><span class="token punctuation">.</span><span class="token function">getLogger</span><span class="token punctuation">(</span><span class="token class-name">ClusterAlertingExample</span><span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">private</span> <span class="token keyword">final</span> <span class="token class-name">AlertManagerHandler</span> alertManagerHandler <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">AlertManagerHandler</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">private</span> <span class="token keyword">final</span> <span class="token class-name">AlertManagerConfiguration</span> alertManagerConfiguration <span class="token operator">=</span>
<span class="token keyword">new</span> <span class="token class-name">AlertManagerConfiguration</span><span class="token punctuation">(</span><span class="token string">&quot;http://127.0.0.1:9093/api/v2/alerts&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">private</span> <span class="token class-name">String</span> alertname<span class="token punctuation">;</span>
<span class="token keyword">private</span> <span class="token keyword">final</span> <span class="token class-name">HashMap</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">String</span><span class="token punctuation">,</span> <span class="token class-name">String</span><span class="token punctuation">&gt;</span></span> labels <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">HashMap</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token punctuation">&gt;</span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">private</span> <span class="token keyword">final</span> <span class="token class-name">HashMap</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">String</span><span class="token punctuation">,</span> <span class="token class-name">String</span><span class="token punctuation">&gt;</span></span> annotations <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">HashMap</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token punctuation">&gt;</span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token annotation punctuation">@Override</span>
<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">onCreate</span><span class="token punctuation">(</span><span class="token class-name">TriggerAttributes</span> attributes<span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">Exception</span> <span class="token punctuation">{</span>
alertname <span class="token operator">=</span> <span class="token string">&quot;alert_test&quot;</span><span class="token punctuation">;</span>
labels<span class="token punctuation">.</span><span class="token function">put</span><span class="token punctuation">(</span><span class="token string">&quot;series&quot;</span><span class="token punctuation">,</span> <span class="token string">&quot;root.ln.wf01.wt01.temperature&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
labels<span class="token punctuation">.</span><span class="token function">put</span><span class="token punctuation">(</span><span class="token string">&quot;value&quot;</span><span class="token punctuation">,</span> <span class="token string">&quot;&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
labels<span class="token punctuation">.</span><span class="token function">put</span><span class="token punctuation">(</span><span class="token string">&quot;severity&quot;</span><span class="token punctuation">,</span> <span class="token string">&quot;&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
annotations<span class="token punctuation">.</span><span class="token function">put</span><span class="token punctuation">(</span><span class="token string">&quot;summary&quot;</span><span class="token punctuation">,</span> <span class="token string">&quot;high temperature&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
annotations<span class="token punctuation">.</span><span class="token function">put</span><span class="token punctuation">(</span><span class="token string">&quot;description&quot;</span><span class="token punctuation">,</span> <span class="token string">&quot;{{.alertname}}: {{.series}} is {{.value}}&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
alertManagerHandler<span class="token punctuation">.</span><span class="token keyword">open</span><span class="token punctuation">(</span>alertManagerConfiguration<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token annotation punctuation">@Override</span>
<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">onDrop</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">IOException</span> <span class="token punctuation">{</span>
alertManagerHandler<span class="token punctuation">.</span><span class="token function">close</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token annotation punctuation">@Override</span>
<span class="token keyword">public</span> <span class="token keyword">boolean</span> <span class="token function">fire</span><span class="token punctuation">(</span><span class="token class-name">Tablet</span> tablet<span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">Exception</span> <span class="token punctuation">{</span>
<span class="token class-name">List</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">MeasurementSchema</span><span class="token punctuation">&gt;</span></span> measurementSchemaList <span class="token operator">=</span> tablet<span class="token punctuation">.</span><span class="token function">getSchemas</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">int</span> i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">,</span> n <span class="token operator">=</span> measurementSchemaList<span class="token punctuation">.</span><span class="token function">size</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> i <span class="token operator">&lt;</span> n<span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>measurementSchemaList<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span>i<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">getType</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">equals</span><span class="token punctuation">(</span><span class="token class-name">TSDataType</span><span class="token punctuation">.</span><span class="token constant">DOUBLE</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token comment">// for example, we only deal with the columns of Double type</span>
<span class="token keyword">double</span><span class="token punctuation">[</span><span class="token punctuation">]</span> values <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token keyword">double</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">)</span> tablet<span class="token punctuation">.</span>values<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">double</span> value <span class="token operator">:</span> values<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>value <span class="token operator">&gt;</span> <span class="token number">100.0</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token constant">LOGGER</span><span class="token punctuation">.</span><span class="token function">info</span><span class="token punctuation">(</span><span class="token string">&quot;trigger value &gt; 100&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
labels<span class="token punctuation">.</span><span class="token function">put</span><span class="token punctuation">(</span><span class="token string">&quot;value&quot;</span><span class="token punctuation">,</span> <span class="token class-name">String</span><span class="token punctuation">.</span><span class="token function">valueOf</span><span class="token punctuation">(</span>value<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
labels<span class="token punctuation">.</span><span class="token function">put</span><span class="token punctuation">(</span><span class="token string">&quot;severity&quot;</span><span class="token punctuation">,</span> <span class="token string">&quot;critical&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token class-name">AlertManagerEvent</span> alertManagerEvent <span class="token operator">=</span>
<span class="token keyword">new</span> <span class="token class-name">AlertManagerEvent</span><span class="token punctuation">(</span>alertname<span class="token punctuation">,</span> labels<span class="token punctuation">,</span> annotations<span class="token punctuation">)</span><span class="token punctuation">;</span>
alertManagerHandler<span class="token punctuation">.</span><span class="token function">onEvent</span><span class="token punctuation">(</span>alertManagerEvent<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>value <span class="token operator">&gt;</span> <span class="token number">50.0</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token constant">LOGGER</span><span class="token punctuation">.</span><span class="token function">info</span><span class="token punctuation">(</span><span class="token string">&quot;trigger value &gt; 50&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
labels<span class="token punctuation">.</span><span class="token function">put</span><span class="token punctuation">(</span><span class="token string">&quot;value&quot;</span><span class="token punctuation">,</span> <span class="token class-name">String</span><span class="token punctuation">.</span><span class="token function">valueOf</span><span class="token punctuation">(</span>value<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
labels<span class="token punctuation">.</span><span class="token function">put</span><span class="token punctuation">(</span><span class="token string">&quot;severity&quot;</span><span class="token punctuation">,</span> <span class="token string">&quot;warning&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token class-name">AlertManagerEvent</span> alertManagerEvent <span class="token operator">=</span>
<span class="token keyword">new</span> <span class="token class-name">AlertManagerEvent</span><span class="token punctuation">(</span>alertname<span class="token punctuation">,</span> labels<span class="token punctuation">,</span> annotations<span class="token punctuation">)</span><span class="token punctuation">;</span>
alertManagerHandler<span class="token punctuation">.</span><span class="token function">onEvent</span><span class="token punctuation">(</span>alertManagerEvent<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token keyword">return</span> <span class="token boolean">true</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="_3-trigger-management" tabindex="-1"><a class="header-anchor" href="#_3-trigger-management"><span>3. Trigger Management</span></a></h3><p>You can create and drop a trigger through an SQL statement, and you can also query all registered triggers through an SQL statement.</p><p><strong>We recommend that you stop insertion while creating triggers.</strong></p><h4 id="create-trigger" tabindex="-1"><a class="header-anchor" href="#create-trigger"><span>Create Trigger</span></a></h4><p>Triggers can be registered on arbitrary path patterns. The time series registered with the trigger will be listened to by the trigger. When there is data change on the series, the corresponding fire method in the trigger will be called.</p><p>Registering a trigger can be done as follows:</p><ol><li>Implement a Trigger class as described in the How to implement a Trigger chapter, assuming the class&#39;s full class name is <code>org.apache.iotdb.trigger.ClusterAlertingExample</code></li><li>Package the project into a JAR package.</li><li>Register the trigger with an SQL statement. During the creation process, the <code>validate</code> and <code>onCreate</code> interfaces of the trigger will only be called once. For details, please refer to the chapter of How to implement a Trigger.</li></ol><p>The complete SQL syntax is as follows:</p><div class="language-sql line-numbers-mode" data-ext="sql" data-title="sql"><pre class="language-sql"><code><span class="token comment">// Create Trigger</span>
createTrigger
: <span class="token keyword">CREATE</span> triggerType <span class="token keyword">TRIGGER</span> triggerName<span class="token operator">=</span>identifier triggerEventClause <span class="token keyword">ON</span> pathPattern <span class="token keyword">AS</span> className<span class="token operator">=</span>STRING_LITERAL uriClause? triggerAttributeClause?
<span class="token punctuation">;</span>
triggerType
: STATELESS <span class="token operator">|</span> STATEFUL
<span class="token punctuation">;</span>
triggerEventClause
: <span class="token punctuation">(</span>BEFORE <span class="token operator">|</span> <span class="token keyword">AFTER</span><span class="token punctuation">)</span> <span class="token keyword">INSERT</span>
<span class="token punctuation">;</span>
uriClause
: <span class="token keyword">USING</span> URI uri
<span class="token punctuation">;</span>
uri
: STRING_LITERAL
<span class="token punctuation">;</span>
triggerAttributeClause
: <span class="token keyword">WITH</span> LR_BRACKET triggerAttribute <span class="token punctuation">(</span>COMMA triggerAttribute<span class="token punctuation">)</span><span class="token operator">*</span> RR_BRACKET
<span class="token punctuation">;</span>
triggerAttribute
: <span class="token keyword">key</span><span class="token operator">=</span>attributeKey operator_eq <span class="token keyword">value</span><span class="token operator">=</span>attributeValue
<span class="token punctuation">;</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>Below is the explanation for the SQL syntax:</p><ul><li>triggerName: The trigger ID, which is globally unique and used to distinguish different triggers, is case-sensitive.</li><li>triggerType: Trigger types are divided into two categories, STATELESS and STATEFUL.</li><li>triggerEventClause: when the trigger fires, BEFORE INSERT and AFTER INSERT are supported now.</li><li>pathPattern:The path pattern the trigger listens on, can contain wildcards * and **.</li><li>className:The class name of the Trigger class.</li><li>jarLocation: Optional. When this option is not specified, by default, we consider that the DBA has placed the JAR package required to create the trigger in the trigger_root_dir directory (configuration item, default is IOTDB_HOME/ext/trigger) of each DataNode node. When this option is specified, we will download and distribute the file resource corresponding to the URI to the trigger_root_dir/install directory of each DataNode.</li><li>triggerAttributeClause: It is used to specify the parameters that need to be set when the trigger instance is created. This part is optional in the SQL syntax.</li></ul><p>Here is an example SQL statement to help you understand:</p><div class="language-sql line-numbers-mode" data-ext="sql" data-title="sql"><pre class="language-sql"><code><span class="token keyword">CREATE</span> STATELESS <span class="token keyword">TRIGGER</span> triggerTest
BEFORE <span class="token keyword">INSERT</span>
<span class="token keyword">ON</span> root<span class="token punctuation">.</span>sg<span class="token punctuation">.</span><span class="token operator">*</span><span class="token operator">*</span>
<span class="token keyword">AS</span> <span class="token string">&#39;org.apache.iotdb.trigger.ClusterAlertingExample&#39;</span>
<span class="token keyword">USING</span> URI <span class="token string">&#39;/jar/ClusterAlertingExample.jar&#39;</span>
<span class="token keyword">WITH</span> <span class="token punctuation">(</span>
<span class="token string">&quot;name&quot;</span> <span class="token operator">=</span> <span class="token string">&quot;trigger&quot;</span><span class="token punctuation">,</span>
<span class="token string">&quot;limit&quot;</span> <span class="token operator">=</span> <span class="token string">&quot;100&quot;</span>
<span class="token punctuation">)</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>The above SQL statement creates a trigger named triggerTest:</p><ul><li>The trigger is stateless.</li><li>Fires before insertion.</li><li>Listens on path pattern <a href="http://root.sg" target="_blank" rel="noopener noreferrer">root.sg<span><svg class="external-link-icon" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg><span class="external-link-icon-sr-only">open in new window</span></span></a>.**</li><li>The implemented trigger class is named <code>org.apache.iotdb.trigger.ClusterAlertingExample</code></li><li>The JAR package URI is <a href="http://jar/ClusterAlertingExample.jar" target="_blank" rel="noopener noreferrer">http://jar/ClusterAlertingExample.jar<span><svg class="external-link-icon" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg><span class="external-link-icon-sr-only">open in new window</span></span></a></li><li>When creating the trigger instance, two parameters, name and limit, are passed in.</li></ul><h4 id="drop-trigger" tabindex="-1"><a class="header-anchor" href="#drop-trigger"><span>Drop Trigger</span></a></h4><p>The trigger can be dropped by specifying the trigger ID. During the process of dropping the trigger, the <code>onDrop</code> interface of the trigger will be called only once.</p><p>The SQL syntax is:</p><div class="language-sql line-numbers-mode" data-ext="sql" data-title="sql"><pre class="language-sql"><code><span class="token comment">// Drop Trigger</span>
dropTrigger
: <span class="token keyword">DROP</span> <span class="token keyword">TRIGGER</span> triggerName<span class="token operator">=</span>identifier
<span class="token punctuation">;</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>Here is an example statement:</p><div class="language-sql line-numbers-mode" data-ext="sql" data-title="sql"><pre class="language-sql"><code><span class="token keyword">DROP</span> <span class="token keyword">TRIGGER</span> triggerTest1
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div></div></div><p>The above statement will drop the trigger with ID triggerTest1.</p><h4 id="show-trigger" tabindex="-1"><a class="header-anchor" href="#show-trigger"><span>Show Trigger</span></a></h4><p>You can query information about triggers that exist in the cluster through an SQL statement.</p><p>The SQL syntax is as follows:</p><div class="language-sql line-numbers-mode" data-ext="sql" data-title="sql"><pre class="language-sql"><code><span class="token keyword">SHOW</span> TRIGGERS
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div></div></div><p>The result set format of this statement is as follows:</p><table><thead><tr><th>TriggerName</th><th>Event</th><th>Type</th><th>State</th><th>PathPattern</th><th>ClassName</th><th>NodeId</th></tr></thead><tbody><tr><td>triggerTest1</td><td>BEFORE_INSERT / AFTER_INSERT</td><td>STATELESS / STATEFUL</td><td>INACTIVE / ACTIVE / DROPPING / TRANSFFERING</td><td>root.**</td><td>org.apache.iotdb.trigger.TriggerExample</td><td>ALL(STATELESS) / DATA_NODE_ID(STATEFUL)</td></tr></tbody></table><h4 id="trigger-state" tabindex="-1"><a class="header-anchor" href="#trigger-state"><span>Trigger State</span></a></h4><p>During the process of creating and dropping triggers in the cluster, we maintain the states of the triggers. The following is a description of these states:</p><table><thead><tr><th>State</th><th>Description</th><th>Is it recommended to insert data?</th></tr></thead><tbody><tr><td>INACTIVE</td><td>The intermediate state of executing <code>CREATE TRIGGER</code>, the cluster has just recorded the trigger information on the ConfigNode, and the trigger has not been activated on any DataNode.</td><td>NO</td></tr><tr><td>ACTIVE</td><td>Status after successful execution of <code>CREATE TRIGGE</code>, the trigger is available on all DataNodes in the cluster.</td><td>YES</td></tr><tr><td>DROPPING</td><td>Intermediate state of executing <code>DROP TRIGGER</code>, the cluster is in the process of dropping the trigger.</td><td>NO</td></tr><tr><td>TRANSFERRING</td><td>The cluster is migrating the location of this trigger instance.</td><td>NO</td></tr></tbody></table><h3 id="_4-notes" tabindex="-1"><a class="header-anchor" href="#_4-notes"><span>4. Notes</span></a></h3><ul><li>The trigger takes effect from the time of registration, and does not process the existing historical data. **That is, only insertion requests that occur after the trigger is successfully registered will be listened to by the trigger. **</li><li>The fire process of trigger is synchronous currently, so you need to ensure the efficiency of the trigger, otherwise the writing performance may be greatly affected. <strong>You need to guarantee concurrency safety of triggers yourself</strong>.</li><li>Please do no register too many triggers in the cluster. Because the trigger information is fully stored in the ConfigNode, and there is a copy of the information in all DataNodes</li><li><strong>It is recommended to stop writing when registering triggers</strong>. Registering a trigger is not an atomic operation. When registering a trigger, there will be an intermediate state in which some nodes in the cluster have registered the trigger, and some nodes have not yet registered successfully. To avoid write requests on some nodes being listened to by triggers and not being listened to on some nodes, we recommend not to perform writes when registering triggers.</li><li>When the node holding the stateful trigger instance goes down, we will try to restore the corresponding instance on another node. During the recovery process, we will call the restore interface of the trigger class once.</li><li>The trigger JAR package has a size limit, which must be less than min(<code>config_node_ratis_log_appender_buffer_size_max</code>, 2G), where <code>config_node_ratis_log_appender_buffer_size_max</code> is a configuration item. For the specific meaning, please refer to the IOTDB configuration item description.</li><li><strong>It is better not to have classes with the same full class name but different function implementations in different JAR packages.</strong> For example, trigger1 and trigger2 correspond to resources trigger1.jar and trigger2.jar respectively. If two JAR packages contain a <code>org.apache.iotdb.trigger.example.AlertListener</code> class, when <code>CREATE TRIGGER</code> uses this class, the system will randomly load the class in one of the JAR packages, which will eventually leads the inconsistent behavior of trigger and other issues.</li></ul><h3 id="_5-configuration-parameters" tabindex="-1"><a class="header-anchor" href="#_5-configuration-parameters"><span>5. Configuration Parameters</span></a></h3><table><thead><tr><th>Parameter</th><th>Meaning</th></tr></thead><tbody><tr><td><em>trigger_lib_dir</em></td><td>Directory to save the trigger jar package</td></tr><tr><td><em>stateful_trigger_retry_num_when_not_found</em></td><td>How many times will we retry to found an instance of stateful trigger on DataNodes if not found</td></tr></tbody></table><h2 id="continuous-query-cq" tabindex="-1"><a class="header-anchor" href="#continuous-query-cq"><span>CONTINUOUS QUERY (CQ)</span></a></h2><h3 id="_1-introduction" tabindex="-1"><a class="header-anchor" href="#_1-introduction"><span>1. Introduction</span></a></h3><p>Continuous queries(CQ) are queries that run automatically and periodically on realtime data and store query results in other specified time series.</p><p>Users can implement sliding window streaming computing through continuous query, such as calculating the hourly average temperature of a sequence and writing it into a new sequence. Users can customize the <code>RESAMPLE</code> clause to create different sliding windows, which can achieve a certain degree of tolerance for out-of-order data.</p><h3 id="_2-syntax" tabindex="-1"><a class="header-anchor" href="#_2-syntax"><span>2. Syntax</span></a></h3><div class="language-sql line-numbers-mode" data-ext="sql" data-title="sql"><pre class="language-sql"><code><span class="token keyword">CREATE</span> <span class="token punctuation">(</span>CONTINUOUS QUERY <span class="token operator">|</span> CQ<span class="token punctuation">)</span> <span class="token operator">&lt;</span>cq_id<span class="token operator">&gt;</span>
<span class="token punctuation">[</span>RESAMPLE
<span class="token punctuation">[</span>EVERY <span class="token operator">&lt;</span>every_interval<span class="token operator">&gt;</span><span class="token punctuation">]</span>
<span class="token punctuation">[</span>BOUNDARY <span class="token operator">&lt;</span>execution_boundary_time<span class="token operator">&gt;</span><span class="token punctuation">]</span>
<span class="token punctuation">[</span>RANGE <span class="token operator">&lt;</span>start_time_offset<span class="token operator">&gt;</span><span class="token punctuation">[</span><span class="token punctuation">,</span> end_time_offset<span class="token punctuation">]</span><span class="token punctuation">]</span>
<span class="token punctuation">]</span>
<span class="token punctuation">[</span>TIMEOUT POLICY BLOCKED<span class="token operator">|</span><span class="token keyword">DISCARD</span><span class="token punctuation">]</span>
<span class="token keyword">BEGIN</span>
<span class="token keyword">SELECT</span> CLAUSE
<span class="token keyword">INTO</span> CLAUSE
<span class="token keyword">FROM</span> CLAUSE
<span class="token punctuation">[</span><span class="token keyword">WHERE</span> CLAUSE<span class="token punctuation">]</span>
<span class="token punctuation">[</span><span class="token keyword">GROUP</span> <span class="token keyword">BY</span><span class="token punctuation">(</span><span class="token operator">&lt;</span>group_by_interval<span class="token operator">&gt;</span><span class="token punctuation">[</span><span class="token punctuation">,</span> <span class="token operator">&lt;</span>sliding_step<span class="token operator">&gt;</span><span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token punctuation">[</span><span class="token punctuation">,</span> <span class="token keyword">level</span> <span class="token operator">=</span> <span class="token operator">&lt;</span><span class="token keyword">level</span><span class="token operator">&gt;</span><span class="token punctuation">]</span><span class="token punctuation">]</span>
<span class="token punctuation">[</span><span class="token keyword">HAVING</span> CLAUSE<span class="token punctuation">]</span>
<span class="token punctuation">[</span>FILL {PREVIOUS <span class="token operator">|</span> LINEAR <span class="token operator">|</span> constant}<span class="token punctuation">]</span>
<span class="token punctuation">[</span><span class="token keyword">LIMIT</span> rowLimit <span class="token keyword">OFFSET</span> rowOffset<span class="token punctuation">]</span>
<span class="token punctuation">[</span>ALIGN <span class="token keyword">BY</span> DEVICE<span class="token punctuation">]</span>
<span class="token keyword">END</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><blockquote><p>Note:</p><ol><li>If there exists any time filters in WHERE CLAUSE, IoTDB will throw an error, because IoTDB will automatically generate a time range for the query each time it&#39;s executed.</li><li>GROUP BY TIME CLAUSE is different, it doesn&#39;t contain its original first display window parameter which is [start_time, end_time). It&#39;s still because IoTDB will automatically generate a time range for the query each time it&#39;s executed.</li><li>If there is no group by time clause in query, EVERY clause is required, otherwise IoTDB will throw an error.</li></ol></blockquote><h4 id="descriptions-of-parameters-in-cq-syntax" tabindex="-1"><a class="header-anchor" href="#descriptions-of-parameters-in-cq-syntax"><span>Descriptions of parameters in CQ syntax</span></a></h4><ul><li><code>&lt;cq_id&gt;</code> specifies the globally unique id of CQ.</li><li><code>&lt;every_interval&gt;</code> specifies the query execution time interval. We currently support the units of ns, us, ms, s, m, h, d, w, and its value should not be lower than the minimum threshold configured by the user, which is <code>continuous_query_min_every_interval</code>. It&#39;s an optional parameter, default value is set to <code>group_by_interval</code> in group by clause.</li><li><code>&lt;start_time_offset&gt;</code> specifies the start time of each query execution as <code>now()-&lt;start_time_offset&gt;</code>. We currently support the units of ns, us, ms, s, m, h, d, <a href="http://w.It" target="_blank" rel="noopener noreferrer">w.It<span><svg class="external-link-icon" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg><span class="external-link-icon-sr-only">open in new window</span></span></a>&#39;s an optional parameter, default value is set to <code>every_interval</code> in resample clause.</li><li><code>&lt;end_time_offset&gt;</code> specifies the end time of each query execution as <code>now()-&lt;end_time_offset&gt;</code>. We currently support the units of ns, us, ms, s, m, h, d, <a href="http://w.It" target="_blank" rel="noopener noreferrer">w.It<span><svg class="external-link-icon" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg><span class="external-link-icon-sr-only">open in new window</span></span></a>&#39;s an optional parameter, default value is set to <code>0</code>.</li><li><code>&lt;execution_boundary_time&gt;</code> is a date that represents the execution time of a certain cq task. <ul><li><code>&lt;execution_boundary_time&gt;</code> can be earlier than, equals to, later than <strong>current time</strong>.</li><li>This parameter is optional. If not specified, it is equal to <code>BOUNDARY 0</code></li><li><strong>The start time of the first time window</strong> is <code>&lt;execution_boundary_time&gt; - &lt;start_time_offset&gt;</code>.</li><li><strong>The end time of the first time window</strong> is <code>&lt;execution_boundary_time&gt; - &lt;end_time_offset&gt;</code>.</li><li>The <strong>time range</strong> of the <code>i (1 &lt;= i)th</code> window is <code>[&lt;execution_boundary_time&gt; - &lt;start_time_offset&gt; + (i - 1) * &lt;every_interval&gt;, &lt;execution_boundary_time&gt; - &lt;end_time_offset&gt; + (i - 1) * &lt;every_interval&gt;)</code>.</li><li>If the <strong>current time</strong> is earlier than or equal to <code>execution_boundary_time</code>, then the first execution moment of the continuous query is <code>execution_boundary_time</code>.</li><li>If the <strong>current time</strong> is later than <code>execution_boundary_time</code>, then the first execution moment of the continuous query is the first <code>execution_boundary_time + i * &lt;every_interval&gt;</code> that is later than or equal to the current time .</li></ul></li></ul><blockquote><ul><li><code>&lt;every_interval&gt;</code><code>&lt;start_time_offset&gt;</code> and <code>&lt;group_by_interval&gt;</code> should all be greater than <code>0</code>.</li><li>The value of <code>&lt;group_by_interval&gt;</code> should be less than or equal to the value of <code>&lt;start_time_offset&gt;</code>, otherwise the system will throw an error.</li><li>Users should specify the appropriate <code>&lt;start_time_offset&gt;</code> and <code>&lt;every_interval&gt;</code> according to actual needs. <ul><li>If <code>&lt;start_time_offset&gt;</code> is greater than <code>&lt;every_interval&gt;</code>, there will be partial data overlap in each query window.</li><li>If <code>&lt;start_time_offset&gt;</code> is less than <code>&lt;every_interval&gt;</code>, there may be uncovered data between each query window.</li></ul></li><li><code>start_time_offset</code> should be larger than <code>end_time_offset</code>, otherwise the system will throw an error.</li></ul></blockquote><h5 id="start-time-offset-every-interval" tabindex="-1"><a class="header-anchor" href="#start-time-offset-every-interval"><span><code>&lt;start_time_offset&gt;</code> == <code>&lt;every_interval&gt;</code></span></a></h5><figure><img src="https://alioss.timecho.com/docs/img/UserGuide/Process-Data/Continuous-Query/pic1.png?raw=true" alt="1" tabindex="0" loading="lazy"><figcaption>1</figcaption></figure><h5 id="start-time-offset-every-interval-1" tabindex="-1"><a class="header-anchor" href="#start-time-offset-every-interval-1"><span><code>&lt;start_time_offset&gt;</code> &gt; <code>&lt;every_interval&gt;</code></span></a></h5><figure><img src="https://alioss.timecho.com/docs/img/UserGuide/Process-Data/Continuous-Query/pic2.png?raw=true" alt="2" tabindex="0" loading="lazy"><figcaption>2</figcaption></figure><h5 id="start-time-offset-every-interval-2" tabindex="-1"><a class="header-anchor" href="#start-time-offset-every-interval-2"><span><code>&lt;start_time_offset&gt;</code> &lt; <code>&lt;every_interval&gt;</code></span></a></h5><figure><img src="https://alioss.timecho.com/docs/img/UserGuide/Process-Data/Continuous-Query/pic3.png?raw=true" alt="3" tabindex="0" loading="lazy"><figcaption>3</figcaption></figure><h5 id="every-interval-is-not-zero" tabindex="-1"><a class="header-anchor" href="#every-interval-is-not-zero"><span><code>&lt;every_interval&gt;</code> is not zero</span></a></h5><figure><img src="https://alioss.timecho.com/docs/img/UserGuide/Process-Data/Continuous-Query/pic4.png?raw=true" alt="4" tabindex="0" loading="lazy"><figcaption>4</figcaption></figure><ul><li><code>TIMEOUT POLICY</code> specify how we deal with the cq task whose previous time interval execution is not finished while the next execution time has reached. The default value is <code>BLOCKED</code>. <ul><li><code>BLOCKED</code> means that we will block and wait to do the current cq execution task until the previous time interval cq task finishes. If using <code>BLOCKED</code> policy, all the time intervals will be executed, but it may be behind the latest time interval.</li><li><code>DISCARD</code> means that we just discard the current cq execution task and wait for the next execution time and do the next time interval cq task. If using <code>DISCARD</code> policy, some time intervals won&#39;t be executed when the execution time of one cq task is longer than the <code>&lt;every_interval&gt;</code>. However, once a cq task is executed, it will use the latest time interval, so it can catch up at the sacrifice of some time intervals being discarded.</li></ul></li></ul><h3 id="_3-examples-of-cq" tabindex="-1"><a class="header-anchor" href="#_3-examples-of-cq"><span>3. Examples of CQ</span></a></h3><p>The examples below use the following sample data. It&#39;s a real time data stream and we can assume that the data arrives on time.</p><div class="language-text line-numbers-mode" data-ext="text" data-title="text"><pre class="language-text"><code>+-----------------------------+-----------------------------+-----------------------------+-----------------------------+-----------------------------+
| Time|root.ln.wf02.wt02.temperature|root.ln.wf02.wt01.temperature|root.ln.wf01.wt02.temperature|root.ln.wf01.wt01.temperature|
+-----------------------------+-----------------------------+-----------------------------+-----------------------------+-----------------------------+
|2021-05-11T22:18:14.598+08:00| 121.0| 72.0| 183.0| 115.0|
|2021-05-11T22:18:19.941+08:00| 0.0| 68.0| 68.0| 103.0|
|2021-05-11T22:18:24.949+08:00| 122.0| 45.0| 11.0| 14.0|
|2021-05-11T22:18:29.967+08:00| 47.0| 14.0| 59.0| 181.0|
|2021-05-11T22:18:34.979+08:00| 182.0| 113.0| 29.0| 180.0|
|2021-05-11T22:18:39.990+08:00| 42.0| 11.0| 52.0| 19.0|
|2021-05-11T22:18:44.995+08:00| 78.0| 38.0| 123.0| 52.0|
|2021-05-11T22:18:49.999+08:00| 137.0| 172.0| 135.0| 193.0|
|2021-05-11T22:18:55.003+08:00| 16.0| 124.0| 183.0| 18.0|
+-----------------------------+-----------------------------+-----------------------------+-----------------------------+-----------------------------+
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h4 id="configuring-execution-intervals" tabindex="-1"><a class="header-anchor" href="#configuring-execution-intervals"><span>Configuring execution intervals</span></a></h4><p>Use an <code>EVERY</code> interval in the <code>RESAMPLE</code> clause to specify the CQ’s execution interval, if not specific, default value is equal to <code>group_by_interval</code>.</p><div class="language-sql line-numbers-mode" data-ext="sql" data-title="sql"><pre class="language-sql"><code><span class="token keyword">CREATE</span> CONTINUOUS QUERY cq1
RESAMPLE EVERY <span class="token number">20</span>s
<span class="token keyword">BEGIN</span>
<span class="token keyword">SELECT</span> max_value<span class="token punctuation">(</span>temperature<span class="token punctuation">)</span>
<span class="token keyword">INTO</span> root<span class="token punctuation">.</span>ln<span class="token punctuation">.</span>wf02<span class="token punctuation">.</span>wt02<span class="token punctuation">(</span>temperature_max<span class="token punctuation">)</span><span class="token punctuation">,</span> root<span class="token punctuation">.</span>ln<span class="token punctuation">.</span>wf02<span class="token punctuation">.</span>wt01<span class="token punctuation">(</span>temperature_max<span class="token punctuation">)</span><span class="token punctuation">,</span> root<span class="token punctuation">.</span>ln<span class="token punctuation">.</span>wf01<span class="token punctuation">.</span>wt02<span class="token punctuation">(</span>temperature_max<span class="token punctuation">)</span><span class="token punctuation">,</span> root<span class="token punctuation">.</span>ln<span class="token punctuation">.</span>wf01<span class="token punctuation">.</span>wt01<span class="token punctuation">(</span>temperature_max<span class="token punctuation">)</span>
<span class="token keyword">FROM</span> root<span class="token punctuation">.</span>ln<span class="token punctuation">.</span><span class="token operator">*</span><span class="token punctuation">.</span><span class="token operator">*</span>
<span class="token keyword">GROUP</span> <span class="token keyword">BY</span><span class="token punctuation">(</span><span class="token number">10</span>s<span class="token punctuation">)</span>
<span class="token keyword">END</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><code>cq1</code> calculates the 10-second average of <code>temperature</code> sensor under the <code>root.ln</code> prefix path and stores the results in the <code>temperature_max</code> sensor using the same prefix path as the corresponding sensor.</p><p><code>cq1</code> executes at 20-second intervals, the same interval as the <code>EVERY</code> interval. Every 20 seconds, <code>cq1</code> runs a single query that covers the time range for the current time bucket, that is, the 20-second time bucket that intersects with <code>now()</code>.</p><p>Supposing that the current time is <code>2021-05-11T22:18:40.000+08:00</code>, we can see annotated log output about <code>cq1</code> running at DataNode if you set log level to DEBUG:</p><div class="language-text line-numbers-mode" data-ext="text" data-title="text"><pre class="language-text"><code>At **2021-05-11T22:18:40.000+08:00**, `cq1` executes a query within the time range `[2021-05-11T22:18:20, 2021-05-11T22:18:40)`.
`cq1` generate 2 lines:
&gt;
+-----------------------------+---------------------------------+---------------------------------+---------------------------------+---------------------------------+
| Time|root.ln.wf02.wt02.temperature_max|root.ln.wf02.wt01.temperature_max|root.ln.wf01.wt02.temperature_max|root.ln.wf01.wt01.temperature_max|
+-----------------------------+---------------------------------+---------------------------------+---------------------------------+---------------------------------+
|2021-05-11T22:18:20.000+08:00| 122.0| 45.0| 59.0| 181.0|
|2021-05-11T22:18:30.000+08:00| 182.0| 113.0| 52.0| 180.0|
+-----------------------------+---------------------------------+---------------------------------+---------------------------------+---------------------------------+
&gt;
At **2021-05-11T22:19:00.000+08:00**, `cq1` executes a query within the time range `[2021-05-11T22:18:40, 2021-05-11T22:19:00)`.
`cq1` generate 2 lines:
&gt;
+-----------------------------+---------------------------------+---------------------------------+---------------------------------+---------------------------------+
| Time|root.ln.wf02.wt02.temperature_max|root.ln.wf02.wt01.temperature_max|root.ln.wf01.wt02.temperature_max|root.ln.wf01.wt01.temperature_max|
+-----------------------------+---------------------------------+---------------------------------+---------------------------------+---------------------------------+
|2021-05-11T22:18:40.000+08:00| 137.0| 172.0| 135.0| 193.0|
|2021-05-11T22:18:50.000+08:00| 16.0| 124.0| 183.0| 18.0|
+-----------------------------+---------------------------------+---------------------------------+---------------------------------+---------------------------------+
&gt;
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><code>cq1</code> won&#39;t deal with data that is before the current time window which is <code>2021-05-11T22:18:20.000+08:00</code>, so here are the results:</p><div class="language-text line-numbers-mode" data-ext="text" data-title="text"><pre class="language-text"><code>&gt; SELECT temperature_max from root.ln.*.*;
+-----------------------------+---------------------------------+---------------------------------+---------------------------------+---------------------------------+
| Time|root.ln.wf02.wt02.temperature_max|root.ln.wf02.wt01.temperature_max|root.ln.wf01.wt02.temperature_max|root.ln.wf01.wt01.temperature_max|
+-----------------------------+---------------------------------+---------------------------------+---------------------------------+---------------------------------+
|2021-05-11T22:18:20.000+08:00| 122.0| 45.0| 59.0| 181.0|
|2021-05-11T22:18:30.000+08:00| 182.0| 113.0| 52.0| 180.0|
|2021-05-11T22:18:40.000+08:00| 137.0| 172.0| 135.0| 193.0|
|2021-05-11T22:18:50.000+08:00| 16.0| 124.0| 183.0| 18.0|
+-----------------------------+---------------------------------+---------------------------------+---------------------------------+---------------------------------+
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h4 id="configuring-time-range-for-resampling" tabindex="-1"><a class="header-anchor" href="#configuring-time-range-for-resampling"><span>Configuring time range for resampling</span></a></h4><p>Use <code>start_time_offset</code> in the <code>RANGE</code> clause to specify the start time of the CQ’s time range, if not specific, default value is equal to <code>EVERY</code> interval.</p><div class="language-sql line-numbers-mode" data-ext="sql" data-title="sql"><pre class="language-sql"><code><span class="token keyword">CREATE</span> CONTINUOUS QUERY cq2
RESAMPLE RANGE <span class="token number">40</span>s
<span class="token keyword">BEGIN</span>
<span class="token keyword">SELECT</span> max_value<span class="token punctuation">(</span>temperature<span class="token punctuation">)</span>
<span class="token keyword">INTO</span> root<span class="token punctuation">.</span>ln<span class="token punctuation">.</span>wf02<span class="token punctuation">.</span>wt02<span class="token punctuation">(</span>temperature_max<span class="token punctuation">)</span><span class="token punctuation">,</span> root<span class="token punctuation">.</span>ln<span class="token punctuation">.</span>wf02<span class="token punctuation">.</span>wt01<span class="token punctuation">(</span>temperature_max<span class="token punctuation">)</span><span class="token punctuation">,</span> root<span class="token punctuation">.</span>ln<span class="token punctuation">.</span>wf01<span class="token punctuation">.</span>wt02<span class="token punctuation">(</span>temperature_max<span class="token punctuation">)</span><span class="token punctuation">,</span> root<span class="token punctuation">.</span>ln<span class="token punctuation">.</span>wf01<span class="token punctuation">.</span>wt01<span class="token punctuation">(</span>temperature_max<span class="token punctuation">)</span>
<span class="token keyword">FROM</span> root<span class="token punctuation">.</span>ln<span class="token punctuation">.</span><span class="token operator">*</span><span class="token punctuation">.</span><span class="token operator">*</span>
<span class="token keyword">GROUP</span> <span class="token keyword">BY</span><span class="token punctuation">(</span><span class="token number">10</span>s<span class="token punctuation">)</span>
<span class="token keyword">END</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><code>cq2</code> calculates the 10-second average of <code>temperature</code> sensor under the <code>root.ln</code> prefix path and stores the results in the <code>temperature_max</code> sensor using the same prefix path as the corresponding sensor.</p><p><code>cq2</code> executes at 10-second intervals, the same interval as the <code>group_by_interval</code>. Every 10 seconds, <code>cq2</code> runs a single query that covers the time range between <code>now()</code> minus the <code>start_time_offset</code> and <code>now()</code> , that is, the time range between 40 seconds prior to <code>now()</code> and <code>now()</code>.</p><p>Supposing that the current time is <code>2021-05-11T22:18:40.000+08:00</code>, we can see annotated log output about <code>cq2</code> running at DataNode if you set log level to DEBUG:</p><div class="language-text line-numbers-mode" data-ext="text" data-title="text"><pre class="language-text"><code>At **2021-05-11T22:18:40.000+08:00**, `cq2` executes a query within the time range `[2021-05-11T22:18:00, 2021-05-11T22:18:40)`.
`cq2` generate 4 lines:
&gt;
+-----------------------------+---------------------------------+---------------------------------+---------------------------------+---------------------------------+
| Time|root.ln.wf02.wt02.temperature_max|root.ln.wf02.wt01.temperature_max|root.ln.wf01.wt02.temperature_max|root.ln.wf01.wt01.temperature_max|
+-----------------------------+---------------------------------+---------------------------------+---------------------------------+---------------------------------+
|2021-05-11T22:18:00.000+08:00| NULL| NULL| NULL| NULL|
|2021-05-11T22:18:10.000+08:00| 121.0| 72.0| 183.0| 115.0|
|2021-05-11T22:18:20.000+08:00| 122.0| 45.0| 59.0| 181.0|
|2021-05-11T22:18:30.000+08:00| 182.0| 113.0| 52.0| 180.0|
+-----------------------------+---------------------------------+---------------------------------+---------------------------------+---------------------------------+
&gt;
At **2021-05-11T22:18:50.000+08:00**, `cq2` executes a query within the time range `[2021-05-11T22:18:10, 2021-05-11T22:18:50)`.
`cq2` generate 4 lines:
&gt;
+-----------------------------+---------------------------------+---------------------------------+---------------------------------+---------------------------------+
| Time|root.ln.wf02.wt02.temperature_max|root.ln.wf02.wt01.temperature_max|root.ln.wf01.wt02.temperature_max|root.ln.wf01.wt01.temperature_max|
+-----------------------------+---------------------------------+---------------------------------+---------------------------------+---------------------------------+
|2021-05-11T22:18:10.000+08:00| 121.0| 72.0| 183.0| 115.0|
|2021-05-11T22:18:20.000+08:00| 122.0| 45.0| 59.0| 181.0|
|2021-05-11T22:18:30.000+08:00| 182.0| 113.0| 52.0| 180.0|
|2021-05-11T22:18:40.000+08:00| 137.0| 172.0| 135.0| 193.0|
+-----------------------------+---------------------------------+---------------------------------+---------------------------------+---------------------------------+
&gt;
At **2021-05-11T22:19:00.000+08:00**, `cq2` executes a query within the time range `[2021-05-11T22:18:20, 2021-05-11T22:19:00)`.
`cq2` generate 4 lines:
&gt;
+-----------------------------+---------------------------------+---------------------------------+---------------------------------+---------------------------------+
| Time|root.ln.wf02.wt02.temperature_max|root.ln.wf02.wt01.temperature_max|root.ln.wf01.wt02.temperature_max|root.ln.wf01.wt01.temperature_max|
+-----------------------------+---------------------------------+---------------------------------+---------------------------------+---------------------------------+
|2021-05-11T22:18:20.000+08:00| 122.0| 45.0| 59.0| 181.0|
|2021-05-11T22:18:30.000+08:00| 182.0| 113.0| 52.0| 180.0|
|2021-05-11T22:18:40.000+08:00| 137.0| 172.0| 135.0| 193.0|
|2021-05-11T22:18:50.000+08:00| 16.0| 124.0| 183.0| 18.0|
+-----------------------------+---------------------------------+---------------------------------+---------------------------------+---------------------------------+
&gt;
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><code>cq2</code> won&#39;t write lines that are all null. Notice <code>cq2</code> will also calculate the results for some time interval many times. Here are the results:</p><div class="language-text line-numbers-mode" data-ext="text" data-title="text"><pre class="language-text"><code>&gt; SELECT temperature_max from root.ln.*.*;
+-----------------------------+---------------------------------+---------------------------------+---------------------------------+---------------------------------+
| Time|root.ln.wf02.wt02.temperature_max|root.ln.wf02.wt01.temperature_max|root.ln.wf01.wt02.temperature_max|root.ln.wf01.wt01.temperature_max|
+-----------------------------+---------------------------------+---------------------------------+---------------------------------+---------------------------------+
|2021-05-11T22:18:10.000+08:00| 121.0| 72.0| 183.0| 115.0|
|2021-05-11T22:18:20.000+08:00| 122.0| 45.0| 59.0| 181.0|
|2021-05-11T22:18:30.000+08:00| 182.0| 113.0| 52.0| 180.0|
|2021-05-11T22:18:40.000+08:00| 137.0| 172.0| 135.0| 193.0|
|2021-05-11T22:18:50.000+08:00| 16.0| 124.0| 183.0| 18.0|
+-----------------------------+---------------------------------+---------------------------------+---------------------------------+---------------------------------+
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h4 id="configuring-execution-intervals-and-cq-time-ranges" tabindex="-1"><a class="header-anchor" href="#configuring-execution-intervals-and-cq-time-ranges"><span>Configuring execution intervals and CQ time ranges</span></a></h4><p>Use an <code>EVERY</code> interval and <code>RANGE</code> interval in the <code>RESAMPLE</code> clause to specify the CQ’s execution interval and the length of the CQ’s time range. And use <code>fill()</code> to change the value reported for time intervals with no data.</p><div class="language-sql line-numbers-mode" data-ext="sql" data-title="sql"><pre class="language-sql"><code><span class="token keyword">CREATE</span> CONTINUOUS QUERY cq3
RESAMPLE EVERY <span class="token number">20</span>s RANGE <span class="token number">40</span>s
<span class="token keyword">BEGIN</span>
<span class="token keyword">SELECT</span> max_value<span class="token punctuation">(</span>temperature<span class="token punctuation">)</span>
<span class="token keyword">INTO</span> root<span class="token punctuation">.</span>ln<span class="token punctuation">.</span>wf02<span class="token punctuation">.</span>wt02<span class="token punctuation">(</span>temperature_max<span class="token punctuation">)</span><span class="token punctuation">,</span> root<span class="token punctuation">.</span>ln<span class="token punctuation">.</span>wf02<span class="token punctuation">.</span>wt01<span class="token punctuation">(</span>temperature_max<span class="token punctuation">)</span><span class="token punctuation">,</span> root<span class="token punctuation">.</span>ln<span class="token punctuation">.</span>wf01<span class="token punctuation">.</span>wt02<span class="token punctuation">(</span>temperature_max<span class="token punctuation">)</span><span class="token punctuation">,</span> root<span class="token punctuation">.</span>ln<span class="token punctuation">.</span>wf01<span class="token punctuation">.</span>wt01<span class="token punctuation">(</span>temperature_max<span class="token punctuation">)</span>
<span class="token keyword">FROM</span> root<span class="token punctuation">.</span>ln<span class="token punctuation">.</span><span class="token operator">*</span><span class="token punctuation">.</span><span class="token operator">*</span>
<span class="token keyword">GROUP</span> <span class="token keyword">BY</span><span class="token punctuation">(</span><span class="token number">10</span>s<span class="token punctuation">)</span>
FILL<span class="token punctuation">(</span><span class="token number">100.0</span><span class="token punctuation">)</span>
<span class="token keyword">END</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><code>cq3</code> calculates the 10-second average of <code>temperature</code> sensor under the <code>root.ln</code> prefix path and stores the results in the <code>temperature_max</code> sensor using the same prefix path as the corresponding sensor. Where possible, it writes the value <code>100.0</code> for time intervals with no results.</p><p><code>cq3</code> executes at 20-second intervals, the same interval as the <code>EVERY</code> interval. Every 20 seconds, <code>cq3</code> runs a single query that covers the time range between <code>now()</code> minus the <code>start_time_offset</code> and <code>now()</code>, that is, the time range between 40 seconds prior to <code>now()</code> and <code>now()</code>.</p><p>Supposing that the current time is <code>2021-05-11T22:18:40.000+08:00</code>, we can see annotated log output about <code>cq3</code> running at DataNode if you set log level to DEBUG:</p><div class="language-text line-numbers-mode" data-ext="text" data-title="text"><pre class="language-text"><code>At **2021-05-11T22:18:40.000+08:00**, `cq3` executes a query within the time range `[2021-05-11T22:18:00, 2021-05-11T22:18:40)`.
`cq3` generate 4 lines:
&gt;
+-----------------------------+---------------------------------+---------------------------------+---------------------------------+---------------------------------+
| Time|root.ln.wf02.wt02.temperature_max|root.ln.wf02.wt01.temperature_max|root.ln.wf01.wt02.temperature_max|root.ln.wf01.wt01.temperature_max|
+-----------------------------+---------------------------------+---------------------------------+---------------------------------+---------------------------------+
|2021-05-11T22:18:00.000+08:00| 100.0| 100.0| 100.0| 100.0|
|2021-05-11T22:18:10.000+08:00| 121.0| 72.0| 183.0| 115.0|
|2021-05-11T22:18:20.000+08:00| 122.0| 45.0| 59.0| 181.0|
|2021-05-11T22:18:30.000+08:00| 182.0| 113.0| 52.0| 180.0|
+-----------------------------+---------------------------------+---------------------------------+---------------------------------+---------------------------------+
&gt;
At **2021-05-11T22:19:00.000+08:00**, `cq3` executes a query within the time range `[2021-05-11T22:18:20, 2021-05-11T22:19:00)`.
`cq3` generate 4 lines:
&gt;
+-----------------------------+---------------------------------+---------------------------------+---------------------------------+---------------------------------+
| Time|root.ln.wf02.wt02.temperature_max|root.ln.wf02.wt01.temperature_max|root.ln.wf01.wt02.temperature_max|root.ln.wf01.wt01.temperature_max|
+-----------------------------+---------------------------------+---------------------------------+---------------------------------+---------------------------------+
|2021-05-11T22:18:20.000+08:00| 122.0| 45.0| 59.0| 181.0|
|2021-05-11T22:18:30.000+08:00| 182.0| 113.0| 52.0| 180.0|
|2021-05-11T22:18:40.000+08:00| 137.0| 172.0| 135.0| 193.0|
|2021-05-11T22:18:50.000+08:00| 16.0| 124.0| 183.0| 18.0|
+-----------------------------+---------------------------------+---------------------------------+---------------------------------+---------------------------------+
&gt;
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>Notice that <code>cq3</code> will calculate the results for some time interval many times, so here are the results:</p><div class="language-text line-numbers-mode" data-ext="text" data-title="text"><pre class="language-text"><code>&gt; SELECT temperature_max from root.ln.*.*;
+-----------------------------+---------------------------------+---------------------------------+---------------------------------+---------------------------------+
| Time|root.ln.wf02.wt02.temperature_max|root.ln.wf02.wt01.temperature_max|root.ln.wf01.wt02.temperature_max|root.ln.wf01.wt01.temperature_max|
+-----------------------------+---------------------------------+---------------------------------+---------------------------------+---------------------------------+
|2021-05-11T22:18:00.000+08:00| 100.0| 100.0| 100.0| 100.0|
|2021-05-11T22:18:10.000+08:00| 121.0| 72.0| 183.0| 115.0|
|2021-05-11T22:18:20.000+08:00| 122.0| 45.0| 59.0| 181.0|
|2021-05-11T22:18:30.000+08:00| 182.0| 113.0| 52.0| 180.0|
|2021-05-11T22:18:40.000+08:00| 137.0| 172.0| 135.0| 193.0|
|2021-05-11T22:18:50.000+08:00| 16.0| 124.0| 183.0| 18.0|
+-----------------------------+---------------------------------+---------------------------------+---------------------------------+---------------------------------+
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h4 id="configuring-end-time-offset-for-cq-time-range" tabindex="-1"><a class="header-anchor" href="#configuring-end-time-offset-for-cq-time-range"><span>Configuring end_time_offset for CQ time range</span></a></h4><p>Use an <code>EVERY</code> interval and <code>RANGE</code> interval in the RESAMPLE clause to specify the CQ’s execution interval and the length of the CQ’s time range. And use <code>fill()</code> to change the value reported for time intervals with no data.</p><div class="language-sql line-numbers-mode" data-ext="sql" data-title="sql"><pre class="language-sql"><code><span class="token keyword">CREATE</span> CONTINUOUS QUERY cq4
RESAMPLE EVERY <span class="token number">20</span>s RANGE <span class="token number">40</span>s<span class="token punctuation">,</span> <span class="token number">20</span>s
<span class="token keyword">BEGIN</span>
<span class="token keyword">SELECT</span> max_value<span class="token punctuation">(</span>temperature<span class="token punctuation">)</span>
<span class="token keyword">INTO</span> root<span class="token punctuation">.</span>ln<span class="token punctuation">.</span>wf02<span class="token punctuation">.</span>wt02<span class="token punctuation">(</span>temperature_max<span class="token punctuation">)</span><span class="token punctuation">,</span> root<span class="token punctuation">.</span>ln<span class="token punctuation">.</span>wf02<span class="token punctuation">.</span>wt01<span class="token punctuation">(</span>temperature_max<span class="token punctuation">)</span><span class="token punctuation">,</span> root<span class="token punctuation">.</span>ln<span class="token punctuation">.</span>wf01<span class="token punctuation">.</span>wt02<span class="token punctuation">(</span>temperature_max<span class="token punctuation">)</span><span class="token punctuation">,</span> root<span class="token punctuation">.</span>ln<span class="token punctuation">.</span>wf01<span class="token punctuation">.</span>wt01<span class="token punctuation">(</span>temperature_max<span class="token punctuation">)</span>
<span class="token keyword">FROM</span> root<span class="token punctuation">.</span>ln<span class="token punctuation">.</span><span class="token operator">*</span><span class="token punctuation">.</span><span class="token operator">*</span>
<span class="token keyword">GROUP</span> <span class="token keyword">BY</span><span class="token punctuation">(</span><span class="token number">10</span>s<span class="token punctuation">)</span>
FILL<span class="token punctuation">(</span><span class="token number">100.0</span><span class="token punctuation">)</span>
<span class="token keyword">END</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><code>cq4</code> calculates the 10-second average of <code>temperature</code> sensor under the <code>root.ln</code> prefix path and stores the results in the <code>temperature_max</code> sensor using the same prefix path as the corresponding sensor. Where possible, it writes the value <code>100.0</code> for time intervals with no results.</p><p><code>cq4</code> executes at 20-second intervals, the same interval as the <code>EVERY</code> interval. Every 20 seconds, <code>cq4</code> runs a single query that covers the time range between <code>now()</code> minus the <code>start_time_offset</code> and <code>now()</code> minus the <code>end_time_offset</code>, that is, the time range between 40 seconds prior to <code>now()</code> and 20 seconds prior to <code>now()</code>.</p><p>Supposing that the current time is <code>2021-05-11T22:18:40.000+08:00</code>, we can see annotated log output about <code>cq4</code> running at DataNode if you set log level to DEBUG:</p><div class="language-text line-numbers-mode" data-ext="text" data-title="text"><pre class="language-text"><code>At **2021-05-11T22:18:40.000+08:00**, `cq4` executes a query within the time range `[2021-05-11T22:18:00, 2021-05-11T22:18:20)`.
`cq4` generate 2 lines:
&gt;
+-----------------------------+---------------------------------+---------------------------------+---------------------------------+---------------------------------+
| Time|root.ln.wf02.wt02.temperature_max|root.ln.wf02.wt01.temperature_max|root.ln.wf01.wt02.temperature_max|root.ln.wf01.wt01.temperature_max|
+-----------------------------+---------------------------------+---------------------------------+---------------------------------+---------------------------------+
|2021-05-11T22:18:00.000+08:00| 100.0| 100.0| 100.0| 100.0|
|2021-05-11T22:18:10.000+08:00| 121.0| 72.0| 183.0| 115.0|
+-----------------------------+---------------------------------+---------------------------------+---------------------------------+---------------------------------+
&gt;
At **2021-05-11T22:19:00.000+08:00**, `cq4` executes a query within the time range `[2021-05-11T22:18:20, 2021-05-11T22:18:40)`.
`cq4` generate 2 lines:
&gt;
+-----------------------------+---------------------------------+---------------------------------+---------------------------------+---------------------------------+
| Time|root.ln.wf02.wt02.temperature_max|root.ln.wf02.wt01.temperature_max|root.ln.wf01.wt02.temperature_max|root.ln.wf01.wt01.temperature_max|
+-----------------------------+---------------------------------+---------------------------------+---------------------------------+---------------------------------+
|2021-05-11T22:18:20.000+08:00| 122.0| 45.0| 59.0| 181.0|
|2021-05-11T22:18:30.000+08:00| 182.0| 113.0| 52.0| 180.0|
+-----------------------------+---------------------------------+---------------------------------+---------------------------------+---------------------------------+
&gt;
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>Notice that <code>cq4</code> will calculate the results for all time intervals only once after a delay of 20 seconds, so here are the results:</p><div class="language-text line-numbers-mode" data-ext="text" data-title="text"><pre class="language-text"><code>&gt; SELECT temperature_max from root.ln.*.*;
+-----------------------------+---------------------------------+---------------------------------+---------------------------------+---------------------------------+
| Time|root.ln.wf02.wt02.temperature_max|root.ln.wf02.wt01.temperature_max|root.ln.wf01.wt02.temperature_max|root.ln.wf01.wt01.temperature_max|
+-----------------------------+---------------------------------+---------------------------------+---------------------------------+---------------------------------+
|2021-05-11T22:18:00.000+08:00| 100.0| 100.0| 100.0| 100.0|
|2021-05-11T22:18:10.000+08:00| 121.0| 72.0| 183.0| 115.0|
|2021-05-11T22:18:20.000+08:00| 122.0| 45.0| 59.0| 181.0|
|2021-05-11T22:18:30.000+08:00| 182.0| 113.0| 52.0| 180.0|
+-----------------------------+---------------------------------+---------------------------------+---------------------------------+---------------------------------+
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h4 id="cq-without-group-by-clause" tabindex="-1"><a class="header-anchor" href="#cq-without-group-by-clause"><span>CQ without group by clause</span></a></h4><p>Use an <code>EVERY</code> interval in the <code>RESAMPLE</code> clause to specify the CQ’s execution interval and the length of the CQ’s time range.</p><div class="language-sql line-numbers-mode" data-ext="sql" data-title="sql"><pre class="language-sql"><code><span class="token keyword">CREATE</span> CONTINUOUS QUERY cq5
RESAMPLE EVERY <span class="token number">20</span>s
<span class="token keyword">BEGIN</span>
<span class="token keyword">SELECT</span> temperature <span class="token operator">+</span> <span class="token number">1</span>
<span class="token keyword">INTO</span> root<span class="token punctuation">.</span>precalculated_sg<span class="token punctuation">.</span>::<span class="token punctuation">(</span>temperature<span class="token punctuation">)</span>
<span class="token keyword">FROM</span> root<span class="token punctuation">.</span>ln<span class="token punctuation">.</span><span class="token operator">*</span><span class="token punctuation">.</span><span class="token operator">*</span>
align <span class="token keyword">by</span> device
<span class="token keyword">END</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><code>cq5</code> calculates the <code>temperature + 1</code> under the <code>root.ln</code> prefix path and stores the results in the <code>root.precalculated_sg</code> database. Sensors use the same prefix path as the corresponding sensor.</p><p><code>cq5</code> executes at 20-second intervals, the same interval as the <code>EVERY</code> interval. Every 20 seconds, <code>cq5</code> runs a single query that covers the time range for the current time bucket, that is, the 20-second time bucket that intersects with <code>now()</code>.</p><p>Supposing that the current time is <code>2021-05-11T22:18:40.000+08:00</code>, we can see annotated log output about <code>cq5</code> running at DataNode if you set log level to DEBUG:</p><div class="language-text line-numbers-mode" data-ext="text" data-title="text"><pre class="language-text"><code>At **2021-05-11T22:18:40.000+08:00**, `cq5` executes a query within the time range `[2021-05-11T22:18:20, 2021-05-11T22:18:40)`.
`cq5` generate 16 lines:
&gt;
+-----------------------------+-------------------------------+-----------+
| Time| Device|temperature|
+-----------------------------+-------------------------------+-----------+
|2021-05-11T22:18:24.949+08:00|root.precalculated_sg.wf02.wt02| 123.0|
|2021-05-11T22:18:29.967+08:00|root.precalculated_sg.wf02.wt02| 48.0|
|2021-05-11T22:18:34.979+08:00|root.precalculated_sg.wf02.wt02| 183.0|
|2021-05-11T22:18:39.990+08:00|root.precalculated_sg.wf02.wt02| 45.0|
|2021-05-11T22:18:24.949+08:00|root.precalculated_sg.wf02.wt01| 46.0|
|2021-05-11T22:18:29.967+08:00|root.precalculated_sg.wf02.wt01| 15.0|
|2021-05-11T22:18:34.979+08:00|root.precalculated_sg.wf02.wt01| 114.0|
|2021-05-11T22:18:39.990+08:00|root.precalculated_sg.wf02.wt01| 12.0|
|2021-05-11T22:18:24.949+08:00|root.precalculated_sg.wf01.wt02| 12.0|
|2021-05-11T22:18:29.967+08:00|root.precalculated_sg.wf01.wt02| 60.0|
|2021-05-11T22:18:34.979+08:00|root.precalculated_sg.wf01.wt02| 30.0|
|2021-05-11T22:18:39.990+08:00|root.precalculated_sg.wf01.wt02| 53.0|
|2021-05-11T22:18:24.949+08:00|root.precalculated_sg.wf01.wt01| 15.0|
|2021-05-11T22:18:29.967+08:00|root.precalculated_sg.wf01.wt01| 182.0|
|2021-05-11T22:18:34.979+08:00|root.precalculated_sg.wf01.wt01| 181.0|
|2021-05-11T22:18:39.990+08:00|root.precalculated_sg.wf01.wt01| 20.0|
+-----------------------------+-------------------------------+-----------+
&gt;
At **2021-05-11T22:19:00.000+08:00**, `cq5` executes a query within the time range `[2021-05-11T22:18:40, 2021-05-11T22:19:00)`.
`cq5` generate 12 lines:
&gt;
+-----------------------------+-------------------------------+-----------+
| Time| Device|temperature|
+-----------------------------+-------------------------------+-----------+
|2021-05-11T22:18:44.995+08:00|root.precalculated_sg.wf02.wt02| 79.0|
|2021-05-11T22:18:49.999+08:00|root.precalculated_sg.wf02.wt02| 138.0|
|2021-05-11T22:18:55.003+08:00|root.precalculated_sg.wf02.wt02| 17.0|
|2021-05-11T22:18:44.995+08:00|root.precalculated_sg.wf02.wt01| 39.0|
|2021-05-11T22:18:49.999+08:00|root.precalculated_sg.wf02.wt01| 173.0|
|2021-05-11T22:18:55.003+08:00|root.precalculated_sg.wf02.wt01| 125.0|
|2021-05-11T22:18:44.995+08:00|root.precalculated_sg.wf01.wt02| 124.0|
|2021-05-11T22:18:49.999+08:00|root.precalculated_sg.wf01.wt02| 136.0|
|2021-05-11T22:18:55.003+08:00|root.precalculated_sg.wf01.wt02| 184.0|
|2021-05-11T22:18:44.995+08:00|root.precalculated_sg.wf01.wt01| 53.0|
|2021-05-11T22:18:49.999+08:00|root.precalculated_sg.wf01.wt01| 194.0|
|2021-05-11T22:18:55.003+08:00|root.precalculated_sg.wf01.wt01| 19.0|
+-----------------------------+-------------------------------+-----------+
&gt;
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><code>cq5</code> won&#39;t deal with data that is before the current time window which is <code>2021-05-11T22:18:20.000+08:00</code>, so here are the results:</p><div class="language-text line-numbers-mode" data-ext="text" data-title="text"><pre class="language-text"><code>&gt; SELECT temperature from root.precalculated_sg.*.* align by device;
+-----------------------------+-------------------------------+-----------+
| Time| Device|temperature|
+-----------------------------+-------------------------------+-----------+
|2021-05-11T22:18:24.949+08:00|root.precalculated_sg.wf02.wt02| 123.0|
|2021-05-11T22:18:29.967+08:00|root.precalculated_sg.wf02.wt02| 48.0|
|2021-05-11T22:18:34.979+08:00|root.precalculated_sg.wf02.wt02| 183.0|
|2021-05-11T22:18:39.990+08:00|root.precalculated_sg.wf02.wt02| 45.0|
|2021-05-11T22:18:44.995+08:00|root.precalculated_sg.wf02.wt02| 79.0|
|2021-05-11T22:18:49.999+08:00|root.precalculated_sg.wf02.wt02| 138.0|
|2021-05-11T22:18:55.003+08:00|root.precalculated_sg.wf02.wt02| 17.0|
|2021-05-11T22:18:24.949+08:00|root.precalculated_sg.wf02.wt01| 46.0|
|2021-05-11T22:18:29.967+08:00|root.precalculated_sg.wf02.wt01| 15.0|
|2021-05-11T22:18:34.979+08:00|root.precalculated_sg.wf02.wt01| 114.0|
|2021-05-11T22:18:39.990+08:00|root.precalculated_sg.wf02.wt01| 12.0|
|2021-05-11T22:18:44.995+08:00|root.precalculated_sg.wf02.wt01| 39.0|
|2021-05-11T22:18:49.999+08:00|root.precalculated_sg.wf02.wt01| 173.0|
|2021-05-11T22:18:55.003+08:00|root.precalculated_sg.wf02.wt01| 125.0|
|2021-05-11T22:18:24.949+08:00|root.precalculated_sg.wf01.wt02| 12.0|
|2021-05-11T22:18:29.967+08:00|root.precalculated_sg.wf01.wt02| 60.0|
|2021-05-11T22:18:34.979+08:00|root.precalculated_sg.wf01.wt02| 30.0|
|2021-05-11T22:18:39.990+08:00|root.precalculated_sg.wf01.wt02| 53.0|
|2021-05-11T22:18:44.995+08:00|root.precalculated_sg.wf01.wt02| 124.0|
|2021-05-11T22:18:49.999+08:00|root.precalculated_sg.wf01.wt02| 136.0|
|2021-05-11T22:18:55.003+08:00|root.precalculated_sg.wf01.wt02| 184.0|
|2021-05-11T22:18:24.949+08:00|root.precalculated_sg.wf01.wt01| 15.0|
|2021-05-11T22:18:29.967+08:00|root.precalculated_sg.wf01.wt01| 182.0|
|2021-05-11T22:18:34.979+08:00|root.precalculated_sg.wf01.wt01| 181.0|
|2021-05-11T22:18:39.990+08:00|root.precalculated_sg.wf01.wt01| 20.0|
|2021-05-11T22:18:44.995+08:00|root.precalculated_sg.wf01.wt01| 53.0|
|2021-05-11T22:18:49.999+08:00|root.precalculated_sg.wf01.wt01| 194.0|
|2021-05-11T22:18:55.003+08:00|root.precalculated_sg.wf01.wt01| 19.0|
+-----------------------------+-------------------------------+-----------+
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="_4-cq-management" tabindex="-1"><a class="header-anchor" href="#_4-cq-management"><span>4. CQ Management</span></a></h3><h4 id="listing-continuous-queries" tabindex="-1"><a class="header-anchor" href="#listing-continuous-queries"><span>Listing continuous queries</span></a></h4><p>List every CQ on the IoTDB Cluster with:</p><div class="language-sql line-numbers-mode" data-ext="sql" data-title="sql"><pre class="language-sql"><code><span class="token keyword">SHOW</span> <span class="token punctuation">(</span>CONTINUOUS QUERIES <span class="token operator">|</span> CQS<span class="token punctuation">)</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div></div></div><p><code>SHOW (CONTINUOUS QUERIES | CQS)</code> order results by <code>cq_id</code>.</p><h5 id="examples" tabindex="-1"><a class="header-anchor" href="#examples"><span>Examples</span></a></h5><div class="language-sql line-numbers-mode" data-ext="sql" data-title="sql"><pre class="language-sql"><code><span class="token keyword">SHOW</span> CONTINUOUS QUERIES<span class="token punctuation">;</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div></div></div><p>we will get:</p><table><thead><tr><th style="text-align:left;">cq_id</th><th>query</th><th>state</th></tr></thead><tbody><tr><td style="text-align:left;">s1_count_cq</td><td>CREATE CQ s1_count_cq<br>BEGIN<br>SELECT count(s1)<br>INTO root.sg_count.d.count_s1<br>FROM root.sg.d<br>GROUP BY(30m)<br>END</td><td>active</td></tr></tbody></table><h4 id="dropping-continuous-queries" tabindex="-1"><a class="header-anchor" href="#dropping-continuous-queries"><span>Dropping continuous queries</span></a></h4><p>Drop a CQ with a specific <code>cq_id</code>:</p><div class="language-sql line-numbers-mode" data-ext="sql" data-title="sql"><pre class="language-sql"><code><span class="token keyword">DROP</span> <span class="token punctuation">(</span>CONTINUOUS QUERY <span class="token operator">|</span> CQ<span class="token punctuation">)</span> <span class="token operator">&lt;</span>cq_id<span class="token operator">&gt;</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div></div></div><p>DROP CQ returns an empty result.</p><h5 id="examples-1" tabindex="-1"><a class="header-anchor" href="#examples-1"><span>Examples</span></a></h5><p>Drop the CQ named <code>s1_count_cq</code>:</p><div class="language-sql line-numbers-mode" data-ext="sql" data-title="sql"><pre class="language-sql"><code><span class="token keyword">DROP</span> CONTINUOUS QUERY s1_count_cq<span class="token punctuation">;</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div></div></div><h4 id="altering-continuous-queries" tabindex="-1"><a class="header-anchor" href="#altering-continuous-queries"><span>Altering continuous queries</span></a></h4><p>CQs can&#39;t be altered once they&#39;re created. To change a CQ, you must <code>DROP</code> and re<code>CREATE</code> it with the updated settings.</p><h3 id="_5-cq-use-cases" tabindex="-1"><a class="header-anchor" href="#_5-cq-use-cases"><span>5. CQ Use Cases</span></a></h3><h4 id="downsampling-and-data-retention" tabindex="-1"><a class="header-anchor" href="#downsampling-and-data-retention"><span>Downsampling and Data Retention</span></a></h4><p>Use CQs with <code>TTL</code> set on database in IoTDB to mitigate storage concerns. Combine CQs and <code>TTL</code> to automatically downsample high precision data to a lower precision and remove the dispensable, high precision data from the database.</p><h4 id="recalculating-expensive-queries" tabindex="-1"><a class="header-anchor" href="#recalculating-expensive-queries"><span>Recalculating expensive queries</span></a></h4><p>Shorten query runtimes by pre-calculating expensive queries with CQs. Use a CQ to automatically downsample commonly-queried, high precision data to a lower precision. Queries on lower precision data require fewer resources and return faster.</p><blockquote><p>Pre-calculate queries for your preferred graphing tool to accelerate the population of graphs and dashboards.</p></blockquote><h4 id="substituting-for-sub-query" tabindex="-1"><a class="header-anchor" href="#substituting-for-sub-query"><span>Substituting for sub-query</span></a></h4><p>IoTDB does not support sub queries. We can get the same functionality by creating a CQ as a sub query and store its result into other time series and then querying from those time series again will be like doing nested sub query.</p><h5 id="example-1" tabindex="-1"><a class="header-anchor" href="#example-1"><span>Example</span></a></h5><p>IoTDB does not accept the following query with a nested sub query. The query calculates the average number of non-null values of <code>s1</code> at 30 minute intervals:</p><div class="language-sql line-numbers-mode" data-ext="sql" data-title="sql"><pre class="language-sql"><code><span class="token keyword">SELECT</span> <span class="token function">avg</span><span class="token punctuation">(</span>count_s1<span class="token punctuation">)</span> <span class="token keyword">from</span> <span class="token punctuation">(</span><span class="token keyword">select</span> <span class="token function">count</span><span class="token punctuation">(</span>s1<span class="token punctuation">)</span> <span class="token keyword">as</span> count_s1 <span class="token keyword">from</span> root<span class="token punctuation">.</span>sg<span class="token punctuation">.</span>d <span class="token keyword">group</span> <span class="token keyword">by</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token function">now</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token number">30</span>m<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div></div></div><p>To get the same results:</p><p><strong>1. Create a CQ</strong></p><p>This step performs the nested sub query in from clause of the query above. The following CQ automatically calculates the number of non-null values of <code>s1</code> at 30 minute intervals and writes those counts into the new <code>root.sg_count.d.count_s1</code> time series.</p><div class="language-sql line-numbers-mode" data-ext="sql" data-title="sql"><pre class="language-sql"><code><span class="token keyword">CREATE</span> CQ s1_count_cq
<span class="token keyword">BEGIN</span>
<span class="token keyword">SELECT</span> <span class="token function">count</span><span class="token punctuation">(</span>s1<span class="token punctuation">)</span>
<span class="token keyword">INTO</span> root<span class="token punctuation">.</span>sg_count<span class="token punctuation">.</span>d<span class="token punctuation">(</span>count_s1<span class="token punctuation">)</span>
<span class="token keyword">FROM</span> root<span class="token punctuation">.</span>sg<span class="token punctuation">.</span>d
<span class="token keyword">GROUP</span> <span class="token keyword">BY</span><span class="token punctuation">(</span><span class="token number">30</span>m<span class="token punctuation">)</span>
<span class="token keyword">END</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>2. Query the CQ results</strong></p><p>Next step performs the avg([...]) part of the outer query above.</p><p>Query the data in the time series <code>root.sg_count.d.count_s1</code> to calculate the average of it:</p><div class="language-sql line-numbers-mode" data-ext="sql" data-title="sql"><pre class="language-sql"><code><span class="token keyword">SELECT</span> <span class="token function">avg</span><span class="token punctuation">(</span>count_s1<span class="token punctuation">)</span> <span class="token keyword">from</span> root<span class="token punctuation">.</span>sg_count<span class="token punctuation">.</span>d<span class="token punctuation">;</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div></div></div><h3 id="_6-system-parameter-configuration" tabindex="-1"><a class="header-anchor" href="#_6-system-parameter-configuration"><span>6. System Parameter Configuration</span></a></h3><table><thead><tr><th style="text-align:left;">Name</th><th>Description</th><th>Data Type</th><th>Default Value</th></tr></thead><tbody><tr><td style="text-align:left;"><code>continuous_query_submit_thread</code></td><td>The number of threads in the scheduled thread pool that submit continuous query tasks periodically</td><td>int32</td><td>2</td></tr><tr><td style="text-align:left;"><code>continuous_query_min_every_interval_in_ms</code></td><td>The minimum value of the continuous query execution time interval</td><td>duration</td><td>1000</td></tr></tbody></table><h2 id="user-defined-function-udf" tabindex="-1"><a class="header-anchor" href="#user-defined-function-udf"><span>USER-DEFINED FUNCTION (UDF)</span></a></h2><p>IoTDB provides a variety of built-in functions to meet your computing needs, and you can also create user defined functions to meet more computing needs.</p><p>This document describes how to write, register and use a UDF.</p><h3 id="udf-types" tabindex="-1"><a class="header-anchor" href="#udf-types"><span>UDF Types</span></a></h3><p>In IoTDB, you can expand two types of UDF:</p><table><thead><tr><th>UDF Class</th><th>Description</th></tr></thead><tbody><tr><td>UDTF(User Defined Timeseries Generating Function)</td><td>This type of function can take <strong>multiple</strong> time series as input, and output <strong>one</strong> time series, which can have any number of data points.</td></tr><tr><td>UDAF(User Defined Aggregation Function)</td><td>Custom Aggregation Functions. This type of function can take one time series as input, and output <strong>one</strong> aggregated data point for each group based on the GROUP BY type.</td></tr></tbody></table><h3 id="udf-development-dependencies" tabindex="-1"><a class="header-anchor" href="#udf-development-dependencies"><span>UDF Development Dependencies</span></a></h3><p>If you use <a href="http://search.maven.org/" target="_blank" rel="noopener noreferrer">Maven<span><svg class="external-link-icon" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg><span class="external-link-icon-sr-only">open in new window</span></span></a>, you can search for the development dependencies listed below from the <a href="http://search.maven.org/" target="_blank" rel="noopener noreferrer">Maven repository<span><svg class="external-link-icon" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg><span class="external-link-icon-sr-only">open in new window</span></span></a> . Please note that you must select the same dependency version as the target IoTDB server version for development.</p><div class="language-xml line-numbers-mode" data-ext="xml" data-title="xml"><pre class="language-xml"><code><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dependency</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>groupId</span><span class="token punctuation">&gt;</span></span>org.apache.iotdb<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>groupId</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">&gt;</span></span>udf-api<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>version</span><span class="token punctuation">&gt;</span></span>1.0.0<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>version</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>scope</span><span class="token punctuation">&gt;</span></span>provided<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>scope</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dependency</span><span class="token punctuation">&gt;</span></span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="udtf-user-defined-timeseries-generating-function" tabindex="-1"><a class="header-anchor" href="#udtf-user-defined-timeseries-generating-function"><span>UDTF(User Defined Timeseries Generating Function)</span></a></h3><p>To write a UDTF, you need to inherit the <code>org.apache.iotdb.udf.api.UDTF</code> class, and at least implement the <code>beforeStart</code> method and a <code>transform</code> method.</p><p>The following table shows all the interfaces available for user implementation.</p><table><thead><tr><th style="text-align:left;">Interface definition</th><th style="text-align:left;">Description</th><th>Required to Implement</th></tr></thead><tbody><tr><td style="text-align:left;"><code>void validate(UDFParameterValidator validator) throws Exception</code></td><td style="text-align:left;">This method is mainly used to validate <code>UDFParameters</code> and it is executed before <code>beforeStart(UDFParameters, UDTFConfigurations)</code> is called.</td><td>Optional</td></tr><tr><td style="text-align:left;"><code>void beforeStart(UDFParameters parameters, UDTFConfigurations configurations) throws Exception</code></td><td style="text-align:left;">The initialization method to call the user-defined initialization behavior before a UDTF processes the input data. Every time a user executes a UDTF query, the framework will construct a new UDF instance, and <code>beforeStart</code> will be called.</td><td>Required</td></tr><tr><td style="text-align:left;"><code>void transform(Row row, PointCollector collector) throws Exception</code></td><td style="text-align:left;">This method is called by the framework. This data processing method will be called when you choose to use the <code>RowByRowAccessStrategy</code> strategy (set in <code>beforeStart</code>) to consume raw data. Input data is passed in by <code>Row</code>, and the transformation result should be output by <code>PointCollector</code>. You need to call the data collection method provided by <code>collector</code> to determine the output data.</td><td>Required to implement at least one <code>transform</code> method</td></tr><tr><td style="text-align:left;"><code>void transform(RowWindow rowWindow, PointCollector collector) throws Exception</code></td><td style="text-align:left;">This method is called by the framework. This data processing method will be called when you choose to use the <code>SlidingSizeWindowAccessStrategy</code> or <code>SlidingTimeWindowAccessStrategy</code> strategy (set in <code>beforeStart</code>) to consume raw data. Input data is passed in by <code>RowWindow</code>, and the transformation result should be output by <code>PointCollector</code>. You need to call the data collection method provided by <code>collector</code> to determine the output data.</td><td>Required to implement at least one <code>transform</code> method</td></tr><tr><td style="text-align:left;"><code>void terminate(PointCollector collector) throws Exception</code></td><td style="text-align:left;">This method is called by the framework. This method will be called once after all <code>transform</code> calls have been executed. In a single UDF query, this method will and will only be called once. You need to call the data collection method provided by <code>collector</code> to determine the output data.</td><td>Optional</td></tr><tr><td style="text-align:left;"><code>void beforeDestroy() </code></td><td style="text-align:left;">This method is called by the framework after the last input data is processed, and will only be called once in the life cycle of each UDF instance.</td><td>Optional</td></tr></tbody></table><p>In the life cycle of a UDTF instance, the calling sequence of each method is as follows:</p><ol><li><code>void validate(UDFParameterValidator validator) throws Exception</code></li><li><code>void beforeStart(UDFParameters parameters, UDTFConfigurations configurations) throws Exception</code></li><li><code>void transform(Row row, PointCollector collector) throws Exception</code> or <code>void transform(RowWindow rowWindow, PointCollector collector) throws Exception</code></li><li><code>void terminate(PointCollector collector) throws Exception</code></li><li><code>void beforeDestroy() </code></li></ol><p>Note that every time the framework executes a UDTF query, a new UDF instance will be constructed. When the query ends, the corresponding instance will be destroyed. Therefore, the internal data of the instances in different UDTF queries (even in the same SQL statement) are isolated. You can maintain some state data in the UDTF without considering the influence of concurrency and other factors.</p><p>The usage of each interface will be described in detail below.</p><h4 id="void-validate-udfparametervalidator-validator-throws-exception" tabindex="-1"><a class="header-anchor" href="#void-validate-udfparametervalidator-validator-throws-exception"><span>void validate(UDFParameterValidator validator) throws Exception</span></a></h4><p>The <code>validate</code> method is used to validate the parameters entered by the user.</p><p>In this method, you can limit the number and types of input time series, check the attributes of user input, or perform any custom verification.</p><p>Please refer to the Javadoc for the usage of <code>UDFParameterValidator</code>.</p><h4 id="void-beforestart-udfparameters-parameters-udtfconfigurations-configurations-throws-exception" tabindex="-1"><a class="header-anchor" href="#void-beforestart-udfparameters-parameters-udtfconfigurations-configurations-throws-exception"><span>void beforeStart(UDFParameters parameters, UDTFConfigurations configurations) throws Exception</span></a></h4><p>This method is mainly used to customize UDTF. In this method, the user can do the following things:</p><ol><li>Use UDFParameters to get the time series paths and parse key-value pair attributes entered by the user.</li><li>Set the strategy to access the raw data and set the output data type in UDTFConfigurations.</li><li>Create resources, such as establishing external connections, opening files, etc.</li></ol><h5 id="udfparameters" tabindex="-1"><a class="header-anchor" href="#udfparameters"><span>UDFParameters</span></a></h5><p><code>UDFParameters</code> is used to parse UDF parameters in SQL statements (the part in parentheses after the UDF function name in SQL). The input parameters have two parts. The first part is data types of the time series that the UDF needs to process, and the second part is the key-value pair attributes for customization. Only the second part can be empty.</p><p>Example:</p><div class="language-sql line-numbers-mode" data-ext="sql" data-title="sql"><pre class="language-sql"><code><span class="token keyword">SELECT</span> UDF<span class="token punctuation">(</span>s1<span class="token punctuation">,</span> s2<span class="token punctuation">,</span> <span class="token string">&#39;key1&#39;</span><span class="token operator">=</span><span class="token string">&#39;iotdb&#39;</span><span class="token punctuation">,</span> <span class="token string">&#39;key2&#39;</span><span class="token operator">=</span><span class="token string">&#39;123.45&#39;</span><span class="token punctuation">)</span> <span class="token keyword">FROM</span> root<span class="token punctuation">.</span>sg<span class="token punctuation">.</span>d<span class="token punctuation">;</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div></div></div><p>Usage:</p><div class="language-java line-numbers-mode" data-ext="java" data-title="java"><pre class="language-java"><code><span class="token keyword">void</span> <span class="token function">beforeStart</span><span class="token punctuation">(</span><span class="token class-name">UDFParameters</span> parameters<span class="token punctuation">,</span> <span class="token class-name">UDTFConfigurations</span> configurations<span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">Exception</span> <span class="token punctuation">{</span>
<span class="token class-name">String</span> stringValue <span class="token operator">=</span> parameters<span class="token punctuation">.</span><span class="token function">getString</span><span class="token punctuation">(</span><span class="token string">&quot;key1&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// iotdb</span>
<span class="token class-name">Float</span> floatValue <span class="token operator">=</span> parameters<span class="token punctuation">.</span><span class="token function">getFloat</span><span class="token punctuation">(</span><span class="token string">&quot;key2&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 123.45</span>
<span class="token class-name">Double</span> doubleValue <span class="token operator">=</span> parameters<span class="token punctuation">.</span><span class="token function">getDouble</span><span class="token punctuation">(</span><span class="token string">&quot;key3&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// null</span>
<span class="token keyword">int</span> intValue <span class="token operator">=</span> parameters<span class="token punctuation">.</span><span class="token function">getIntOrDefault</span><span class="token punctuation">(</span><span class="token string">&quot;key4&quot;</span><span class="token punctuation">,</span> <span class="token number">678</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 678</span>
<span class="token comment">// do something</span>
<span class="token comment">// configurations</span>
<span class="token comment">// ...</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h5 id="udtfconfigurations" tabindex="-1"><a class="header-anchor" href="#udtfconfigurations"><span>UDTFConfigurations</span></a></h5><p>You must use <code>UDTFConfigurations</code> to specify the strategy used by UDF to access raw data and the type of output sequence.</p><p>Usage:</p><div class="language-java line-numbers-mode" data-ext="java" data-title="java"><pre class="language-java"><code><span class="token keyword">void</span> <span class="token function">beforeStart</span><span class="token punctuation">(</span><span class="token class-name">UDFParameters</span> parameters<span class="token punctuation">,</span> <span class="token class-name">UDTFConfigurations</span> configurations<span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">Exception</span> <span class="token punctuation">{</span>
<span class="token comment">// parameters</span>
<span class="token comment">// ...</span>
<span class="token comment">// configurations</span>
configurations
<span class="token punctuation">.</span><span class="token function">setAccessStrategy</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">RowByRowAccessStrategy</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">setOutputDataType</span><span class="token punctuation">(</span><span class="token class-name">Type</span><span class="token punctuation">.</span><span class="token constant">INT32</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>The <code>setAccessStrategy</code> method is used to set the UDF&#39;s strategy for accessing the raw data, and the <code>setOutputDataType</code> method is used to set the data type of the output sequence.</p><h6 id="setaccessstrategy" tabindex="-1"><a class="header-anchor" href="#setaccessstrategy"><span>setAccessStrategy</span></a></h6><p>Note that the raw data access strategy you set here determines which <code>transform</code> method the framework will call. Please implement the <code>transform</code> method corresponding to the raw data access strategy. Of course, you can also dynamically decide which strategy to set based on the attribute parameters parsed by <code>UDFParameters</code>. Therefore, two <code>transform</code> methods are also allowed to be implemented in one UDF.</p><p>The following are the strategies you can set:</p><table><thead><tr><th style="text-align:left;">Interface definition</th><th style="text-align:left;">Description</th><th>The <code>transform</code> Method to Call</th></tr></thead><tbody><tr><td style="text-align:left;"><code>RowByRowAccessStrategy</code></td><td style="text-align:left;">Process raw data row by row. The framework calls the <code>transform</code> method once for each row of raw data input. When UDF has only one input sequence, a row of input is one data point in the input sequence. When UDF has multiple input sequences, one row of input is a result record of the raw query (aligned by time) on these input sequences. (In a row, there may be a column with a value of <code>null</code>, but not all of them are <code>null</code>)</td><td><code>void transform(Row row, PointCollector collector) throws Exception</code></td></tr><tr><td style="text-align:left;"><code>SlidingTimeWindowAccessStrategy</code></td><td style="text-align:left;">Process a batch of data in a fixed time interval each time. We call the container of a data batch a window. The framework calls the <code>transform</code> method once for each raw data input window. There may be multiple rows of data in a window, and each row is a result record of the raw query (aligned by time) on these input sequences. (In a row, there may be a column with a value of <code>null</code>, but not all of them are <code>null</code>)</td><td><code>void transform(RowWindow rowWindow, PointCollector collector) throws Exception</code></td></tr><tr><td style="text-align:left;"><code>SlidingSizeWindowAccessStrategy</code></td><td style="text-align:left;">The raw data is processed batch by batch, and each batch contains a fixed number of raw data rows (except the last batch). We call the container of a data batch a window. The framework calls the <code>transform</code> method once for each raw data input window. There may be multiple rows of data in a window, and each row is a result record of the raw query (aligned by time) on these input sequences. (In a row, there may be a column with a value of <code>null</code>, but not all of them are <code>null</code>)</td><td><code>void transform(RowWindow rowWindow, PointCollector collector) throws Exception</code></td></tr><tr><td style="text-align:left;"><code>SessionTimeWindowAccessStrategy</code></td><td style="text-align:left;">The raw data is processed batch by batch. We call the container of a data batch a window. The time interval between each two windows is greater than or equal to the <code>sessionGap</code> given by the user. The framework calls the <code>transform</code> method once for each raw data input window. There may be multiple rows of data in a window, and each row is a result record of the raw query (aligned by time) on these input sequences. (In a row, there may be a column with a value of <code>null</code>, but not all of them are <code>null</code>)</td><td><code>void transform(RowWindow rowWindow, PointCollector collector) throws Exception</code></td></tr><tr><td style="text-align:left;"><code>StateWindowAccessStrategy</code></td><td style="text-align:left;">The raw data is processed batch by batch. We call the container of a data batch a window. In the state window, for text type or boolean type data, each value of the point in window is equal to the value of the first point in the window, and for numerical data, the distance between each value of the point in window and the value of the first point in the window is less than the threshold <code>delta</code> given by the user. The framework calls the <code>transform</code> method once for each raw data input window. There may be multiple rows of data in a window. Currently, we only support state window for one measurement, that is, a column of data.</td><td><code>void transform(RowWindow rowWindow, PointCollector collector) throws Exception</code></td></tr></tbody></table><p><code>RowByRowAccessStrategy</code>: The construction of <code>RowByRowAccessStrategy</code> does not require any parameters.</p><p>The <code>SlidingTimeWindowAccessStrategy</code> is shown schematically below.<br><img style="width:100%;max-width:800px;max-height:600px;margin-left:auto;margin-right:auto;display:block;" src="https://alioss.timecho.com/docs/img/UserGuide/Process-Data/UDF-User-Defined-Function/timeWindow.png"></p><p><code>SlidingTimeWindowAccessStrategy</code>: <code>SlidingTimeWindowAccessStrategy</code> has many constructors, you can pass 3 types of parameters to them:</p><ul><li>Parameter 1: The display window on the time axis</li><li>Parameter 2: Time interval for dividing the time axis (should be positive)</li><li>Parameter 3: Time sliding step (not required to be greater than or equal to the time interval, but must be a positive number)</li></ul><p>The first type of parameters are optional. If the parameters are not provided, the beginning time of the display window will be set to the same as the minimum timestamp of the query result set, and the ending time of the display window will be set to the same as the maximum timestamp of the query result set.</p><p>The sliding step parameter is also optional. If the parameter is not provided, the sliding step will be set to the same as the time interval for dividing the time axis.</p><p>The relationship between the three types of parameters can be seen in the figure below. Please see the Javadoc for more details.</p><div style="text-align:center;"><img style="width:100%;max-width:800px;max-height:600px;margin-left:auto;margin-right:auto;display:block;" src="https://alioss.timecho.com/docs/img/github/99787878-47b51480-2b5b-11eb-8ed3-84088c5c30f7.png"></div><p>Note that the actual time interval of some of the last time windows may be less than the specified time interval parameter. In addition, there may be cases where the number of data rows in some time windows is 0. In these cases, the framework will also call the <code>transform</code> method for the empty windows.</p><p>The <code>SlidingSizeWindowAccessStrategy</code> is shown schematically below.<br><img style="width:100%;max-width:800px;max-height:600px;margin-left:auto;margin-right:auto;display:block;" src="https://alioss.timecho.com/docs/img/UserGuide/Process-Data/UDF-User-Defined-Function/countWindow.png"></p><p><code>SlidingSizeWindowAccessStrategy</code>: <code>SlidingSizeWindowAccessStrategy</code> has many constructors, you can pass 2 types of parameters to them:</p><ul><li>Parameter 1: Window size. This parameter specifies the number of data rows contained in a data processing window. Note that the number of data rows in some of the last time windows may be less than the specified number of data rows.</li><li>Parameter 2: Sliding step. This parameter means the number of rows between the first point of the next window and the first point of the current window. (This parameter is not required to be greater than or equal to the window size, but must be a positive number)</li></ul><p>The sliding step parameter is optional. If the parameter is not provided, the sliding step will be set to the same as the window size.</p><p>The <code>SessionTimeWindowAccessStrategy</code> is shown schematically below. <strong>Time intervals less than or equal to the given minimum time interval <code>sessionGap</code> are assigned in one group</strong><br><img style="width:100%;max-width:800px;max-height:600px;margin-left:auto;margin-right:auto;display:block;" src="https://alioss.timecho.com/docs/img/UserGuide/Process-Data/UDF-User-Defined-Function/sessionWindow.png"></p><p><code>SessionTimeWindowAccessStrategy</code>: <code>SessionTimeWindowAccessStrategy</code> has many constructors, you can pass 2 types of parameters to them:</p><ul><li>Parameter 1: The display window on the time axis.</li><li>Parameter 2: The minimum time interval <code>sessionGap</code> of two adjacent windows.</li></ul><p>The <code>StateWindowAccessStrategy</code> is shown schematically below. **For numerical data, if the state difference is less than or equal to the given threshold <code>delta</code>, it will be assigned in one group. **<br><img style="width:100%;max-width:800px;max-height:600px;margin-left:auto;margin-right:auto;display:block;" src="https://alioss.timecho.com/docs/img/UserGuide/Process-Data/UDF-User-Defined-Function/stateWindow.png"></p><p><code>StateWindowAccessStrategy</code> has four constructors.</p><ul><li>Constructor 1: For numerical data, there are 3 parameters: the time axis can display the start and end time of the time window and the threshold <code>delta</code> for the allowable change within a single window.</li><li>Constructor 2: For text data and boolean data, there are 3 parameters: the time axis can be provided to display the start and end time of the time window. For both data types, the data within a single window is same, and there is no need to provide an allowable change threshold.</li><li>Constructor 3: For numerical data, there are 1 parameters: you can only provide the threshold delta that is allowed to change within a single window. The start time of the time axis display time window will be defined as the smallest timestamp in the entire query result set, and the time axis display time window end time will be defined as The largest timestamp in the entire query result set.</li><li>Constructor 4: For text data and boolean data, you can provide no parameter. The start and end timestamps are explained in Constructor 3.</li></ul><p>StateWindowAccessStrategy can only take one column as input for now.</p><p>Please see the Javadoc for more details.</p><h6 id="setoutputdatatype" tabindex="-1"><a class="header-anchor" href="#setoutputdatatype"><span>setOutputDataType</span></a></h6><p>Note that the type of output sequence you set here determines the type of data that the <code>PointCollector</code> can actually receive in the <code>transform</code> method. The relationship between the output data type set in <code>setOutputDataType</code> and the actual data output type that <code>PointCollector</code> can receive is as follows:</p><table><thead><tr><th style="text-align:left;">Output Data Type Set in <code>setOutputDataType</code></th><th style="text-align:left;">Data Type that <code>PointCollector</code> Can Receive</th></tr></thead><tbody><tr><td style="text-align:left;"><code>INT32</code></td><td style="text-align:left;"><code>int</code></td></tr><tr><td style="text-align:left;"><code>INT64</code></td><td style="text-align:left;"><code>long</code></td></tr><tr><td style="text-align:left;"><code>FLOAT</code></td><td style="text-align:left;"><code>float</code></td></tr><tr><td style="text-align:left;"><code>DOUBLE</code></td><td style="text-align:left;"><code>double</code></td></tr><tr><td style="text-align:left;"><code>BOOLEAN</code></td><td style="text-align:left;"><code>boolean</code></td></tr><tr><td style="text-align:left;"><code>TEXT</code></td><td style="text-align:left;"><code>java.lang.String</code> and <code>org.apache.iotdb.udf.api.type.Binary</code></td></tr></tbody></table><p>The type of output time series of a UDTF is determined at runtime, which means that a UDTF can dynamically determine the type of output time series according to the type of input time series.<br> Here is a simple example:</p><div class="language-java line-numbers-mode" data-ext="java" data-title="java"><pre class="language-java"><code><span class="token keyword">void</span> <span class="token function">beforeStart</span><span class="token punctuation">(</span><span class="token class-name">UDFParameters</span> parameters<span class="token punctuation">,</span> <span class="token class-name">UDTFConfigurations</span> configurations<span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">Exception</span> <span class="token punctuation">{</span>
<span class="token comment">// do something</span>
<span class="token comment">// ...</span>
configurations
<span class="token punctuation">.</span><span class="token function">setAccessStrategy</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">RowByRowAccessStrategy</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">setOutputDataType</span><span class="token punctuation">(</span>parameters<span class="token punctuation">.</span><span class="token function">getDataType</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h4 id="void-transform-row-row-pointcollector-collector-throws-exception" tabindex="-1"><a class="header-anchor" href="#void-transform-row-row-pointcollector-collector-throws-exception"><span>void transform(Row row, PointCollector collector) throws Exception</span></a></h4><p>You need to implement this method when you specify the strategy of UDF to read the original data as <code>RowByRowAccessStrategy</code>.</p><p>This method processes the raw data one row at a time. The raw data is input from <code>Row</code> and output by <code>PointCollector</code>. You can output any number of data points in one <code>transform</code> method call. It should be noted that the type of output data points must be the same as you set in the <code>beforeStart</code> method, and the timestamps of output data points must be strictly monotonically increasing.</p><p>The following is a complete UDF example that implements the <code>void transform(Row row, PointCollector collector) throws Exception</code> method. It is an adder that receives two columns of time series as input. When two data points in a row are not <code>null</code>, this UDF will output the algebraic sum of these two data points.</p><div class="language-java line-numbers-mode" data-ext="java" data-title="java"><pre class="language-java"><code><span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>apache<span class="token punctuation">.</span>iotdb<span class="token punctuation">.</span>udf<span class="token punctuation">.</span>api<span class="token punctuation">.</span></span><span class="token class-name">UDTF</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>apache<span class="token punctuation">.</span>iotdb<span class="token punctuation">.</span>udf<span class="token punctuation">.</span>api<span class="token punctuation">.</span>access<span class="token punctuation">.</span></span><span class="token class-name">Row</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>apache<span class="token punctuation">.</span>iotdb<span class="token punctuation">.</span>udf<span class="token punctuation">.</span>api<span class="token punctuation">.</span>collector<span class="token punctuation">.</span></span><span class="token class-name">PointCollector</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>apache<span class="token punctuation">.</span>iotdb<span class="token punctuation">.</span>udf<span class="token punctuation">.</span>api<span class="token punctuation">.</span>customizer<span class="token punctuation">.</span>config<span class="token punctuation">.</span></span><span class="token class-name">UDTFConfigurations</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>apache<span class="token punctuation">.</span>iotdb<span class="token punctuation">.</span>udf<span class="token punctuation">.</span>api<span class="token punctuation">.</span>customizer<span class="token punctuation">.</span>parameter<span class="token punctuation">.</span></span><span class="token class-name">UDFParameters</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>apache<span class="token punctuation">.</span>iotdb<span class="token punctuation">.</span>udf<span class="token punctuation">.</span>api<span class="token punctuation">.</span>customizer<span class="token punctuation">.</span>strategy<span class="token punctuation">.</span></span><span class="token class-name">RowByRowAccessStrategy</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>apache<span class="token punctuation">.</span>iotdb<span class="token punctuation">.</span>udf<span class="token punctuation">.</span>api<span class="token punctuation">.</span>type<span class="token punctuation">.</span></span><span class="token class-name">Type</span></span><span class="token punctuation">;</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">Adder</span> <span class="token keyword">implements</span> <span class="token class-name">UDTF</span> <span class="token punctuation">{</span>
<span class="token annotation punctuation">@Override</span>
<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">beforeStart</span><span class="token punctuation">(</span><span class="token class-name">UDFParameters</span> parameters<span class="token punctuation">,</span> <span class="token class-name">UDTFConfigurations</span> configurations<span class="token punctuation">)</span> <span class="token punctuation">{</span>
configurations
<span class="token punctuation">.</span><span class="token function">setOutputDataType</span><span class="token punctuation">(</span><span class="token class-name">TSDataType</span><span class="token punctuation">.</span><span class="token constant">INT64</span><span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">setAccessStrategy</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">RowByRowAccessStrategy</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token annotation punctuation">@Override</span>
<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">transform</span><span class="token punctuation">(</span><span class="token class-name">Row</span> row<span class="token punctuation">,</span> <span class="token class-name">PointCollector</span> collector<span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">Exception</span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>row<span class="token punctuation">.</span><span class="token function">isNull</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span> <span class="token operator">||</span> row<span class="token punctuation">.</span><span class="token function">isNull</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
collector<span class="token punctuation">.</span><span class="token function">putLong</span><span class="token punctuation">(</span>row<span class="token punctuation">.</span><span class="token function">getTime</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> row<span class="token punctuation">.</span><span class="token function">getLong</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span> <span class="token operator">+</span> row<span class="token punctuation">.</span><span class="token function">getLong</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h4 id="void-transform-rowwindow-rowwindow-pointcollector-collector-throws-exception" tabindex="-1"><a class="header-anchor" href="#void-transform-rowwindow-rowwindow-pointcollector-collector-throws-exception"><span>void transform(RowWindow rowWindow, PointCollector collector) throws Exception</span></a></h4><p>You need to implement this method when you specify the strategy of UDF to read the original data as <code>SlidingTimeWindowAccessStrategy</code> or <code>SlidingSizeWindowAccessStrategy</code>.</p><p>This method processes a batch of data in a fixed number of rows or a fixed time interval each time, and we call the container containing this batch of data a window. The raw data is input from <code>RowWindow</code> and output by <code>PointCollector</code>. <code>RowWindow</code> can help you access a batch of <code>Row</code>, it provides a set of interfaces for random access and iterative access to this batch of <code>Row</code>. You can output any number of data points in one <code>transform</code> method call. It should be noted that the type of output data points must be the same as you set in the <code>beforeStart</code> method, and the timestamps of output data points must be strictly monotonically increasing.</p><p>Below is a complete UDF example that implements the <code>void transform(RowWindow rowWindow, PointCollector collector) throws Exception</code> method. It is a counter that receives any number of time series as input, and its function is to count and output the number of data rows in each time window within a specified time range.</p><div class="language-java line-numbers-mode" data-ext="java" data-title="java"><pre class="language-java"><code><span class="token keyword">import</span> <span class="token import"><span class="token namespace">java<span class="token punctuation">.</span>io<span class="token punctuation">.</span></span><span class="token class-name">IOException</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>apache<span class="token punctuation">.</span>iotdb<span class="token punctuation">.</span>udf<span class="token punctuation">.</span>api<span class="token punctuation">.</span></span><span class="token class-name">UDTF</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>apache<span class="token punctuation">.</span>iotdb<span class="token punctuation">.</span>udf<span class="token punctuation">.</span>api<span class="token punctuation">.</span>access<span class="token punctuation">.</span></span><span class="token class-name">Row</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>apache<span class="token punctuation">.</span>iotdb<span class="token punctuation">.</span>udf<span class="token punctuation">.</span>api<span class="token punctuation">.</span>access<span class="token punctuation">.</span></span><span class="token class-name">RowWindow</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>apache<span class="token punctuation">.</span>iotdb<span class="token punctuation">.</span>udf<span class="token punctuation">.</span>api<span class="token punctuation">.</span>collector<span class="token punctuation">.</span></span><span class="token class-name">PointCollector</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>apache<span class="token punctuation">.</span>iotdb<span class="token punctuation">.</span>udf<span class="token punctuation">.</span>api<span class="token punctuation">.</span>customizer<span class="token punctuation">.</span>config<span class="token punctuation">.</span></span><span class="token class-name">UDTFConfigurations</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>apache<span class="token punctuation">.</span>iotdb<span class="token punctuation">.</span>udf<span class="token punctuation">.</span>api<span class="token punctuation">.</span>customizer<span class="token punctuation">.</span>parameter<span class="token punctuation">.</span></span><span class="token class-name">UDFParameters</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>apache<span class="token punctuation">.</span>iotdb<span class="token punctuation">.</span>udf<span class="token punctuation">.</span>api<span class="token punctuation">.</span>customizer<span class="token punctuation">.</span>strategy<span class="token punctuation">.</span></span><span class="token class-name">SlidingTimeWindowAccessStrategy</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>apache<span class="token punctuation">.</span>iotdb<span class="token punctuation">.</span>udf<span class="token punctuation">.</span>api<span class="token punctuation">.</span>type<span class="token punctuation">.</span></span><span class="token class-name">Type</span></span><span class="token punctuation">;</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">Counter</span> <span class="token keyword">implements</span> <span class="token class-name">UDTF</span> <span class="token punctuation">{</span>
<span class="token annotation punctuation">@Override</span>
<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">beforeStart</span><span class="token punctuation">(</span><span class="token class-name">UDFParameters</span> parameters<span class="token punctuation">,</span> <span class="token class-name">UDTFConfigurations</span> configurations<span class="token punctuation">)</span> <span class="token punctuation">{</span>
configurations
<span class="token punctuation">.</span><span class="token function">setOutputDataType</span><span class="token punctuation">(</span><span class="token class-name">TSDataType</span><span class="token punctuation">.</span><span class="token constant">INT32</span><span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">setAccessStrategy</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">SlidingTimeWindowAccessStrategy</span><span class="token punctuation">(</span>
parameters<span class="token punctuation">.</span><span class="token function">getLong</span><span class="token punctuation">(</span><span class="token string">&quot;time_interval&quot;</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
parameters<span class="token punctuation">.</span><span class="token function">getLong</span><span class="token punctuation">(</span><span class="token string">&quot;sliding_step&quot;</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
parameters<span class="token punctuation">.</span><span class="token function">getLong</span><span class="token punctuation">(</span><span class="token string">&quot;display_window_begin&quot;</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
parameters<span class="token punctuation">.</span><span class="token function">getLong</span><span class="token punctuation">(</span><span class="token string">&quot;display_window_end&quot;</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token annotation punctuation">@Override</span>
<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">transform</span><span class="token punctuation">(</span><span class="token class-name">RowWindow</span> rowWindow<span class="token punctuation">,</span> <span class="token class-name">PointCollector</span> collector<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>rowWindow<span class="token punctuation">.</span><span class="token function">windowSize</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">!=</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
collector<span class="token punctuation">.</span><span class="token function">putInt</span><span class="token punctuation">(</span>rowWindow<span class="token punctuation">.</span><span class="token function">windowStartTime</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> rowWindow<span class="token punctuation">.</span><span class="token function">windowSize</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h4 id="void-terminate-pointcollector-collector-throws-exception" tabindex="-1"><a class="header-anchor" href="#void-terminate-pointcollector-collector-throws-exception"><span>void terminate(PointCollector collector) throws Exception</span></a></h4><p>In some scenarios, a UDF needs to traverse all the original data to calculate the final output data points. The <code>terminate</code> interface provides support for those scenarios.</p><p>This method is called after all <code>transform</code> calls are executed and before the <code>beforeDestory</code> method is executed. You can implement the <code>transform</code> method to perform pure data processing (without outputting any data points), and implement the <code>terminate</code> method to output the processing results.</p><p>The processing results need to be output by the <code>PointCollector</code>. You can output any number of data points in one <code>terminate</code> method call. It should be noted that the type of output data points must be the same as you set in the <code>beforeStart</code> method, and the timestamps of output data points must be strictly monotonically increasing.</p><p>Below is a complete UDF example that implements the <code>void terminate(PointCollector collector) throws Exception</code> method. It takes one time series whose data type is <code>INT32</code> as input, and outputs the maximum value point of the series.</p><div class="language-java line-numbers-mode" data-ext="java" data-title="java"><pre class="language-java"><code><span class="token keyword">import</span> <span class="token import"><span class="token namespace">java<span class="token punctuation">.</span>io<span class="token punctuation">.</span></span><span class="token class-name">IOException</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>apache<span class="token punctuation">.</span>iotdb<span class="token punctuation">.</span>udf<span class="token punctuation">.</span>api<span class="token punctuation">.</span></span><span class="token class-name">UDTF</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>apache<span class="token punctuation">.</span>iotdb<span class="token punctuation">.</span>udf<span class="token punctuation">.</span>api<span class="token punctuation">.</span>access<span class="token punctuation">.</span></span><span class="token class-name">Row</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>apache<span class="token punctuation">.</span>iotdb<span class="token punctuation">.</span>udf<span class="token punctuation">.</span>api<span class="token punctuation">.</span>collector<span class="token punctuation">.</span></span><span class="token class-name">PointCollector</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>apache<span class="token punctuation">.</span>iotdb<span class="token punctuation">.</span>udf<span class="token punctuation">.</span>api<span class="token punctuation">.</span>customizer<span class="token punctuation">.</span>config<span class="token punctuation">.</span></span><span class="token class-name">UDTFConfigurations</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>apache<span class="token punctuation">.</span>iotdb<span class="token punctuation">.</span>udf<span class="token punctuation">.</span>api<span class="token punctuation">.</span>customizer<span class="token punctuation">.</span>parameter<span class="token punctuation">.</span></span><span class="token class-name">UDFParameters</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>apache<span class="token punctuation">.</span>iotdb<span class="token punctuation">.</span>udf<span class="token punctuation">.</span>api<span class="token punctuation">.</span>customizer<span class="token punctuation">.</span>strategy<span class="token punctuation">.</span></span><span class="token class-name">RowByRowAccessStrategy</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>apache<span class="token punctuation">.</span>iotdb<span class="token punctuation">.</span>udf<span class="token punctuation">.</span>api<span class="token punctuation">.</span>type<span class="token punctuation">.</span></span><span class="token class-name">Type</span></span><span class="token punctuation">;</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">Max</span> <span class="token keyword">implements</span> <span class="token class-name">UDTF</span> <span class="token punctuation">{</span>
<span class="token keyword">private</span> <span class="token class-name">Long</span> time<span class="token punctuation">;</span>
<span class="token keyword">private</span> <span class="token keyword">int</span> value<span class="token punctuation">;</span>
<span class="token annotation punctuation">@Override</span>
<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">beforeStart</span><span class="token punctuation">(</span><span class="token class-name">UDFParameters</span> parameters<span class="token punctuation">,</span> <span class="token class-name">UDTFConfigurations</span> configurations<span class="token punctuation">)</span> <span class="token punctuation">{</span>
configurations
<span class="token punctuation">.</span><span class="token function">setOutputDataType</span><span class="token punctuation">(</span><span class="token class-name">TSDataType</span><span class="token punctuation">.</span><span class="token constant">INT32</span><span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">setAccessStrategy</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">RowByRowAccessStrategy</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token annotation punctuation">@Override</span>
<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">transform</span><span class="token punctuation">(</span><span class="token class-name">Row</span> row<span class="token punctuation">,</span> <span class="token class-name">PointCollector</span> collector<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>row<span class="token punctuation">.</span><span class="token function">isNull</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">int</span> candidateValue <span class="token operator">=</span> row<span class="token punctuation">.</span><span class="token function">getInt</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>time <span class="token operator">==</span> <span class="token keyword">null</span> <span class="token operator">||</span> value <span class="token operator">&lt;</span> candidateValue<span class="token punctuation">)</span> <span class="token punctuation">{</span>
time <span class="token operator">=</span> row<span class="token punctuation">.</span><span class="token function">getTime</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
value <span class="token operator">=</span> candidateValue<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token annotation punctuation">@Override</span>
<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">terminate</span><span class="token punctuation">(</span><span class="token class-name">PointCollector</span> collector<span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">IOException</span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>time <span class="token operator">!=</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
collector<span class="token punctuation">.</span><span class="token function">putInt</span><span class="token punctuation">(</span>time<span class="token punctuation">,</span> value<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h4 id="void-beforedestroy" tabindex="-1"><a class="header-anchor" href="#void-beforedestroy"><span>void beforeDestroy()</span></a></h4><p>The method for terminating a UDF.</p><p>This method is called by the framework. For a UDF instance, <code>beforeDestroy</code> will be called after the last record is processed. In the entire life cycle of the instance, <code>beforeDestroy</code> will only be called once.</p><h3 id="udaf-user-defined-aggregation-function" tabindex="-1"><a class="header-anchor" href="#udaf-user-defined-aggregation-function"><span>UDAF (User Defined Aggregation Function)</span></a></h3><p>A complete definition of UDAF involves two classes, <code>State</code> and <code>UDAF</code>.</p><h4 id="state-class" tabindex="-1"><a class="header-anchor" href="#state-class"><span>State Class</span></a></h4><p>To write your own <code>State</code>, you need to implement the <code>org.apache.iotdb.udf.api.State</code> interface.</p><p>The following table shows all the interfaces available for user implementation.</p><table><thead><tr><th>Interface Definition</th><th>Description</th><th>Required to Implement</th></tr></thead><tbody><tr><td><code>void reset()</code></td><td>To reset the <code>State</code> object to its initial state, you need to fill in the initial values of the fields in the <code>State</code> class within this method as if you were writing a constructor.</td><td>Required</td></tr><tr><td><code>byte[] serialize()</code></td><td>Serializes <code>State</code> to binary data. This method is used for IoTDB internal <code>State</code> passing. Note that the order of serialization must be consistent with the following deserialization methods.</td><td>Required</td></tr><tr><td><code>void deserialize(byte[] bytes)</code></td><td>Deserializes binary data to <code>State</code>. This method is used for IoTDB internal <code>State</code> passing. Note that the order of deserialization must be consistent with the serialization method above.</td><td>Required</td></tr></tbody></table><p>The following section describes the usage of each interface in detail.</p><h5 id="void-reset" tabindex="-1"><a class="header-anchor" href="#void-reset"><span>void reset()</span></a></h5><p>This method resets the <code>State</code> to its initial state, you need to fill in the initial values of the fields in the <code>State</code> object in this method. For optimization reasons, IoTDB reuses <code>State</code> as much as possible internally, rather than creating a new <code>State</code> for each group, which would introduce unnecessary overhead. When <code>State</code> has finished updating the data in a group, this method is called to reset to the initial state as a way to process the next group.</p><p>In the case of <code>State</code> for averaging (aka <code>avg</code>), for example, you would need the sum of the data, <code>sum</code>, and the number of entries in the data, <code>count</code>, and initialize both to 0 in the <code>reset()</code> method.</p><div class="language-java line-numbers-mode" data-ext="java" data-title="java"><pre class="language-java"><code><span class="token keyword">class</span> <span class="token class-name">AvgState</span> <span class="token keyword">implements</span> <span class="token class-name">State</span> <span class="token punctuation">{</span>
<span class="token keyword">double</span> sum<span class="token punctuation">;</span>
<span class="token keyword">long</span> count<span class="token punctuation">;</span>
<span class="token annotation punctuation">@Override</span>
<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">reset</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
sum <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>
count <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">// other methods</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h5 id="byte-serialize-void-deserialize-byte-bytes" tabindex="-1"><a class="header-anchor" href="#byte-serialize-void-deserialize-byte-bytes"><span>byte[] serialize()/void deserialize(byte[] bytes)</span></a></h5><p>These methods serialize the <code>State</code> into binary data, and deserialize the <code>State</code> from the binary data. IoTDB, as a distributed database, involves passing data among different nodes, so you need to write these two methods to enable the passing of the State among different nodes. Note that the order of serialization and deserialization must be the consistent.</p><p>In the case of <code>State</code> for averaging (aka <code>avg</code>), for example, you can convert the content of State to <code>byte[]</code> array and read out the content of State from <code>byte[]</code> array in any way you want, the following shows the code for serialization/deserialization using <code>ByteBuffer</code> introduced by Java8:</p><div class="language-java line-numbers-mode" data-ext="java" data-title="java"><pre class="language-java"><code><span class="token annotation punctuation">@Override</span>
<span class="token keyword">public</span> <span class="token keyword">byte</span><span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token function">serialize</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token class-name">ByteBuffer</span> buffer <span class="token operator">=</span> <span class="token class-name">ByteBuffer</span><span class="token punctuation">.</span><span class="token function">allocate</span><span class="token punctuation">(</span><span class="token class-name">Double</span><span class="token punctuation">.</span><span class="token constant">BYTES</span> <span class="token operator">+</span> <span class="token class-name">Long</span><span class="token punctuation">.</span><span class="token constant">BYTES</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
buffer<span class="token punctuation">.</span><span class="token function">putDouble</span><span class="token punctuation">(</span>sum<span class="token punctuation">)</span><span class="token punctuation">;</span>
buffer<span class="token punctuation">.</span><span class="token function">putLong</span><span class="token punctuation">(</span>count<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> buffer<span class="token punctuation">.</span><span class="token function">array</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token annotation punctuation">@Override</span>
<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">deserialize</span><span class="token punctuation">(</span><span class="token keyword">byte</span><span class="token punctuation">[</span><span class="token punctuation">]</span> bytes<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token class-name">ByteBuffer</span> buffer <span class="token operator">=</span> <span class="token class-name">ByteBuffer</span><span class="token punctuation">.</span><span class="token function">wrap</span><span class="token punctuation">(</span>bytes<span class="token punctuation">)</span><span class="token punctuation">;</span>
sum <span class="token operator">=</span> buffer<span class="token punctuation">.</span><span class="token function">getDouble</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
count <span class="token operator">=</span> buffer<span class="token punctuation">.</span><span class="token function">getLong</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h4 id="udaf-classes" tabindex="-1"><a class="header-anchor" href="#udaf-classes"><span>UDAF Classes</span></a></h4><p>To write a UDAF, you need to implement the <code>org.apache.iotdb.udf.api.UDAF</code> interface.</p><p>The following table shows all the interfaces available for user implementation.</p><table><thead><tr><th>Interface definition</th><th>Description</th><th>Required to Implement</th></tr></thead><tbody><tr><td><code>void validate(UDFParameterValidator validator) throws Exception</code></td><td>This method is mainly used to validate <code>UDFParameters</code> and it is executed before <code>beforeStart(UDFParameters, UDTFConfigurations)</code> is called.</td><td>Optional</td></tr><tr><td><code>void beforeStart(UDFParameters parameters, UDAFConfigurations configurations) throws Exception</code></td><td>Initialization method that invokes user-defined initialization behavior before UDAF processes the input data. Unlike UDTF, configuration is of type <code>UDAFConfiguration</code>.</td><td>Required</td></tr><tr><td><code>State createState()</code></td><td>To create a <code>State</code> object, usually just call the default constructor and modify the default initial value as needed.</td><td>Required</td></tr><tr><td><code>void addInput(State state, Column[] columns, BitMap bitMap)</code></td><td>Update <code>State</code> object according to the incoming data <code>Column[]</code> in batch, note that <code>column[0]</code> always represents the time column. In addition, <code>BitMap</code> represents the data that has been filtered out before, you need to manually determine whether the corresponding data has been filtered out when writing this method.</td><td>Required</td></tr><tr><td><code>void combineState(State state, State rhs)</code></td><td>Merge <code>rhs</code> state into <code>state</code> state. In a distributed scenario, the same set of data may be distributed on different nodes, IoTDB generates a <code>State</code> object for the partial data on each node, and then calls this method to merge it into the complete <code>State</code>.</td><td>Required</td></tr><tr><td><code>void outputFinal(State state, ResultValue resultValue)</code></td><td>Computes the final aggregated result based on the data in <code>State</code>. Note that according to the semantics of the aggregation, only one value can be output per group.</td><td>Required</td></tr><tr><td><code>void beforeDestroy() </code></td><td>This method is called by the framework after the last input data is processed, and will only be called once in the life cycle of each UDF instance.</td><td>Optional</td></tr></tbody></table><p>In the life cycle of a UDAF instance, the calling sequence of each method is as follows:</p><ol><li><code>State createState()</code></li><li><code>void validate(UDFParameterValidator validator) throws Exception</code></li><li><code>void beforeStart(UDFParameters parameters, UDAFConfigurations configurations) throws Exception</code></li><li><code>void addInput(State state, Column[] columns, BitMap bitMap)</code></li><li><code>void combineState(State state, State rhs)</code></li><li><code>void outputFinal(State state, ResultValue resultValue)</code></li><li><code>void beforeDestroy()</code></li></ol><p>Similar to UDTF, every time the framework executes a UDAF query, a new UDF instance will be constructed. When the query ends, the corresponding instance will be destroyed. Therefore, the internal data of the instances in different UDAF queries (even in the same SQL statement) are isolated. You can maintain some state data in the UDAF without considering the influence of concurrency and other factors.</p><p>The usage of each interface will be described in detail below.</p><h5 id="void-validate-udfparametervalidator-validator-throws-exception-1" tabindex="-1"><a class="header-anchor" href="#void-validate-udfparametervalidator-validator-throws-exception-1"><span>void validate(UDFParameterValidator validator) throws Exception</span></a></h5><p>Same as UDTF, the <code>validate</code> method is used to validate the parameters entered by the user.</p><p>In this method, you can limit the number and types of input time series, check the attributes of user input, or perform any custom verification.</p><h5 id="void-beforestart-udfparameters-parameters-udafconfigurations-configurations-throws-exception" tabindex="-1"><a class="header-anchor" href="#void-beforestart-udfparameters-parameters-udafconfigurations-configurations-throws-exception"><span>void beforeStart(UDFParameters parameters, UDAFConfigurations configurations) throws Exception</span></a></h5><p>The <code>beforeStart</code> method does the same thing as the UDAF:</p><ol><li>Use UDFParameters to get the time series paths and parse key-value pair attributes entered by the user.</li><li>Set the strategy to access the raw data and set the output data type in UDAFConfigurations.</li><li>Create resources, such as establishing external connections, opening files, etc.</li></ol><p>The role of the <code>UDFParameters</code> type can be seen above.</p><h6 id="udafconfigurations" tabindex="-1"><a class="header-anchor" href="#udafconfigurations"><span>UDAFConfigurations</span></a></h6><p>The difference from UDTF is that UDAF uses <code>UDAFConfigurations</code> as the type of <code>configuration</code> object.</p><p>Currently, this class only supports setting the type of output data.</p><div class="language-java line-numbers-mode" data-ext="java" data-title="java"><pre class="language-java"><code><span class="token keyword">void</span> <span class="token function">beforeStart</span><span class="token punctuation">(</span><span class="token class-name">UDFParameters</span> parameters<span class="token punctuation">,</span> <span class="token class-name">UDAFConfigurations</span> configurations<span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">Exception</span> <span class="token punctuation">{</span>
<span class="token comment">// parameters</span>
<span class="token comment">// ...</span>
<span class="token comment">// configurations</span>
configurations
<span class="token punctuation">.</span><span class="token function">setOutputDataType</span><span class="token punctuation">(</span><span class="token class-name">Type</span><span class="token punctuation">.</span><span class="token constant">INT32</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>The relationship between the output type set in <code>setOutputDataType</code> and the type of data output that <code>ResultValue</code> can actually receive is as follows:</p><table><thead><tr><th>The output type set in <code>setOutputDataType</code></th><th>The output type that <code>ResultValue</code> can actually receive</th></tr></thead><tbody><tr><td><code>INT32</code></td><td><code>int</code></td></tr><tr><td><code>INT64</code></td><td><code>long</code></td></tr><tr><td><code>FLOAT</code></td><td><code>float</code></td></tr><tr><td><code>DOUBLE</code></td><td><code>double</code></td></tr><tr><td><code>BOOLEAN</code></td><td><code>boolean</code></td></tr><tr><td><code>TEXT</code></td><td><code>org.apache.iotdb.udf.api.type.Binary</code></td></tr></tbody></table><p>The output type of the UDAF is determined at runtime. You can dynamically determine the output sequence type based on the input type.</p><p>Here is a simple example:</p><div class="language-java line-numbers-mode" data-ext="java" data-title="java"><pre class="language-java"><code><span class="token keyword">void</span> <span class="token function">beforeStart</span><span class="token punctuation">(</span><span class="token class-name">UDFParameters</span> parameters<span class="token punctuation">,</span> <span class="token class-name">UDAFConfigurations</span> configurations<span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">Exception</span> <span class="token punctuation">{</span>
<span class="token comment">// do something</span>
<span class="token comment">// ...</span>
configurations
<span class="token punctuation">.</span><span class="token function">setOutputDataType</span><span class="token punctuation">(</span>parameters<span class="token punctuation">.</span><span class="token function">getDataType</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h5 id="state-createstate" tabindex="-1"><a class="header-anchor" href="#state-createstate"><span>State createState()</span></a></h5><p>This method creates and initializes a <code>State</code> object for UDAF. Due to the limitations of the Java language, you can only call the default constructor for the <code>State</code> class. The default constructor assigns a default initial value to all the fields in the class, and if that initial value does not meet your requirements, you need to initialize them manually within this method.</p><p>The following is an example that includes manual initialization. Suppose you want to implement an aggregate function that multiply all numbers in the group, then your initial <code>State</code> value should be set to 1, but the default constructor initializes it to 0, so you need to initialize <code>State</code> manually after calling the default constructor:</p><div class="language-java line-numbers-mode" data-ext="java" data-title="java"><pre class="language-java"><code><span class="token keyword">public</span> <span class="token class-name">State</span> <span class="token function">createState</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token class-name">MultiplyState</span> state <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">MultiplyState</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
state<span class="token punctuation">.</span>result <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> state<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h5 id="void-addinput-state-state-column-columns-bitmap-bitmap" tabindex="-1"><a class="header-anchor" href="#void-addinput-state-state-column-columns-bitmap-bitmap"><span>void addInput(State state, Column[] columns, BitMap bitMap)</span></a></h5><p>This method updates the <code>State</code> object with the raw input data. For performance reasons, also to align with the IoTDB vectorized query engine, the raw input data is no longer a data point, but an array of columns <code>Column[]</code>. Note that the first column (i.e. <code>column[0]</code>) is always the time column, so you can also do different operations in UDAF depending on the time.</p><p>Since the input parameter is not of a single data point type, but of multiple columns, you need to manually filter some of the data in the columns, which is why the third parameter, <code>BitMap</code>, exists. It identifies which of these columns have been filtered out, so you don&#39;t have to think about the filtered data in any case.</p><p>Here&#39;s an example of <code>addInput()</code> that counts the number of items (aka count). It shows how you can use <code>BitMap</code> to ignore data that has been filtered out. Note that due to the limitations of the Java language, you need to do the explicit cast the <code>State</code> object from type defined in the interface to a custom <code>State</code> type at the beginning of the method, otherwise you won&#39;t be able to use the <code>State</code> object.</p><div class="language-java line-numbers-mode" data-ext="java" data-title="java"><pre class="language-java"><code><span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">addInput</span><span class="token punctuation">(</span><span class="token class-name">State</span> state<span class="token punctuation">,</span> <span class="token class-name">Column</span><span class="token punctuation">[</span><span class="token punctuation">]</span> column<span class="token punctuation">,</span> <span class="token class-name">BitMap</span> bitMap<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token class-name">CountState</span> countState <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token class-name">CountState</span><span class="token punctuation">)</span> state<span class="token punctuation">;</span>
<span class="token keyword">int</span> count <span class="token operator">=</span> column<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">.</span><span class="token function">getPositionCount</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">int</span> i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator">&lt;</span> count<span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>bitMap <span class="token operator">!=</span> <span class="token keyword">null</span> <span class="token operator">&amp;&amp;</span> <span class="token operator">!</span>bitMap<span class="token punctuation">.</span><span class="token function">isMarked</span><span class="token punctuation">(</span>i<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">continue</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>column<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">.</span><span class="token function">isNull</span><span class="token punctuation">(</span>i<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
countState<span class="token punctuation">.</span>count<span class="token operator">++</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h5 id="void-combinestate-state-state-state-rhs" tabindex="-1"><a class="header-anchor" href="#void-combinestate-state-state-state-rhs"><span>void combineState(State state, State rhs)</span></a></h5><p>This method combines two <code>State</code>s, or more precisely, updates the first <code>State</code> object with the second <code>State</code> object. IoTDB is a distributed database, and the data of the same group may be distributed on different nodes. For performance reasons, IoTDB will first aggregate some of the data on each node into <code>State</code>, and then merge the <code>State</code>s on different nodes that belong to the same group, which is what <code>combineState</code> does.</p><p>Here&#39;s an example of <code>combineState()</code> for averaging (aka avg). Similar to <code>addInput</code>, you need to do an explicit type conversion for the two <code>State</code>s at the beginning. Also note that you are updating the value of the first <code>State</code> with the contents of the second <code>State</code>.</p><div class="language-java line-numbers-mode" data-ext="java" data-title="java"><pre class="language-java"><code><span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">combineState</span><span class="token punctuation">(</span><span class="token class-name">State</span> state<span class="token punctuation">,</span> <span class="token class-name">State</span> rhs<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token class-name">AvgState</span> avgState <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token class-name">AvgState</span><span class="token punctuation">)</span> state<span class="token punctuation">;</span>
<span class="token class-name">AvgState</span> avgRhs <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token class-name">AvgState</span><span class="token punctuation">)</span> rhs<span class="token punctuation">;</span>
avgState<span class="token punctuation">.</span>count <span class="token operator">+=</span> avgRhs<span class="token punctuation">.</span>count<span class="token punctuation">;</span>
avgState<span class="token punctuation">.</span>sum <span class="token operator">+=</span> avgRhs<span class="token punctuation">.</span>sum<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h5 id="void-outputfinal-state-state-resultvalue-resultvalue" tabindex="-1"><a class="header-anchor" href="#void-outputfinal-state-state-resultvalue-resultvalue"><span>void outputFinal(State state, ResultValue resultValue)</span></a></h5><p>This method works by calculating the final result from <code>State</code>. You need to access the various fields in <code>State</code>, derive the final result, and set the final result into the <code>ResultValue</code> object.IoTDB internally calls this method once at the end for each group. Note that according to the semantics of aggregation, the final result can only be one value.</p><p>Here is another <code>outputFinal</code> example for averaging (aka avg). In addition to the forced type conversion at the beginning, you will also see a specific use of the <code>ResultValue</code> object, where the final result is set by <code>setXXX</code> (where <code>XXX</code> is the type name).</p><div class="language-java line-numbers-mode" data-ext="java" data-title="java"><pre class="language-java"><code><span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">outputFinal</span><span class="token punctuation">(</span><span class="token class-name">State</span> state<span class="token punctuation">,</span> <span class="token class-name">ResultValue</span> resultValue<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token class-name">AvgState</span> avgState <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token class-name">AvgState</span><span class="token punctuation">)</span> state<span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>avgState<span class="token punctuation">.</span>count <span class="token operator">!=</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
resultValue<span class="token punctuation">.</span><span class="token function">setDouble</span><span class="token punctuation">(</span>avgState<span class="token punctuation">.</span>sum <span class="token operator">/</span> avgState<span class="token punctuation">.</span>count<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
resultValue<span class="token punctuation">.</span><span class="token function">setNull</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h5 id="void-beforedestroy-1" tabindex="-1"><a class="header-anchor" href="#void-beforedestroy-1"><span>void beforeDestroy()</span></a></h5><p>The method for terminating a UDF.</p><p>This method is called by the framework. For a UDF instance, <code>beforeDestroy</code> will be called after the last record is processed. In the entire life cycle of the instance, <code>beforeDestroy</code> will only be called once.</p><h3 id="maven-project-example" tabindex="-1"><a class="header-anchor" href="#maven-project-example"><span>Maven Project Example</span></a></h3><p>If you use Maven, you can build your own UDF project referring to our <strong>udf-example</strong> module. You can find the project <a href="https://github.com/apache/iotdb/tree/master/example/udf" target="_blank" rel="noopener noreferrer">here<span><svg class="external-link-icon" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg><span class="external-link-icon-sr-only">open in new window</span></span></a>.</p><h3 id="udf-registration" tabindex="-1"><a class="header-anchor" href="#udf-registration"><span>UDF Registration</span></a></h3><p>The process of registering a UDF in IoTDB is as follows:</p><ol><li>Implement a complete UDF class, assuming the full class name of this class is <code>org.apache.iotdb.udf.ExampleUDTF</code>.</li><li>Package your project into a JAR. If you use Maven to manage your project, you can refer to the Maven project example above.</li><li>Make preparations for registration according to the registration mode. For details, see the following example.</li><li>You can use following SQL to register UDF.</li></ol><div class="language-sql line-numbers-mode" data-ext="sql" data-title="sql"><pre class="language-sql"><code><span class="token keyword">CREATE</span> <span class="token keyword">FUNCTION</span> <span class="token operator">&lt;</span>UDF<span class="token operator">-</span>NAME<span class="token operator">&gt;</span> <span class="token keyword">AS</span> <span class="token operator">&lt;</span>UDF<span class="token operator">-</span>CLASS<span class="token operator">-</span><span class="token keyword">FULL</span><span class="token operator">-</span>PATHNAME<span class="token operator">&gt;</span> <span class="token punctuation">(</span><span class="token keyword">USING</span> URI URI<span class="token operator">-</span>STRING<span class="token punctuation">)</span>?
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div></div></div><h4 id="example-register-udf-named-example-you-can-choose-either-of-the-following-two-registration-methods" tabindex="-1"><a class="header-anchor" href="#example-register-udf-named-example-you-can-choose-either-of-the-following-two-registration-methods"><span>Example: register UDF named <code>example</code>, you can choose either of the following two registration methods</span></a></h4><h5 id="no-uri" tabindex="-1"><a class="header-anchor" href="#no-uri"><span>No URI</span></a></h5><p>Prepare:<br> When use this method to register,you should put JAR to directory <code>iotdb-server-1.0.0-all-bin/ext/udf</code>(directory can config).<br><strong>Note,you should put JAR to this directory of all DataNodes if using Cluster</strong></p><p>SQL:</p><div class="language-sql line-numbers-mode" data-ext="sql" data-title="sql"><pre class="language-sql"><code><span class="token keyword">CREATE</span> <span class="token keyword">FUNCTION</span> example <span class="token keyword">AS</span> <span class="token string">&#39;org.apache.iotdb.udf.UDTFExample&#39;</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div></div></div><h5 id="using-uri" tabindex="-1"><a class="header-anchor" href="#using-uri"><span>Using URI</span></a></h5><p>Prepare:<br> When use this method to register,you need to upload the JAR to URI server and ensure the IoTDB instance executing this registration statement has access to the URI server.<br><strong>Note,you needn&#39;t place JAR manually,IoTDB will download the JAR and sync it.</strong></p><p>SQL:</p><div class="language-sql line-numbers-mode" data-ext="sql" data-title="sql"><pre class="language-sql"><code><span class="token keyword">CREATE</span> <span class="token keyword">FUNCTION</span> example <span class="token keyword">AS</span> <span class="token string">&#39;org.apache.iotdb.udf.UDTFExample&#39;</span> <span class="token keyword">USING</span> URI <span class="token string">&#39;http://jar/example.jar&#39;</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div></div></div><h4 id="note" tabindex="-1"><a class="header-anchor" href="#note"><span>Note</span></a></h4><p>Since UDF instances are dynamically loaded through reflection technology, you do not need to restart the server during the UDF registration process.</p><p>UDF function names are not case-sensitive.</p><p>Please ensure that the function name given to the UDF is different from all built-in function names. A UDF with the same name as a built-in function cannot be registered.</p><p>We recommend that you do not use classes that have the same class name but different function logic in different JAR packages. For example, in <code>UDF(UDAF/UDTF): udf1, udf2</code>, the JAR package of udf1 is <code>udf1.jar</code> and the JAR package of udf2 is <code>udf2.jar</code>. Assume that both JAR packages contain the <code>org.apache.iotdb.udf.ExampleUDTF</code> class. If you use two UDFs in the same SQL statement at the same time, the system will randomly load either of them and may cause inconsistency in UDF execution behavior.</p><h3 id="udf-deregistration" tabindex="-1"><a class="header-anchor" href="#udf-deregistration"><span>UDF Deregistration</span></a></h3><p>The following shows the SQL syntax of how to deregister a UDF.</p><div class="language-sql line-numbers-mode" data-ext="sql" data-title="sql"><pre class="language-sql"><code><span class="token keyword">DROP</span> <span class="token keyword">FUNCTION</span> <span class="token operator">&lt;</span>UDF<span class="token operator">-</span>NAME<span class="token operator">&gt;</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div></div></div><p>Here is an example:</p><div class="language-sql line-numbers-mode" data-ext="sql" data-title="sql"><pre class="language-sql"><code><span class="token keyword">DROP</span> <span class="token keyword">FUNCTION</span> example
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div></div></div><h3 id="udf-queries" tabindex="-1"><a class="header-anchor" href="#udf-queries"><span>UDF Queries</span></a></h3><p>The usage of UDF is similar to that of built-in aggregation functions.</p><h4 id="basic-sql-syntax-support" tabindex="-1"><a class="header-anchor" href="#basic-sql-syntax-support"><span>Basic SQL syntax support</span></a></h4><ul><li>Support <code>SLIMIT</code> / <code>SOFFSET</code></li><li>Support <code>LIMIT</code> / <code>OFFSET</code></li><li>Support queries with time filters</li><li>Support queries with value filters</li></ul><h4 id="queries-with-in-select-clauses" tabindex="-1"><a class="header-anchor" href="#queries-with-in-select-clauses"><span>Queries with * in SELECT Clauses</span></a></h4><p>Assume that there are 2 time series (<code>root.sg.d1.s1</code> and <code>root.sg.d1.s2</code>) in the system.</p><ul><li><strong><code>SELECT example(*) from root.sg.d1</code></strong></li></ul><p>Then the result set will include the results of <code>example (root.sg.d1.s1)</code> and <code>example (root.sg.d1.s2)</code>.</p><ul><li><strong><code>SELECT example(s1, *) from root.sg.d1</code></strong></li></ul><p>Then the result set will include the results of <code>example(root.sg.d1.s1, root.sg.d1.s1)</code> and <code>example(root.sg.d1.s1, root.sg.d1.s2)</code>.</p><ul><li><strong><code>SELECT example(*, *) from root.sg.d1</code></strong></li></ul><p>Then the result set will include the results of <code>example(root.sg.d1.s1, root.sg.d1.s1)</code>, <code>example(root.sg.d1.s2, root.sg.d1.s1)</code>, <code>example(root.sg.d1.s1, root.sg.d1.s2)</code> and <code>example(root.sg.d1.s2, root.sg.d1.s2)</code>.</p><h4 id="queries-with-key-value-attributes-in-udf-parameters" tabindex="-1"><a class="header-anchor" href="#queries-with-key-value-attributes-in-udf-parameters"><span>Queries with Key-value Attributes in UDF Parameters</span></a></h4><p>You can pass any number of key-value pair parameters to the UDF when constructing a UDF query. The key and value in the key-value pair need to be enclosed in single or double quotes. Note that key-value pair parameters can only be passed in after all time series have been passed in. Here is a set of examples:</p><div class="language-sql line-numbers-mode" data-ext="sql" data-title="sql"><pre class="language-sql"><code><span class="token keyword">SELECT</span> example<span class="token punctuation">(</span>s1<span class="token punctuation">,</span> <span class="token string">&#39;key1&#39;</span><span class="token operator">=</span><span class="token string">&#39;value1&#39;</span><span class="token punctuation">,</span> <span class="token string">&#39;key2&#39;</span><span class="token operator">=</span><span class="token string">&#39;value2&#39;</span><span class="token punctuation">)</span><span class="token punctuation">,</span> example<span class="token punctuation">(</span><span class="token operator">*</span><span class="token punctuation">,</span> <span class="token string">&#39;key3&#39;</span><span class="token operator">=</span><span class="token string">&#39;value3&#39;</span><span class="token punctuation">)</span> <span class="token keyword">FROM</span> root<span class="token punctuation">.</span>sg<span class="token punctuation">.</span>d1<span class="token punctuation">;</span>
<span class="token keyword">SELECT</span> example<span class="token punctuation">(</span>s1<span class="token punctuation">,</span> s2<span class="token punctuation">,</span> <span class="token string">&#39;key1&#39;</span><span class="token operator">=</span><span class="token string">&#39;value1&#39;</span><span class="token punctuation">,</span> <span class="token string">&#39;key2&#39;</span><span class="token operator">=</span><span class="token string">&#39;value2&#39;</span><span class="token punctuation">)</span> <span class="token keyword">FROM</span> root<span class="token punctuation">.</span>sg<span class="token punctuation">.</span>d1<span class="token punctuation">;</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div></div></div><h4 id="nested-queries" tabindex="-1"><a class="header-anchor" href="#nested-queries"><span>Nested Queries</span></a></h4><div class="language-sql line-numbers-mode" data-ext="sql" data-title="sql"><pre class="language-sql"><code><span class="token keyword">SELECT</span> s1<span class="token punctuation">,</span> s2<span class="token punctuation">,</span> example<span class="token punctuation">(</span>s1<span class="token punctuation">,</span> s2<span class="token punctuation">)</span> <span class="token keyword">FROM</span> root<span class="token punctuation">.</span>sg<span class="token punctuation">.</span>d1<span class="token punctuation">;</span>
<span class="token keyword">SELECT</span> <span class="token operator">*</span><span class="token punctuation">,</span> example<span class="token punctuation">(</span><span class="token operator">*</span><span class="token punctuation">)</span> <span class="token keyword">FROM</span> root<span class="token punctuation">.</span>sg<span class="token punctuation">.</span>d1 <span class="token keyword">DISABLE</span> ALIGN<span class="token punctuation">;</span>
<span class="token keyword">SELECT</span> s1 <span class="token operator">*</span> example<span class="token punctuation">(</span><span class="token operator">*</span> <span class="token operator">/</span> s1 <span class="token operator">+</span> s2<span class="token punctuation">)</span> <span class="token keyword">FROM</span> root<span class="token punctuation">.</span>sg<span class="token punctuation">.</span>d1<span class="token punctuation">;</span>
<span class="token keyword">SELECT</span> s1<span class="token punctuation">,</span> s2<span class="token punctuation">,</span> s1 <span class="token operator">+</span> example<span class="token punctuation">(</span>s1<span class="token punctuation">,</span> s2<span class="token punctuation">)</span><span class="token punctuation">,</span> s1 <span class="token operator">-</span> example<span class="token punctuation">(</span>s1 <span class="token operator">+</span> example<span class="token punctuation">(</span>s1<span class="token punctuation">,</span> s2<span class="token punctuation">)</span> <span class="token operator">/</span> s2<span class="token punctuation">)</span> <span class="token keyword">FROM</span> root<span class="token punctuation">.</span>sg<span class="token punctuation">.</span>d1<span class="token punctuation">;</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="show-all-registered-udfs" tabindex="-1"><a class="header-anchor" href="#show-all-registered-udfs"><span>Show All Registered UDFs</span></a></h3><div class="language-sql line-numbers-mode" data-ext="sql" data-title="sql"><pre class="language-sql"><code><span class="token keyword">SHOW</span> FUNCTIONS
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div></div></div><h3 id="user-permission-management" tabindex="-1"><a class="header-anchor" href="#user-permission-management"><span>User Permission Management</span></a></h3><p>There are 1 types of user permissions related to UDF: <code>USE_UDF</code></p><ul><li>Only users with this permission are allowed to register UDFs</li><li>Only users with this permission are allowed to deregister UDFs</li><li>Only users with this permission are allowed to use UDFs for queries</li></ul><p>For more user permissions related content, please refer to <a class="route-link" href="/UserGuide/latest/User-Manual/Authority-Management.html">Account Management Statements</a>.</p><h3 id="configurable-properties" tabindex="-1"><a class="header-anchor" href="#configurable-properties"><span>Configurable Properties</span></a></h3><p>You can use <code>udf_lib_dir</code> to config udf lib directory.<br> When querying by a UDF, IoTDB may prompt that there is insufficient memory. You can resolve the issue by configuring <code>udf_initial_byte_array_length_for_memory_control</code>, <code>udf_memory_budget_in_mb</code> and <code>udf_reader_transformer_collector_memory_proportion</code> in <code>iotdb-datanode.properties</code> and restarting the server.</p><h3 id="contribute-udf" tabindex="-1"><a class="header-anchor" href="#contribute-udf"><span>Contribute UDF</span></a></h3><p>This part mainly introduces how external users can contribute their own UDFs to the IoTDB community.</p><h4 id="prerequisites" tabindex="-1"><a class="header-anchor" href="#prerequisites"><span>Prerequisites</span></a></h4><ol><li><p>UDFs must be universal.</p><p>The &quot;universal&quot; mentioned here refers to: UDFs can be widely used in some scenarios. In other words, the UDF function must have reuse value and may be directly used by other users in the community.</p><p>If you are not sure whether the UDF you want to contribute is universal, you can send an email to <code>dev@iotdb.apache.org</code> or create an issue to initiate a discussion.</p></li><li><p>The UDF you are going to contribute has been well tested and can run normally in the production environment.</p></li></ol><h4 id="what-you-need-to-prepare" tabindex="-1"><a class="header-anchor" href="#what-you-need-to-prepare"><span>What you need to prepare</span></a></h4><ol><li>UDF source code</li><li>Test cases</li><li>Instructions</li></ol><h5 id="udf-source-code" tabindex="-1"><a class="header-anchor" href="#udf-source-code"><span>UDF Source Code</span></a></h5><ol><li>Create the UDF main class and related classes in <code>iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/udf/builtin</code> or in its subfolders.</li><li>Register your UDF in <code>iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/udf/builtin/BuiltinTimeSeriesGeneratingFunction.java</code>.</li></ol><h5 id="test-cases" tabindex="-1"><a class="header-anchor" href="#test-cases"><span>Test Cases</span></a></h5><p>At a minimum, you need to write integration tests for the UDF.</p><p>You can add a test class in <code>integration-test/src/test/java/org/apache/iotdb/db/it/udf</code>.</p><h5 id="instructions" tabindex="-1"><a class="header-anchor" href="#instructions"><span>Instructions</span></a></h5><p>The instructions need to include: the name and the function of the UDF, the attribute parameters that must be provided when the UDF is executed, the applicable scenarios, and the usage examples, etc.</p><p>The instructions should be added in <code>docs/UserGuide/Operation Manual/DML Data Manipulation Language.md</code>.</p><h4 id="submit-a-pr" tabindex="-1"><a class="header-anchor" href="#submit-a-pr"><span>Submit a PR</span></a></h4><p>When you have prepared the UDF source code, test cases, and instructions, you are ready to submit a Pull Request (PR) on <a href="https://github.com/apache/iotdb" target="_blank" rel="noopener noreferrer">Github<span><svg class="external-link-icon" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg><span class="external-link-icon-sr-only">open in new window</span></span></a>. You can refer to our code contribution guide to submit a PR: <a href="https://iotdb.apache.org/Development/HowToCommit.html" target="_blank" rel="noopener noreferrer">Pull Request Guide<span><svg class="external-link-icon" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg><span class="external-link-icon-sr-only">open in new window</span></span></a>.</p><h3 id="known-implementations" tabindex="-1"><a class="header-anchor" href="#known-implementations"><span>Known Implementations</span></a></h3><h4 id="built-in-udf" tabindex="-1"><a class="header-anchor" href="#built-in-udf"><span>Built-in UDF</span></a></h4><ol><li>Aggregate Functions, such as <code>SUM</code>. For details and examples, see the document <a class="route-link" href="/UserGuide/latest/Reference/Function-and-Expression.html#aggregate-functions">Aggregate Functions</a>.</li><li>Arithmetic Functions, such as <code>SIN</code>. For details and examples, see the document <a class="route-link" href="/UserGuide/latest/Reference/Function-and-Expression.html#arithmetic-operators-and-functions">Arithmetic Operators and Functions</a>.</li><li>Comparison Functions, such as <code>ON_OFF</code>. For details and examples, see the document <a class="route-link" href="/UserGuide/latest/Reference/Function-and-Expression.html#comparison-operators-and-functions">Comparison Operators and Functions</a>.</li><li>String Processing Functions, such as <code>STRING_CONTAINS</code>. For details and examples, see the document <a class="route-link" href="/UserGuide/latest/Reference/Function-and-Expression.html#string-processing">String Processing</a>.</li><li>Data Type Conversion Function, such as <code>CAST</code>. For details and examples, see the document <a class="route-link" href="/UserGuide/latest/Reference/Function-and-Expression.html#data-type-conversion-function">Data Type Conversion Function</a>.</li><li>Constant Timeseries Generating Functions, such as <code>CONST</code>. For details and examples, see the document <a class="route-link" href="/UserGuide/latest/Reference/Function-and-Expression.html#constant-timeseries-generating-functions">Constant Timeseries Generating Functions</a>.</li><li>Selector Functions, such as <code>TOP_K</code>. For details and examples, see the document <a class="route-link" href="/UserGuide/latest/Reference/Function-and-Expression.html#selector-functions">Selector Functions</a>.</li><li>Continuous Interval Functions, such as <code>ZERO_DURATION</code>. For details and examples, see the document <a class="route-link" href="/UserGuide/latest/Reference/Function-and-Expression.html#continuous-interval-functions">Continuous Interval Functions</a>.</li><li>Variation Trend Calculation Functions, such as <code>TIME_DIFFERENCE</code>. For details and examples, see the document <a class="route-link" href="/UserGuide/latest/Reference/Function-and-Expression.html#variation-trend-calculation-functions">Variation Trend Calculation Functions</a>.</li><li>Sample Functions, such as <code>M4</code>. For details and examples, see the document <a class="route-link" href="/UserGuide/latest/Reference/Function-and-Expression.html#sample-functions">Sample Functions</a>.</li><li>Change Points Function, such as <code>CHANGE_POINTS</code>. For details and examples, see the document <a class="route-link" href="/UserGuide/latest/Reference/Function-and-Expression.html#time-series-processing">Time-Series</a>.</li></ol><h4 id="data-quality-function-library" tabindex="-1"><a class="header-anchor" href="#data-quality-function-library"><span>Data Quality Function Library</span></a></h4><h5 id="about" tabindex="-1"><a class="header-anchor" href="#about"><span>About</span></a></h5><p>For applications based on time series data, data quality is vital. <strong>UDF Library</strong> is IoTDB User Defined Functions (UDF) about data quality, including data profiling, data quality evalution and data repairing. It effectively meets the demand for data quality in the industrial field.</p><h5 id="quick-start" tabindex="-1"><a class="header-anchor" href="#quick-start"><span>Quick Start</span></a></h5><p>The functions in this function library are not built-in functions, and must be loaded into the system before use.</p><ol><li><a href="https://archive.apache.org/dist/iotdb/1.0.1/apache-iotdb-1.0.1-library-udf-bin.zip" target="_blank" rel="noopener noreferrer">Download<span><svg class="external-link-icon" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg><span class="external-link-icon-sr-only">open in new window</span></span></a> the JAR with all dependencies and the script of registering UDF.</li><li>Copy the JAR package to <code>ext\udf</code> under the directory of IoTDB system (Please put JAR to this directory of all DataNodes if you use Cluster).</li><li>Run <code>sbin\start-server.bat</code> (for Windows) or <code>sbin\start-server.sh</code> (for Linux or MacOS) to start IoTDB server.</li><li>Copy the script to the directory of IoTDB system (under the root directory, at the same level as <code>sbin</code>), modify the parameters in the script if needed and run it to register UDF.</li></ol><h5 id="implemented-functions" tabindex="-1"><a class="header-anchor" href="#implemented-functions"><span>Implemented Functions</span></a></h5><ol><li>Data Quality related functions, such as <code>Completeness</code>. For details and examples, see the document <a class="route-link" href="/UserGuide/latest/Reference/UDF-Libraries.html#data-quality">Data-Quality</a>.</li><li>Data Profiling related functions, such as <code>ACF</code>. For details and examples, see the document <a class="route-link" href="/UserGuide/latest/Reference/UDF-Libraries.html#data-profiling">Data-Profiling</a>.</li><li>Anomaly Detection related functions, such as <code>IQR</code>. For details and examples, see the document <a class="route-link" href="/UserGuide/latest/Reference/UDF-Libraries.html#anomaly-detection">Anomaly-Detection</a>.</li><li>Frequency Domain Analysis related functions, such as <code>Conv</code>. For details and examples, see the document <a class="route-link" href="/UserGuide/latest/Reference/UDF-Libraries.html#frequency-domain-analysis">Frequency-Domain</a>.</li><li>Data Matching related functions, such as <code>DTW</code>. For details and examples, see the document <a class="route-link" href="/UserGuide/latest/Reference/UDF-Libraries.html#data-matching">Data-Matching</a>.</li><li>Data Repairing related functions, such as <code>TimestampRepair</code>. For details and examples, see the document <a class="route-link" href="/UserGuide/latest/Reference/UDF-Libraries.html#data-repairing">Data-Repairing</a>.</li><li>Series Discovery related functions, such as <code>ConsecutiveSequences</code>. For details and examples, see the document <a class="route-link" href="/UserGuide/latest/Reference/UDF-Libraries.html#series-discovery">Series-Discovery</a>.</li><li>Machine Learning related functions, such as <code>AR</code>. For details and examples, see the document <a class="route-link" href="/UserGuide/latest/Reference/UDF-Libraries.html#machine-learning">Machine-Learning</a>.</li></ol><h3 id="q-a" tabindex="-1"><a class="header-anchor" href="#q-a"><span>Q&amp;A</span></a></h3><p>Q1: How to modify the registered UDF?</p><p>A1: Assume that the name of the UDF is <code>example</code> and the full class name is <code>org.apache.iotdb.udf.ExampleUDTF</code>, which is introduced by <code>example.jar</code>.</p><ol><li>Unload the registered function by executing <code>DROP FUNCTION example</code>.</li><li>Delete <code>example.jar</code> under <code>iotdb-server-1.0.0-all-bin/ext/udf</code>.</li><li>Modify the logic in <code>org.apache.iotdb.udf.ExampleUDTF</code> and repackage it. The name of the JAR package can still be <code>example.jar</code>.</li><li>Upload the new JAR package to <code>iotdb-server-1.0.0-all-bin/ext/udf</code>.</li><li>Load the new UDF by executing <code>CREATE FUNCTION example AS &quot;org.apache.iotdb.udf.ExampleUDTF&quot;</code>.</li></ol></div><!--[--><!----><!--]--><footer class="vp-page-meta"><div class="vp-meta-item edit-link"><a href="https://github.com/apache/iotdb-docs/edit/main/src/UserGuide/latest/User-Manual/Database-Programming.md" rel="noopener noreferrer" target="_blank" aria-label="Found Error? Edit this page on GitHub" class="nav-link vp-meta-label"><!--[--><svg xmlns="http://www.w3.org/2000/svg" class="icon edit-icon" viewBox="0 0 1024 1024" fill="currentColor" aria-label="edit icon"><path d="M430.818 653.65a60.46 60.46 0 0 1-50.96-93.281l71.69-114.012 7.773-10.365L816.038 80.138A60.46 60.46 0 0 1 859.225 62a60.46 60.46 0 0 1 43.186 18.138l43.186 43.186a60.46 60.46 0 0 1 0 86.373L588.879 565.55l-8.637 8.637-117.466 68.234a60.46 60.46 0 0 1-31.958 11.229z"></path><path d="M728.802 962H252.891A190.883 190.883 0 0 1 62.008 771.98V296.934a190.883 190.883 0 0 1 190.883-192.61h267.754a60.46 60.46 0 0 1 0 120.92H252.891a69.962 69.962 0 0 0-69.098 69.099V771.98a69.962 69.962 0 0 0 69.098 69.098h475.911A69.962 69.962 0 0 0 797.9 771.98V503.363a60.46 60.46 0 1 1 120.922 0V771.98A190.883 190.883 0 0 1 728.802 962z"></path></svg><!--]-->Found Error? Edit this page on GitHub<span><svg class="external-link-icon" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg><span class="external-link-icon-sr-only">open in new window</span></span><!----></a></div><div class="vp-meta-item git-info"><div class="update-time"><span class="vp-meta-label">Last update: </span><!----></div><!----></div></footer><nav class="vp-page-nav"><a class="route-link nav-link prev" href="/UserGuide/latest/User-Manual/Data-Sync.html" aria-label="Data Sync"><div class="hint"><span class="arrow start"></span>Prev</div><div class="link"><!---->Data Sync</div></a><a class="route-link nav-link next" href="/UserGuide/latest/User-Manual/Authority-Management.html" aria-label="Authority Management"><div class="hint">Next<span class="arrow end"></span></div><div class="link">Authority Management<!----></div></a></nav><!----><!--[--><!----><!--]--><!--]--></main><!--]--><footer style="padding-bottom:2rem;"><span id="doc-version" style="display:none;">latest</span><p style="text-align:center;color:#909399;font-size:12px;margin:0 30px;">Copyright © 2024 The Apache Software Foundation.<br> Apache and the Apache feather logo are trademarks of The Apache Software Foundation</p><p style="text-align:center;margin-top:10px;color:#909399;font-size:12px;margin:0 30px;"><strong>Have a question?</strong> Connect with us on QQ, WeChat, or Slack. <a href="https://github.com/apache/iotdb/issues/1995">Join the community</a> now.</p></footer></div><!--]--><!--]--><!--[--><!----><!--]--><!--]--></div>
<script type="module" src="/assets/app-DrPcRZG6.js" defer></script>
</body>
</html>