diff --git a/docs/dev/404.html b/docs/dev/404.html index 26bf06d0..dcd94de3 100644 --- a/docs/dev/404.html +++ b/docs/dev/404.html @@ -1,17 +1,17 @@ - + - + Page Not Found | GlueSQL - - - + + +
Skip to main content

Page Not Found

We could not find what you were looking for.

Please contact the owner of the site that linked you to the original URL and let them know their link is broken.

- - + + \ No newline at end of file diff --git a/docs/dev/assets/css/styles.7e858986.css b/docs/dev/assets/css/styles.36de027f.css similarity index 80% rename from docs/dev/assets/css/styles.7e858986.css rename to docs/dev/assets/css/styles.36de027f.css index 48a015d0..f7f970f5 100644 --- a/docs/dev/assets/css/styles.7e858986.css +++ b/docs/dev/assets/css/styles.36de027f.css @@ -1 +1 @@ -@import url(https://fonts.googleapis.com/css2?family=Fira+Sans:wght@400;500;600&display=swap);@import url(https://fonts.googleapis.com/css2?family=Alfa+Slab+One&display=swap);.col,.container{padding:0 var(--ifm-spacing-horizontal);width:100%}.markdown>h2,.markdown>h3,.markdown>h4,.markdown>h5,.markdown>h6{margin-bottom:calc(var(--ifm-heading-vertical-rhythm-bottom)*var(--ifm-leading))}body,ol ol,ol ul,ul ol,ul ul{margin:0}pre,table{overflow:auto}blockquote,pre{margin:0 0 var(--ifm-spacing-vertical)}.breadcrumbs__link,.button{transition-timing-function:var(--ifm-transition-timing-default)}.button,code{vertical-align:middle}.button--outline.button--active,.button--outline:active,.button--outline:hover,:root{--ifm-button-color:var(--ifm-font-color-base-inverse)}.menu__link:hover,a{transition:color var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.navbar--dark,:root{--ifm-navbar-link-hover-color:var(--ifm-color-primary)}.menu,.navbar-sidebar{overflow-x:hidden}:root,html[data-theme=dark]{--ifm-color-emphasis-500:var(--ifm-color-gray-500)}.markdown li,article h1,body{word-wrap:break-word}.toggleButton_gllP,html{-webkit-tap-highlight-color:transparent}.clean-list,.containsTaskList_mC6p,.details_lb9f>summary,.dropdown__menu,.menu__list{list-style:none}:root{--ifm-color-scheme:light;--ifm-dark-value:10%;--ifm-darker-value:15%;--ifm-darkest-value:30%;--ifm-light-value:15%;--ifm-lighter-value:30%;--ifm-lightest-value:50%;--ifm-contrast-background-value:90%;--ifm-contrast-foreground-value:70%;--ifm-contrast-background-dark-value:70%;--ifm-contrast-foreground-dark-value:90%;--ifm-color-primary:#3578e5;--ifm-color-secondary:#ebedf0;--ifm-color-success:#00a400;--ifm-color-info:#54c7ec;--ifm-color-warning:#ffba00;--ifm-color-danger:#fa383e;--ifm-color-primary-dark:#306cce;--ifm-color-primary-darker:#2d66c3;--ifm-color-primary-darkest:#2554a0;--ifm-color-primary-light:#538ce9;--ifm-color-primary-lighter:#72a1ed;--ifm-color-primary-lightest:#9abcf2;--ifm-color-primary-contrast-background:#ebf2fc;--ifm-color-primary-contrast-foreground:#102445;--ifm-color-secondary-dark:#d4d5d8;--ifm-color-secondary-darker:#c8c9cc;--ifm-color-secondary-darkest:#a4a6a8;--ifm-color-secondary-light:#eef0f2;--ifm-color-secondary-lighter:#f1f2f5;--ifm-color-secondary-lightest:#f5f6f8;--ifm-color-secondary-contrast-background:#fdfdfe;--ifm-color-secondary-contrast-foreground:#474748;--ifm-color-success-dark:#009400;--ifm-color-success-darker:#008b00;--ifm-color-success-darkest:#007300;--ifm-color-success-light:#26b226;--ifm-color-success-lighter:#4dbf4d;--ifm-color-success-lightest:#80d280;--ifm-color-success-contrast-background:#e6f6e6;--ifm-color-success-contrast-foreground:#003100;--ifm-color-info-dark:#4cb3d4;--ifm-color-info-darker:#47a9c9;--ifm-color-info-darkest:#3b8ba5;--ifm-color-info-light:#6ecfef;--ifm-color-info-lighter:#87d8f2;--ifm-color-info-lightest:#aae3f6;--ifm-color-info-contrast-background:#eef9fd;--ifm-color-info-contrast-foreground:#193c47;--ifm-color-warning-dark:#e6a700;--ifm-color-warning-darker:#d99e00;--ifm-color-warning-darkest:#b38200;--ifm-color-warning-light:#ffc426;--ifm-color-warning-lighter:#ffcf4d;--ifm-color-warning-lightest:#ffdd80;--ifm-color-warning-contrast-background:#fff8e6;--ifm-color-warning-contrast-foreground:#4d3800;--ifm-color-danger-dark:#e13238;--ifm-color-danger-darker:#d53035;--ifm-color-danger-darkest:#af272b;--ifm-color-danger-light:#fb565b;--ifm-color-danger-lighter:#fb7478;--ifm-color-danger-lightest:#fd9c9f;--ifm-color-danger-contrast-background:#ffebec;--ifm-color-danger-contrast-foreground:#4b1113;--ifm-color-white:#fff;--ifm-color-black:#000;--ifm-color-gray-0:var(--ifm-color-white);--ifm-color-gray-100:#f5f6f7;--ifm-color-gray-200:#ebedf0;--ifm-color-gray-300:#dadde1;--ifm-color-gray-400:#ccd0d5;--ifm-color-gray-500:#bec3c9;--ifm-color-gray-600:#8d949e;--ifm-color-gray-700:#606770;--ifm-color-gray-800:#444950;--ifm-color-gray-900:#1c1e21;--ifm-color-gray-1000:var(--ifm-color-black);--ifm-color-emphasis-0:var(--ifm-color-gray-0);--ifm-color-emphasis-100:var(--ifm-color-gray-100);--ifm-color-emphasis-200:var(--ifm-color-gray-200);--ifm-color-emphasis-300:var(--ifm-color-gray-300);--ifm-color-emphasis-400:var(--ifm-color-gray-400);--ifm-color-emphasis-600:var(--ifm-color-gray-600);--ifm-color-emphasis-700:var(--ifm-color-gray-700);--ifm-color-emphasis-800:var(--ifm-color-gray-800);--ifm-color-emphasis-900:var(--ifm-color-gray-900);--ifm-color-emphasis-1000:var(--ifm-color-gray-1000);--ifm-color-content:var(--ifm-color-emphasis-900);--ifm-color-content-inverse:var(--ifm-color-emphasis-0);--ifm-color-content-secondary:#525860;--ifm-background-color:#0000;--ifm-background-surface-color:var(--ifm-color-content-inverse);--ifm-global-border-width:1px;--ifm-global-radius:0.4rem;--ifm-hover-overlay:#0000000d;--ifm-font-color-base:var(--ifm-color-content);--ifm-font-color-base-inverse:var(--ifm-color-content-inverse);--ifm-font-color-secondary:var(--ifm-color-content-secondary);--ifm-font-family-base:system-ui,-apple-system,Segoe UI,Roboto,Ubuntu,Cantarell,Noto Sans,sans-serif,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";--ifm-font-family-monospace:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--ifm-font-size-base:100%;--ifm-font-weight-light:300;--ifm-font-weight-normal:400;--ifm-font-weight-semibold:500;--ifm-font-weight-bold:700;--ifm-font-weight-base:var(--ifm-font-weight-normal);--ifm-line-height-base:1.65;--ifm-global-spacing:1rem;--ifm-spacing-vertical:var(--ifm-global-spacing);--ifm-spacing-horizontal:var(--ifm-global-spacing);--ifm-transition-fast:200ms;--ifm-transition-slow:400ms;--ifm-transition-timing-default:cubic-bezier(0.08,0.52,0.52,1);--ifm-global-shadow-lw:0 1px 2px 0 #0000001a;--ifm-global-shadow-md:0 5px 40px #0003;--ifm-global-shadow-tl:0 12px 28px 0 #0003,0 2px 4px 0 #0000001a;--ifm-z-index-dropdown:100;--ifm-z-index-fixed:200;--ifm-z-index-overlay:400;--ifm-container-width:1140px;--ifm-container-width-xl:1320px;--ifm-code-background:#f6f7f8;--ifm-code-border-radius:var(--ifm-global-radius);--ifm-code-font-size:90%;--ifm-code-padding-horizontal:0.1rem;--ifm-code-padding-vertical:0.1rem;--ifm-pre-background:var(--ifm-code-background);--ifm-pre-border-radius:var(--ifm-code-border-radius);--ifm-pre-color:inherit;--ifm-pre-line-height:1.45;--ifm-pre-padding:1rem;--ifm-heading-color:inherit;--ifm-heading-margin-top:0;--ifm-heading-margin-bottom:var(--ifm-spacing-vertical);--ifm-heading-font-family:var(--ifm-font-family-base);--ifm-heading-font-weight:var(--ifm-font-weight-bold);--ifm-heading-line-height:1.25;--ifm-h1-font-size:2rem;--ifm-h2-font-size:1.5rem;--ifm-h3-font-size:1.25rem;--ifm-h4-font-size:1rem;--ifm-h5-font-size:0.875rem;--ifm-h6-font-size:0.85rem;--ifm-image-alignment-padding:1.25rem;--ifm-leading-desktop:1.25;--ifm-leading:calc(var(--ifm-leading-desktop)*1rem);--ifm-list-left-padding:2rem;--ifm-list-margin:1rem;--ifm-list-item-margin:0.25rem;--ifm-list-paragraph-margin:1rem;--ifm-table-cell-padding:0.75rem;--ifm-table-background:#0000;--ifm-table-stripe-background:#00000008;--ifm-table-border-width:1px;--ifm-table-border-color:var(--ifm-color-emphasis-300);--ifm-table-head-background:inherit;--ifm-table-head-color:inherit;--ifm-table-head-font-weight:var(--ifm-font-weight-bold);--ifm-table-cell-color:inherit;--ifm-link-color:var(--ifm-color-primary);--ifm-link-decoration:none;--ifm-link-hover-color:var(--ifm-link-color);--ifm-link-hover-decoration:underline;--ifm-paragraph-margin-bottom:var(--ifm-leading);--ifm-blockquote-font-size:var(--ifm-font-size-base);--ifm-blockquote-border-left-width:2px;--ifm-blockquote-padding-horizontal:var(--ifm-spacing-horizontal);--ifm-blockquote-padding-vertical:0;--ifm-blockquote-shadow:none;--ifm-blockquote-color:var(--ifm-color-emphasis-800);--ifm-blockquote-border-color:var(--ifm-color-emphasis-300);--ifm-hr-background-color:var(--ifm-color-emphasis-500);--ifm-hr-height:1px;--ifm-hr-margin-vertical:1.5rem;--ifm-scrollbar-size:7px;--ifm-scrollbar-track-background-color:#f1f1f1;--ifm-scrollbar-thumb-background-color:silver;--ifm-scrollbar-thumb-hover-background-color:#a7a7a7;--ifm-alert-background-color:inherit;--ifm-alert-border-color:inherit;--ifm-alert-border-radius:var(--ifm-global-radius);--ifm-alert-border-width:0px;--ifm-alert-border-left-width:5px;--ifm-alert-color:var(--ifm-font-color-base);--ifm-alert-padding-horizontal:var(--ifm-spacing-horizontal);--ifm-alert-padding-vertical:var(--ifm-spacing-vertical);--ifm-alert-shadow:var(--ifm-global-shadow-lw);--ifm-avatar-intro-margin:1rem;--ifm-avatar-intro-alignment:inherit;--ifm-avatar-photo-size:3rem;--ifm-badge-background-color:inherit;--ifm-badge-border-color:inherit;--ifm-badge-border-radius:var(--ifm-global-radius);--ifm-badge-border-width:var(--ifm-global-border-width);--ifm-badge-color:var(--ifm-color-white);--ifm-badge-padding-horizontal:calc(var(--ifm-spacing-horizontal)*0.5);--ifm-badge-padding-vertical:calc(var(--ifm-spacing-vertical)*0.25);--ifm-breadcrumb-border-radius:1.5rem;--ifm-breadcrumb-spacing:0.5rem;--ifm-breadcrumb-color-active:var(--ifm-color-primary);--ifm-breadcrumb-item-background-active:var(--ifm-hover-overlay);--ifm-breadcrumb-padding-horizontal:0.8rem;--ifm-breadcrumb-padding-vertical:0.4rem;--ifm-breadcrumb-size-multiplier:1;--ifm-breadcrumb-separator:url('data:image/svg+xml;utf8,');--ifm-breadcrumb-separator-filter:none;--ifm-breadcrumb-separator-size:0.5rem;--ifm-breadcrumb-separator-size-multiplier:1.25;--ifm-button-background-color:inherit;--ifm-button-border-color:var(--ifm-button-background-color);--ifm-button-border-width:var(--ifm-global-border-width);--ifm-button-font-weight:var(--ifm-font-weight-bold);--ifm-button-padding-horizontal:1.5rem;--ifm-button-padding-vertical:0.375rem;--ifm-button-size-multiplier:1;--ifm-button-transition-duration:var(--ifm-transition-fast);--ifm-button-border-radius:calc(var(--ifm-global-radius)*var(--ifm-button-size-multiplier));--ifm-button-group-spacing:2px;--ifm-card-background-color:var(--ifm-background-surface-color);--ifm-card-border-radius:calc(var(--ifm-global-radius)*2);--ifm-card-horizontal-spacing:var(--ifm-global-spacing);--ifm-card-vertical-spacing:var(--ifm-global-spacing);--ifm-toc-border-color:var(--ifm-color-emphasis-300);--ifm-toc-link-color:var(--ifm-color-content-secondary);--ifm-toc-padding-vertical:0.5rem;--ifm-toc-padding-horizontal:0.5rem;--ifm-dropdown-background-color:var(--ifm-background-surface-color);--ifm-dropdown-font-weight:var(--ifm-font-weight-semibold);--ifm-dropdown-link-color:var(--ifm-font-color-base);--ifm-dropdown-hover-background-color:var(--ifm-hover-overlay);--ifm-footer-background-color:var(--ifm-color-emphasis-100);--ifm-footer-color:inherit;--ifm-footer-link-color:var(--ifm-color-emphasis-700);--ifm-footer-link-hover-color:var(--ifm-color-primary);--ifm-footer-link-horizontal-spacing:0.5rem;--ifm-footer-padding-horizontal:calc(var(--ifm-spacing-horizontal)*2);--ifm-footer-padding-vertical:calc(var(--ifm-spacing-vertical)*2);--ifm-footer-title-color:inherit;--ifm-footer-logo-max-width:min(30rem,90vw);--ifm-hero-background-color:var(--ifm-background-surface-color);--ifm-hero-text-color:var(--ifm-color-emphasis-800);--ifm-menu-color:var(--ifm-color-emphasis-700);--ifm-menu-color-active:var(--ifm-color-primary);--ifm-menu-color-background-active:var(--ifm-hover-overlay);--ifm-menu-color-background-hover:var(--ifm-hover-overlay);--ifm-menu-link-padding-horizontal:0.75rem;--ifm-menu-link-padding-vertical:0.375rem;--ifm-menu-link-sublist-icon:url('data:image/svg+xml;utf8,');--ifm-menu-link-sublist-icon-filter:none;--ifm-navbar-background-color:var(--ifm-background-surface-color);--ifm-navbar-height:3.75rem;--ifm-navbar-item-padding-horizontal:0.75rem;--ifm-navbar-item-padding-vertical:0.25rem;--ifm-navbar-link-color:var(--ifm-font-color-base);--ifm-navbar-link-active-color:var(--ifm-link-color);--ifm-navbar-padding-horizontal:var(--ifm-spacing-horizontal);--ifm-navbar-padding-vertical:calc(var(--ifm-spacing-vertical)*0.5);--ifm-navbar-shadow:var(--ifm-global-shadow-lw);--ifm-navbar-search-input-background-color:var(--ifm-color-emphasis-200);--ifm-navbar-search-input-color:var(--ifm-color-emphasis-800);--ifm-navbar-search-input-placeholder-color:var(--ifm-color-emphasis-500);--ifm-navbar-search-input-icon:url('data:image/svg+xml;utf8,');--ifm-navbar-sidebar-width:83vw;--ifm-pagination-border-radius:var(--ifm-global-radius);--ifm-pagination-color-active:var(--ifm-color-primary);--ifm-pagination-font-size:1rem;--ifm-pagination-item-active-background:var(--ifm-hover-overlay);--ifm-pagination-page-spacing:0.2em;--ifm-pagination-padding-horizontal:calc(var(--ifm-spacing-horizontal)*1);--ifm-pagination-padding-vertical:calc(var(--ifm-spacing-vertical)*0.25);--ifm-pagination-nav-border-radius:var(--ifm-global-radius);--ifm-pagination-nav-color-hover:var(--ifm-color-primary);--ifm-pills-color-active:var(--ifm-color-primary);--ifm-pills-color-background-active:var(--ifm-hover-overlay);--ifm-pills-spacing:0.125rem;--ifm-tabs-color:var(--ifm-font-color-secondary);--ifm-tabs-color-active:var(--ifm-color-primary);--ifm-tabs-color-active-border:var(--ifm-tabs-color-active);--ifm-tabs-padding-horizontal:1rem;--ifm-tabs-padding-vertical:1rem;--docusaurus-progress-bar-color:var(--ifm-color-primary);--ifm-color-primary:#0077be;--ifm-color-primary-dark:#005fa3;--ifm-color-primary-darker:#004c87;--ifm-color-primary-darkest:#003c6b;--ifm-color-primary-light:#0093e8;--ifm-color-primary-lighter:#00a3ff;--ifm-color-primary-lightest:#00baff;--ifm-code-font-size:95%;--docusaurus-highlighted-code-line-bg:#0000001a;--docusaurus-announcement-bar-height:auto;--docusaurus-collapse-button-bg:#0000;--docusaurus-collapse-button-bg-hover:#0000001a;--doc-sidebar-width:300px;--doc-sidebar-hidden-width:30px;--docusaurus-tag-list-border:var(--ifm-color-emphasis-300)}.badge--danger,.badge--info,.badge--primary,.badge--secondary,.badge--success,.badge--warning{--ifm-badge-border-color:var(--ifm-badge-background-color)}.button--link,.button--outline{--ifm-button-background-color:#0000}*{box-sizing:border-box}html{-webkit-font-smoothing:antialiased;-webkit-text-size-adjust:100%;text-size-adjust:100%;background-color:var(--ifm-background-color);color:var(--ifm-font-color-base);color-scheme:var(--ifm-color-scheme);font:var(--ifm-font-size-base)/var(--ifm-line-height-base) var(--ifm-font-family-base);text-rendering:optimizelegibility}iframe{border:0;color-scheme:auto}.container{margin:0 auto;max-width:var(--ifm-container-width)}.container--fluid{max-width:inherit}.row{display:flex;flex-wrap:wrap;margin:0 calc(var(--ifm-spacing-horizontal)*-1)}.margin-bottom--none,.margin-vert--none,.markdown>:last-child{margin-bottom:0!important}.margin-top--none,.margin-vert--none{margin-top:0!important}.row--no-gutters{margin-left:0;margin-right:0}.margin-horiz--none,.margin-right--none{margin-right:0!important}.row--no-gutters>.col{padding-left:0;padding-right:0}.row--align-top{align-items:flex-start}.row--align-bottom{align-items:flex-end}.menuExternalLink_NmtK,.row--align-center{align-items:center}.row--align-stretch{align-items:stretch}.row--align-baseline{align-items:baseline}.col{--ifm-col-width:100%;flex:1 0;margin-left:0;max-width:var(--ifm-col-width)}.padding-bottom--none,.padding-vert--none{padding-bottom:0!important}.padding-top--none,.padding-vert--none{padding-top:0!important}.padding-horiz--none,.padding-left--none{padding-left:0!important}.padding-horiz--none,.padding-right--none{padding-right:0!important}.col[class*=col--]{flex:0 0 var(--ifm-col-width)}.col--1{--ifm-col-width:8.33333%}.col--offset-1{margin-left:8.33333%}.col--2{--ifm-col-width:16.66667%}.col--offset-2{margin-left:16.66667%}.col--3{--ifm-col-width:25%}.col--offset-3{margin-left:25%}.col--4{--ifm-col-width:33.33333%}.col--offset-4{margin-left:33.33333%}.col--5{--ifm-col-width:41.66667%}.col--offset-5{margin-left:41.66667%}.col--6{--ifm-col-width:50%}.col--offset-6{margin-left:50%}.col--7{--ifm-col-width:58.33333%}.col--offset-7{margin-left:58.33333%}.col--8{--ifm-col-width:66.66667%}.col--offset-8{margin-left:66.66667%}.col--9{--ifm-col-width:75%}.col--offset-9{margin-left:75%}.col--10{--ifm-col-width:83.33333%}.col--offset-10{margin-left:83.33333%}.col--11{--ifm-col-width:91.66667%}.col--offset-11{margin-left:91.66667%}.col--12{--ifm-col-width:100%}.col--offset-12{margin-left:100%}.margin-horiz--none,.margin-left--none{margin-left:0!important}.margin--none{margin:0!important}.margin-bottom--xs,.margin-vert--xs{margin-bottom:.25rem!important}.margin-top--xs,.margin-vert--xs{margin-top:.25rem!important}.margin-horiz--xs,.margin-left--xs{margin-left:.25rem!important}.margin-horiz--xs,.margin-right--xs{margin-right:.25rem!important}.margin--xs{margin:.25rem!important}.margin-bottom--sm,.margin-vert--sm{margin-bottom:.5rem!important}.margin-top--sm,.margin-vert--sm{margin-top:.5rem!important}.margin-horiz--sm,.margin-left--sm{margin-left:.5rem!important}.margin-horiz--sm,.margin-right--sm{margin-right:.5rem!important}.margin--sm{margin:.5rem!important}.margin-bottom--md,.margin-vert--md{margin-bottom:1rem!important}.margin-top--md,.margin-vert--md{margin-top:1rem!important}.margin-horiz--md,.margin-left--md{margin-left:1rem!important}.margin-horiz--md,.margin-right--md{margin-right:1rem!important}.margin--md{margin:1rem!important}.margin-bottom--lg,.margin-vert--lg{margin-bottom:2rem!important}.margin-top--lg,.margin-vert--lg{margin-top:2rem!important}.margin-horiz--lg,.margin-left--lg{margin-left:2rem!important}.margin-horiz--lg,.margin-right--lg{margin-right:2rem!important}.margin--lg{margin:2rem!important}.margin-bottom--xl,.margin-vert--xl{margin-bottom:5rem!important}.margin-top--xl,.margin-vert--xl{margin-top:5rem!important}.margin-horiz--xl,.margin-left--xl{margin-left:5rem!important}.margin-horiz--xl,.margin-right--xl{margin-right:5rem!important}.margin--xl{margin:5rem!important}.padding--none{padding:0!important}.padding-bottom--xs,.padding-vert--xs{padding-bottom:.25rem!important}.padding-top--xs,.padding-vert--xs{padding-top:.25rem!important}.padding-horiz--xs,.padding-left--xs{padding-left:.25rem!important}.padding-horiz--xs,.padding-right--xs{padding-right:.25rem!important}.padding--xs{padding:.25rem!important}.padding-bottom--sm,.padding-vert--sm{padding-bottom:.5rem!important}.padding-top--sm,.padding-vert--sm{padding-top:.5rem!important}.padding-horiz--sm,.padding-left--sm{padding-left:.5rem!important}.padding-horiz--sm,.padding-right--sm{padding-right:.5rem!important}.padding--sm{padding:.5rem!important}.padding-bottom--md,.padding-vert--md{padding-bottom:1rem!important}.padding-top--md,.padding-vert--md{padding-top:1rem!important}.padding-horiz--md,.padding-left--md{padding-left:1rem!important}.padding-horiz--md,.padding-right--md{padding-right:1rem!important}.padding--md{padding:1rem!important}.padding-bottom--lg,.padding-vert--lg{padding-bottom:2rem!important}.padding-top--lg,.padding-vert--lg{padding-top:2rem!important}.padding-horiz--lg,.padding-left--lg{padding-left:2rem!important}.padding-horiz--lg,.padding-right--lg{padding-right:2rem!important}.padding--lg{padding:2rem!important}.padding-bottom--xl,.padding-vert--xl{padding-bottom:5rem!important}.padding-top--xl,.padding-vert--xl{padding-top:5rem!important}.padding-horiz--xl,.padding-left--xl{padding-left:5rem!important}.padding-horiz--xl,.padding-right--xl{padding-right:5rem!important}.padding--xl{padding:5rem!important}code{background-color:var(--ifm-code-background);border:.1rem solid #0000001a;border-radius:var(--ifm-code-border-radius);font-family:var(--ifm-font-family-monospace);font-size:var(--ifm-code-font-size);padding:var(--ifm-code-padding-vertical) var(--ifm-code-padding-horizontal)}a code{color:inherit}pre{background-color:var(--ifm-pre-background);border-radius:var(--ifm-pre-border-radius);color:var(--ifm-pre-color);font:var(--ifm-code-font-size)/var(--ifm-pre-line-height) var(--ifm-font-family-monospace);padding:var(--ifm-pre-padding)}pre code{background-color:initial;border:none;font-size:100%;line-height:inherit;padding:0}kbd{background-color:var(--ifm-color-emphasis-0);border:1px solid var(--ifm-color-emphasis-400);border-radius:.2rem;box-shadow:inset 0 -1px 0 var(--ifm-color-emphasis-400);color:var(--ifm-color-emphasis-800);font:80% var(--ifm-font-family-monospace);padding:.15rem .3rem}h1,h2,h3,h4,h5,h6{color:var(--ifm-heading-color);font-family:var(--ifm-heading-font-family);font-weight:var(--ifm-heading-font-weight);line-height:var(--ifm-heading-line-height);margin:var(--ifm-heading-margin-top) 0 var(--ifm-heading-margin-bottom) 0}h1{font-size:var(--ifm-h1-font-size)}h2{font-size:var(--ifm-h2-font-size)}h3{font-size:var(--ifm-h3-font-size)}h4{font-size:var(--ifm-h4-font-size)}h5{font-size:var(--ifm-h5-font-size)}h6{font-size:var(--ifm-h6-font-size)}img{max-width:100%}img[align=right]{padding-left:var(--image-alignment-padding)}img[align=left]{padding-right:var(--image-alignment-padding)}.markdown{--ifm-h1-vertical-rhythm-top:3;--ifm-h2-vertical-rhythm-top:2;--ifm-h3-vertical-rhythm-top:1.5;--ifm-heading-vertical-rhythm-top:1.25;--ifm-h1-vertical-rhythm-bottom:1.25;--ifm-heading-vertical-rhythm-bottom:1}.markdown:after,.markdown:before{content:"";display:table}.markdown:after{clear:both}.markdown h1:first-child{--ifm-h1-font-size:3rem;margin-bottom:calc(var(--ifm-h1-vertical-rhythm-bottom)*var(--ifm-leading))}.markdown>h2{--ifm-h2-font-size:2rem;margin-top:calc(var(--ifm-h2-vertical-rhythm-top)*var(--ifm-leading))}.markdown>h3{--ifm-h3-font-size:1.5rem;margin-top:calc(var(--ifm-h3-vertical-rhythm-top)*var(--ifm-leading))}.markdown>h4,.markdown>h5,.markdown>h6{margin-top:calc(var(--ifm-heading-vertical-rhythm-top)*var(--ifm-leading))}.markdown>p,.markdown>pre,.markdown>ul{margin-bottom:var(--ifm-leading)}.markdown li>p{margin-top:var(--ifm-list-paragraph-margin)}.markdown li+li{margin-top:var(--ifm-list-item-margin)}ol,ul{margin:0 0 var(--ifm-list-margin);padding-left:var(--ifm-list-left-padding)}ol ol,ul ol{list-style-type:lower-roman}ol ol ol,ol ul ol,ul ol ol,ul ul ol{list-style-type:lower-alpha}table{border-collapse:collapse;display:block;margin-bottom:var(--ifm-spacing-vertical)}table thead tr{border-bottom:2px solid var(--ifm-table-border-color)}table thead,table tr:nth-child(2n){background-color:var(--ifm-table-stripe-background)}table tr{background-color:var(--ifm-table-background);border-top:var(--ifm-table-border-width) solid var(--ifm-table-border-color)}table td,table th{border:var(--ifm-table-border-width) solid var(--ifm-table-border-color);padding:var(--ifm-table-cell-padding)}table th{background-color:var(--ifm-table-head-background);color:var(--ifm-table-head-color);font-weight:var(--ifm-table-head-font-weight)}table td{color:var(--ifm-table-cell-color)}strong{font-weight:var(--ifm-font-weight-bold)}a{color:var(--ifm-link-color);text-decoration:var(--ifm-link-decoration)}a:hover{color:var(--ifm-link-hover-color);text-decoration:var(--ifm-link-hover-decoration)}.button:hover,.text--no-decoration,.text--no-decoration:hover,a:not([href]){text-decoration:none}p{margin:0 0 var(--ifm-paragraph-margin-bottom)}blockquote{border-left:var(--ifm-blockquote-border-left-width) solid var(--ifm-blockquote-border-color);box-shadow:var(--ifm-blockquote-shadow);color:var(--ifm-blockquote-color);font-size:var(--ifm-blockquote-font-size);padding:var(--ifm-blockquote-padding-vertical) var(--ifm-blockquote-padding-horizontal)}blockquote>:first-child{margin-top:0}blockquote>:last-child{margin-bottom:0}hr{background-color:var(--ifm-hr-background-color);border:0;height:var(--ifm-hr-height);margin:var(--ifm-hr-margin-vertical) 0}.shadow--lw{box-shadow:var(--ifm-global-shadow-lw)!important}.shadow--md{box-shadow:var(--ifm-global-shadow-md)!important}.shadow--tl{box-shadow:var(--ifm-global-shadow-tl)!important}.text--primary,.wordWrapButtonEnabled_EoeP .wordWrapButtonIcon_Bwma{color:var(--ifm-color-primary)}.text--secondary{color:var(--ifm-color-secondary)}.text--success{color:var(--ifm-color-success)}.text--info{color:var(--ifm-color-info)}.text--warning{color:var(--ifm-color-warning)}.text--danger{color:var(--ifm-color-danger)}.text--center{text-align:center}.text--left{text-align:left}.text--justify{text-align:justify}.text--right{text-align:right}.text--capitalize{text-transform:capitalize}.text--lowercase{text-transform:lowercase}.admonitionHeading_tbUL,.alert__heading,.text--uppercase{text-transform:uppercase}.text--light{font-weight:var(--ifm-font-weight-light)}.text--normal{font-weight:var(--ifm-font-weight-normal)}.text--semibold{font-weight:var(--ifm-font-weight-semibold)}.text--bold{font-weight:var(--ifm-font-weight-bold)}.text--italic{font-style:italic}.text--truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.text--break{word-wrap:break-word!important;word-break:break-word!important}.clean-btn{background:none;border:none;color:inherit;cursor:pointer;font-family:inherit;padding:0}.alert,.alert .close{color:var(--ifm-alert-foreground-color)}.clean-list{padding-left:0}.alert--primary{--ifm-alert-background-color:var(--ifm-color-primary-contrast-background);--ifm-alert-background-color-highlight:#3578e526;--ifm-alert-foreground-color:var(--ifm-color-primary-contrast-foreground);--ifm-alert-border-color:var(--ifm-color-primary-dark)}.alert--secondary{--ifm-alert-background-color:var(--ifm-color-secondary-contrast-background);--ifm-alert-background-color-highlight:#ebedf026;--ifm-alert-foreground-color:var(--ifm-color-secondary-contrast-foreground);--ifm-alert-border-color:var(--ifm-color-secondary-dark)}.alert--success{--ifm-alert-background-color:var(--ifm-color-success-contrast-background);--ifm-alert-background-color-highlight:#00a40026;--ifm-alert-foreground-color:var(--ifm-color-success-contrast-foreground);--ifm-alert-border-color:var(--ifm-color-success-dark)}.alert--info{--ifm-alert-background-color:var(--ifm-color-info-contrast-background);--ifm-alert-background-color-highlight:#54c7ec26;--ifm-alert-foreground-color:var(--ifm-color-info-contrast-foreground);--ifm-alert-border-color:var(--ifm-color-info-dark)}.alert--warning{--ifm-alert-background-color:var(--ifm-color-warning-contrast-background);--ifm-alert-background-color-highlight:#ffba0026;--ifm-alert-foreground-color:var(--ifm-color-warning-contrast-foreground);--ifm-alert-border-color:var(--ifm-color-warning-dark)}.alert--danger{--ifm-alert-background-color:var(--ifm-color-danger-contrast-background);--ifm-alert-background-color-highlight:#fa383e26;--ifm-alert-foreground-color:var(--ifm-color-danger-contrast-foreground);--ifm-alert-border-color:var(--ifm-color-danger-dark)}.alert{--ifm-code-background:var(--ifm-alert-background-color-highlight);--ifm-link-color:var(--ifm-alert-foreground-color);--ifm-link-hover-color:var(--ifm-alert-foreground-color);--ifm-link-decoration:underline;--ifm-tabs-color:var(--ifm-alert-foreground-color);--ifm-tabs-color-active:var(--ifm-alert-foreground-color);--ifm-tabs-color-active-border:var(--ifm-alert-border-color);background-color:var(--ifm-alert-background-color);border:var(--ifm-alert-border-width) solid var(--ifm-alert-border-color);border-left-width:var(--ifm-alert-border-left-width);border-radius:var(--ifm-alert-border-radius);box-shadow:var(--ifm-alert-shadow);padding:var(--ifm-alert-padding-vertical) var(--ifm-alert-padding-horizontal)}.alert__heading{align-items:center;display:flex;font:700 var(--ifm-h5-font-size)/var(--ifm-heading-line-height) var(--ifm-heading-font-family);margin-bottom:.5rem}.alert__icon{display:inline-flex;margin-right:.4em}.alert__icon svg{fill:var(--ifm-alert-foreground-color);stroke:var(--ifm-alert-foreground-color);stroke-width:0}.alert .close{margin:calc(var(--ifm-alert-padding-vertical)*-1) calc(var(--ifm-alert-padding-horizontal)*-1) 0 0;opacity:.75}.alert .close:focus,.alert .close:hover{opacity:1}.alert a{text-decoration-color:var(--ifm-alert-border-color)}.alert a:hover{text-decoration-thickness:2px}.avatar{column-gap:var(--ifm-avatar-intro-margin);display:flex}.avatar__photo{border-radius:50%;display:block;height:var(--ifm-avatar-photo-size);overflow:hidden;width:var(--ifm-avatar-photo-size)}.card--full-height,.navbar__logo img,body,html{height:100%}.avatar__photo--sm{--ifm-avatar-photo-size:2rem}.avatar__photo--lg{--ifm-avatar-photo-size:4rem}.avatar__photo--xl{--ifm-avatar-photo-size:6rem}.avatar__intro{display:flex;flex:1 1;flex-direction:column;justify-content:center;text-align:var(--ifm-avatar-intro-alignment)}.badge,.breadcrumbs__item,.breadcrumbs__link,.button,.dropdown>.navbar__link:after{display:inline-block}.avatar__name{font:700 var(--ifm-h4-font-size)/var(--ifm-heading-line-height) var(--ifm-font-family-base)}.avatar__subtitle{margin-top:.25rem}.avatar--vertical{--ifm-avatar-intro-alignment:center;--ifm-avatar-intro-margin:0.5rem;align-items:center;flex-direction:column}.badge{background-color:var(--ifm-badge-background-color);border:var(--ifm-badge-border-width) solid var(--ifm-badge-border-color);border-radius:var(--ifm-badge-border-radius);color:var(--ifm-badge-color);font-size:75%;font-weight:var(--ifm-font-weight-bold);line-height:1;padding:var(--ifm-badge-padding-vertical) var(--ifm-badge-padding-horizontal)}.badge--primary{--ifm-badge-background-color:var(--ifm-color-primary)}.badge--secondary{--ifm-badge-background-color:var(--ifm-color-secondary);color:var(--ifm-color-black)}.breadcrumbs__link,.button.button--secondary.button--outline:not(.button--active):not(:hover){color:var(--ifm-font-color-base)}.badge--success{--ifm-badge-background-color:var(--ifm-color-success)}.badge--info{--ifm-badge-background-color:var(--ifm-color-info)}.badge--warning{--ifm-badge-background-color:var(--ifm-color-warning)}.badge--danger{--ifm-badge-background-color:var(--ifm-color-danger)}.breadcrumbs{margin-bottom:0;padding-left:0}.breadcrumbs__item:not(:last-child):after{background:var(--ifm-breadcrumb-separator) center;content:" ";display:inline-block;filter:var(--ifm-breadcrumb-separator-filter);height:calc(var(--ifm-breadcrumb-separator-size)*var(--ifm-breadcrumb-size-multiplier)*var(--ifm-breadcrumb-separator-size-multiplier));margin:0 var(--ifm-breadcrumb-spacing);opacity:.5;width:calc(var(--ifm-breadcrumb-separator-size)*var(--ifm-breadcrumb-size-multiplier)*var(--ifm-breadcrumb-separator-size-multiplier))}.breadcrumbs__item--active .breadcrumbs__link{background:var(--ifm-breadcrumb-item-background-active);color:var(--ifm-breadcrumb-color-active)}.breadcrumbs__link{border-radius:var(--ifm-breadcrumb-border-radius);font-size:calc(1rem*var(--ifm-breadcrumb-size-multiplier));padding:calc(var(--ifm-breadcrumb-padding-vertical)*var(--ifm-breadcrumb-size-multiplier)) calc(var(--ifm-breadcrumb-padding-horizontal)*var(--ifm-breadcrumb-size-multiplier));transition-duration:var(--ifm-transition-fast);transition-property:background,color}.breadcrumbs__link:any-link:hover,.breadcrumbs__link:link:hover,.breadcrumbs__link:visited:hover,area[href].breadcrumbs__link:hover{background:var(--ifm-breadcrumb-item-background-active);text-decoration:none}.breadcrumbs--sm{--ifm-breadcrumb-size-multiplier:0.8}.breadcrumbs--lg{--ifm-breadcrumb-size-multiplier:1.2}.button{background-color:var(--ifm-button-background-color);border:var(--ifm-button-border-width) solid var(--ifm-button-border-color);border-radius:var(--ifm-button-border-radius);cursor:pointer;font-size:calc(.875rem*var(--ifm-button-size-multiplier));font-weight:var(--ifm-button-font-weight);line-height:1.5;padding:calc(var(--ifm-button-padding-vertical)*var(--ifm-button-size-multiplier)) calc(var(--ifm-button-padding-horizontal)*var(--ifm-button-size-multiplier));text-align:center;transition-duration:var(--ifm-button-transition-duration);transition-property:color,background,border-color;-webkit-user-select:none;user-select:none;white-space:nowrap}.button,.button:hover{color:var(--ifm-button-color)}.button--outline{--ifm-button-color:var(--ifm-button-border-color)}.button--outline:hover{--ifm-button-background-color:var(--ifm-button-border-color)}.button--link{--ifm-button-border-color:#0000;color:var(--ifm-link-color);text-decoration:var(--ifm-link-decoration)}.button--link.button--active,.button--link:active,.button--link:hover{color:var(--ifm-link-hover-color);text-decoration:var(--ifm-link-hover-decoration)}.button.disabled,.button:disabled,.button[disabled]{opacity:.65;pointer-events:none}.button--sm{--ifm-button-size-multiplier:0.8}.button--lg{--ifm-button-size-multiplier:1.35}.button--block{display:block;width:100%}.button.button--secondary{color:var(--ifm-color-gray-900)}:where(.button--primary){--ifm-button-background-color:var(--ifm-color-primary);--ifm-button-border-color:var(--ifm-color-primary)}:where(.button--primary):not(.button--outline):hover{--ifm-button-background-color:var(--ifm-color-primary-dark);--ifm-button-border-color:var(--ifm-color-primary-dark)}.button--primary.button--active,.button--primary:active{--ifm-button-background-color:var(--ifm-color-primary-darker);--ifm-button-border-color:var(--ifm-color-primary-darker)}:where(.button--secondary){--ifm-button-background-color:var(--ifm-color-secondary);--ifm-button-border-color:var(--ifm-color-secondary)}:where(.button--secondary):not(.button--outline):hover{--ifm-button-background-color:var(--ifm-color-secondary-dark);--ifm-button-border-color:var(--ifm-color-secondary-dark)}.button--secondary.button--active,.button--secondary:active{--ifm-button-background-color:var(--ifm-color-secondary-darker);--ifm-button-border-color:var(--ifm-color-secondary-darker)}:where(.button--success){--ifm-button-background-color:var(--ifm-color-success);--ifm-button-border-color:var(--ifm-color-success)}:where(.button--success):not(.button--outline):hover{--ifm-button-background-color:var(--ifm-color-success-dark);--ifm-button-border-color:var(--ifm-color-success-dark)}.button--success.button--active,.button--success:active{--ifm-button-background-color:var(--ifm-color-success-darker);--ifm-button-border-color:var(--ifm-color-success-darker)}:where(.button--info){--ifm-button-background-color:var(--ifm-color-info);--ifm-button-border-color:var(--ifm-color-info)}:where(.button--info):not(.button--outline):hover{--ifm-button-background-color:var(--ifm-color-info-dark);--ifm-button-border-color:var(--ifm-color-info-dark)}.button--info.button--active,.button--info:active{--ifm-button-background-color:var(--ifm-color-info-darker);--ifm-button-border-color:var(--ifm-color-info-darker)}:where(.button--warning){--ifm-button-background-color:var(--ifm-color-warning);--ifm-button-border-color:var(--ifm-color-warning)}:where(.button--warning):not(.button--outline):hover{--ifm-button-background-color:var(--ifm-color-warning-dark);--ifm-button-border-color:var(--ifm-color-warning-dark)}.button--warning.button--active,.button--warning:active{--ifm-button-background-color:var(--ifm-color-warning-darker);--ifm-button-border-color:var(--ifm-color-warning-darker)}:where(.button--danger){--ifm-button-background-color:var(--ifm-color-danger);--ifm-button-border-color:var(--ifm-color-danger)}:where(.button--danger):not(.button--outline):hover{--ifm-button-background-color:var(--ifm-color-danger-dark);--ifm-button-border-color:var(--ifm-color-danger-dark)}.button--danger.button--active,.button--danger:active{--ifm-button-background-color:var(--ifm-color-danger-darker);--ifm-button-border-color:var(--ifm-color-danger-darker)}.button-group{display:inline-flex;gap:var(--ifm-button-group-spacing)}.button-group>.button:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.button-group>.button:not(:last-child){border-bottom-right-radius:0;border-top-right-radius:0}.button-group--block{display:flex;justify-content:stretch}.button-group--block>.button{flex-grow:1}.card{background-color:var(--ifm-card-background-color);border-radius:var(--ifm-card-border-radius);box-shadow:var(--ifm-global-shadow-lw);display:flex;flex-direction:column;overflow:hidden}.card__image{padding-top:var(--ifm-card-vertical-spacing)}.card__image:first-child{padding-top:0}.card__body,.card__footer,.card__header{padding:var(--ifm-card-vertical-spacing) var(--ifm-card-horizontal-spacing)}.card__body:not(:last-child),.card__footer:not(:last-child),.card__header:not(:last-child){padding-bottom:0}.card__body>:last-child,.card__footer>:last-child,.card__header>:last-child{margin-bottom:0}.card__footer{margin-top:auto}.table-of-contents{font-size:.8rem;margin-bottom:0;padding:var(--ifm-toc-padding-vertical) 0}.table-of-contents,.table-of-contents ul{list-style:none;padding-left:var(--ifm-toc-padding-horizontal)}.table-of-contents li{margin:var(--ifm-toc-padding-vertical) var(--ifm-toc-padding-horizontal)}.table-of-contents__left-border{border-left:1px solid var(--ifm-toc-border-color)}.table-of-contents__link{color:var(--ifm-toc-link-color);display:block}.table-of-contents__link--active,.table-of-contents__link--active code,.table-of-contents__link:hover,.table-of-contents__link:hover code{color:var(--ifm-color-primary);text-decoration:none}.close{color:var(--ifm-color-black);float:right;font-size:1.5rem;font-weight:var(--ifm-font-weight-bold);line-height:1;opacity:.5;padding:1rem;transition:opacity var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.close:hover{opacity:.7}.close:focus,.theme-code-block-highlighted-line .codeLineNumber_Tfdd:before{opacity:.8}.dropdown{display:inline-flex;font-weight:var(--ifm-dropdown-font-weight);position:relative;vertical-align:top}.dropdown--hoverable:hover .dropdown__menu,.dropdown--show .dropdown__menu{opacity:1;pointer-events:all;transform:translateY(-1px);visibility:visible}#nprogress,.dropdown__menu,.navbar__item.dropdown .navbar__link:not([href]){pointer-events:none}.dropdown--right .dropdown__menu{left:inherit;right:0}.dropdown--nocaret .navbar__link:after{content:none!important}.dropdown__menu{background-color:var(--ifm-dropdown-background-color);border-radius:var(--ifm-global-radius);box-shadow:var(--ifm-global-shadow-md);left:0;max-height:80vh;min-width:10rem;opacity:0;overflow-y:auto;padding:.5rem;position:absolute;top:calc(100% - var(--ifm-navbar-item-padding-vertical) + .3rem);transform:translateY(-.625rem);transition-duration:var(--ifm-transition-fast);transition-property:opacity,transform,visibility;transition-timing-function:var(--ifm-transition-timing-default);visibility:hidden;z-index:var(--ifm-z-index-dropdown)}.sidebar_re4s,.tableOfContents_bqdL{max-height:calc(100vh - var(--ifm-navbar-height) - 2rem);overflow-y:auto}.menu__caret,.menu__link,.menu__list-item-collapsible{border-radius:.25rem;transition:background var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.dropdown__link{border-radius:.25rem;color:var(--ifm-dropdown-link-color);display:block;font-size:.875rem;margin-top:.2rem;padding:.25rem .5rem;white-space:nowrap}.dropdown__link--active,.dropdown__link:hover{background-color:var(--ifm-dropdown-hover-background-color);color:var(--ifm-dropdown-link-color);text-decoration:none}.dropdown__link--active,.dropdown__link--active:hover{--ifm-dropdown-link-color:var(--ifm-link-color)}.dropdown>.navbar__link:after{border-color:currentcolor #0000;border-style:solid;border-width:.4em .4em 0;content:"";margin-left:.3em;position:relative;top:2px;transform:translateY(-50%)}.footer{background-color:var(--ifm-footer-background-color);color:var(--ifm-footer-color);padding:var(--ifm-footer-padding-vertical) var(--ifm-footer-padding-horizontal)}.footer--dark{--ifm-footer-background-color:#303846;--ifm-footer-color:var(--ifm-footer-link-color);--ifm-footer-link-color:var(--ifm-color-secondary);--ifm-footer-title-color:var(--ifm-color-white)}.footer__links{margin-bottom:1rem}.footer__link-item{color:var(--ifm-footer-link-color);line-height:2}.footer__link-item:hover{color:var(--ifm-footer-link-hover-color)}.footer__link-separator{margin:0 var(--ifm-footer-link-horizontal-spacing)}.footer__logo{margin-top:1rem;max-width:var(--ifm-footer-logo-max-width)}.footer__title{color:var(--ifm-footer-title-color);font:700 var(--ifm-h4-font-size)/var(--ifm-heading-line-height) var(--ifm-font-family-base);margin-bottom:var(--ifm-heading-margin-bottom)}.menu,.navbar__link{font-weight:var(--ifm-font-weight-semibold)}.docItemContainer_Djhp article>:first-child,.docItemContainer_Djhp header+*,.footer__item{margin-top:0}.admonitionContent_S0QG>:last-child,.collapsibleContent_i85q>:last-child,.footer__items{margin-bottom:0}.codeBlockStandalone_MEMb,[type=checkbox]{padding:0}.hero{align-items:center;background-color:var(--ifm-hero-background-color);color:var(--ifm-hero-text-color);display:flex;padding:4rem 2rem}.hero--primary{--ifm-hero-background-color:var(--ifm-color-primary);--ifm-hero-text-color:var(--ifm-font-color-base-inverse)}.hero--dark{--ifm-hero-background-color:#303846;--ifm-hero-text-color:var(--ifm-color-white)}.hero__title,.title_f1Hy{font-size:3rem}.hero__subtitle{font-size:1.5rem}.menu__list{margin:0;padding-left:0}.menu__caret,.menu__link{padding:var(--ifm-menu-link-padding-vertical) var(--ifm-menu-link-padding-horizontal)}.menu__list .menu__list{flex:0 0 100%;margin-top:.25rem;padding-left:var(--ifm-menu-link-padding-horizontal)}.menu__list-item:not(:first-child){margin-top:.25rem}.menu__list-item--collapsed .menu__list{height:0;overflow:hidden}.details_lb9f[data-collapsed=false].isBrowser_bmU9>summary:before,.details_lb9f[open]:not(.isBrowser_bmU9)>summary:before,.menu__list-item--collapsed .menu__caret:before,.menu__list-item--collapsed .menu__link--sublist:after{transform:rotate(90deg)}.menu__list-item-collapsible{display:flex;flex-wrap:wrap;position:relative}.menu__caret:hover,.menu__link:hover,.menu__list-item-collapsible--active,.menu__list-item-collapsible:hover{background:var(--ifm-menu-color-background-hover)}.menu__list-item-collapsible .menu__link--active,.menu__list-item-collapsible .menu__link:hover{background:none!important}.menu__caret,.menu__link{align-items:center;display:flex}.menu__link{color:var(--ifm-menu-color);flex:1;line-height:1.25}.menu__link:hover{color:var(--ifm-menu-color);text-decoration:none}.menu__caret:before,.menu__link--sublist-caret:after{content:"";height:1.25rem;transform:rotate(180deg);transition:transform var(--ifm-transition-fast) linear;width:1.25rem;filter:var(--ifm-menu-link-sublist-icon-filter)}.menu__link--sublist-caret:after{background:var(--ifm-menu-link-sublist-icon) 50%/2rem 2rem;margin-left:auto;min-width:1.25rem}.menu__link--active,.menu__link--active:hover{color:var(--ifm-menu-color-active)}.navbar__brand,.navbar__link{color:var(--ifm-navbar-link-color)}.menu__link--active:not(.menu__link--sublist){background-color:var(--ifm-menu-color-background-active)}.menu__caret:before{background:var(--ifm-menu-link-sublist-icon) 50%/2rem 2rem}.navbar--dark,html[data-theme=dark]{--ifm-menu-link-sublist-icon-filter:invert(100%) sepia(94%) saturate(17%) hue-rotate(223deg) brightness(104%) contrast(98%)}.navbar{background-color:var(--ifm-navbar-background-color);box-shadow:var(--ifm-navbar-shadow);height:var(--ifm-navbar-height);padding:var(--ifm-navbar-padding-vertical) var(--ifm-navbar-padding-horizontal)}.navbar,.navbar>.container,.navbar>.container-fluid{display:flex}.navbar--fixed-top{position:sticky;top:0;z-index:var(--ifm-z-index-fixed)}.navbar-sidebar,.navbar-sidebar__backdrop{bottom:0;opacity:0;position:fixed;transition-duration:var(--ifm-transition-fast);transition-timing-function:ease-in-out;left:0;top:0;visibility:hidden}.navbar__inner{display:flex;flex-wrap:wrap;justify-content:space-between;width:100%}.navbar__brand{align-items:center;display:flex;margin-right:1rem;min-width:0}.navbar__brand:hover{color:var(--ifm-navbar-link-hover-color);text-decoration:none}.announcementBarContent_xLdY,.navbar__title{flex:1 1 auto}.navbar__toggle{display:none;margin-right:.5rem}.navbar__logo{flex:0 0 auto;height:2rem;margin-right:.5rem}.navbar__items{align-items:center;display:flex;flex:1;min-width:0}.navbar__items--center{flex:0 0 auto}.navbar__items--center .navbar__brand{margin:0}.navbar__items--center+.navbar__items--right{flex:1}.navbar__items--right{flex:0 0 auto;justify-content:flex-end}.navbar__items--right>:last-child{padding-right:0}.navbar__item{display:inline-block;padding:var(--ifm-navbar-item-padding-vertical) var(--ifm-navbar-item-padding-horizontal)}.navbar__link--active,.navbar__link:hover{color:var(--ifm-navbar-link-hover-color);text-decoration:none}.navbar--dark,.navbar--primary{--ifm-menu-color:var(--ifm-color-gray-300);--ifm-navbar-link-color:var(--ifm-color-gray-100);--ifm-navbar-search-input-background-color:#ffffff1a;--ifm-navbar-search-input-placeholder-color:#ffffff80;color:var(--ifm-color-white)}.navbar--dark{--ifm-navbar-background-color:#242526;--ifm-menu-color-background-active:#ffffff0d;--ifm-navbar-search-input-color:var(--ifm-color-white)}.navbar--primary{--ifm-navbar-background-color:var(--ifm-color-primary);--ifm-navbar-link-hover-color:var(--ifm-color-white);--ifm-menu-color-active:var(--ifm-color-white);--ifm-navbar-search-input-color:var(--ifm-color-emphasis-500)}.navbar__search-input{-webkit-appearance:none;appearance:none;background:var(--ifm-navbar-search-input-background-color) var(--ifm-navbar-search-input-icon) no-repeat .75rem center/1rem 1rem;border:none;border-radius:2rem;color:var(--ifm-navbar-search-input-color);cursor:text;display:inline-block;font-size:.9rem;height:2rem;padding:0 .5rem 0 2.25rem;width:12.5rem}.navbar__search-input::placeholder{color:var(--ifm-navbar-search-input-placeholder-color)}.navbar-sidebar{background-color:var(--ifm-navbar-background-color);box-shadow:var(--ifm-global-shadow-md);transform:translate3d(-100%,0,0);transition-property:opacity,visibility,transform;width:var(--ifm-navbar-sidebar-width)}.navbar-sidebar--show .navbar-sidebar,.navbar-sidebar__items{transform:translateZ(0)}.navbar-sidebar--show .navbar-sidebar,.navbar-sidebar--show .navbar-sidebar__backdrop{opacity:1;visibility:visible}.navbar-sidebar__backdrop{background-color:#0009;right:0;transition-property:opacity,visibility}.navbar-sidebar__brand{align-items:center;box-shadow:var(--ifm-navbar-shadow);display:flex;flex:1;height:var(--ifm-navbar-height);padding:var(--ifm-navbar-padding-vertical) var(--ifm-navbar-padding-horizontal)}.navbar-sidebar__items{display:flex;height:calc(100% - var(--ifm-navbar-height));transition:transform var(--ifm-transition-fast) ease-in-out}.navbar-sidebar__items--show-secondary{transform:translate3d(calc((var(--ifm-navbar-sidebar-width))*-1),0,0)}.navbar-sidebar__item{flex-shrink:0;padding:.5rem;width:calc(var(--ifm-navbar-sidebar-width))}.navbar-sidebar__back{background:var(--ifm-menu-color-background-active);font-size:15px;font-weight:var(--ifm-button-font-weight);margin:0 0 .2rem -.5rem;padding:.6rem 1.5rem;position:relative;text-align:left;top:-.5rem;width:calc(100% + 1rem)}.navbar-sidebar__close{display:flex;margin-left:auto}.pagination{column-gap:var(--ifm-pagination-page-spacing);display:flex;font-size:var(--ifm-pagination-font-size);padding-left:0}.pagination--sm{--ifm-pagination-font-size:0.8rem;--ifm-pagination-padding-horizontal:0.8rem;--ifm-pagination-padding-vertical:0.2rem}.pagination--lg{--ifm-pagination-font-size:1.2rem;--ifm-pagination-padding-horizontal:1.2rem;--ifm-pagination-padding-vertical:0.3rem}.pagination__item{display:inline-flex}.pagination__item>span{padding:var(--ifm-pagination-padding-vertical)}.pagination__item--active .pagination__link{color:var(--ifm-pagination-color-active)}.pagination__item--active .pagination__link,.pagination__item:not(.pagination__item--active):hover .pagination__link{background:var(--ifm-pagination-item-active-background)}.pagination__item--disabled,.pagination__item[disabled]{opacity:.25;pointer-events:none}.pagination__link{border-radius:var(--ifm-pagination-border-radius);color:var(--ifm-font-color-base);display:inline-block;padding:var(--ifm-pagination-padding-vertical) var(--ifm-pagination-padding-horizontal);transition:background var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.pagination__link:hover,.sidebarItemLink_mo7H:hover{text-decoration:none}.pagination-nav{grid-gap:var(--ifm-spacing-horizontal);display:grid;gap:var(--ifm-spacing-horizontal);grid-template-columns:repeat(2,1fr)}.pagination-nav__link{border:1px solid var(--ifm-color-emphasis-300);border-radius:var(--ifm-pagination-nav-border-radius);display:block;height:100%;line-height:var(--ifm-heading-line-height);padding:var(--ifm-global-spacing);transition:border-color var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.pagination-nav__link:hover{border-color:var(--ifm-pagination-nav-color-hover);text-decoration:none}.pagination-nav__link--next{grid-column:2/3;text-align:right}.pagination-nav__label{font-size:var(--ifm-h4-font-size);font-weight:var(--ifm-heading-font-weight);word-break:break-word}.pagination-nav__link--prev .pagination-nav__label:before{content:"« "}.pagination-nav__link--next .pagination-nav__label:after{content:" »"}.pagination-nav__sublabel{color:var(--ifm-color-content-secondary);font-size:var(--ifm-h5-font-size);font-weight:var(--ifm-font-weight-semibold);margin-bottom:.25rem}.pills__item,.sidebarItemTitle_pO2u,.tabs{font-weight:var(--ifm-font-weight-bold)}.pills{display:flex;gap:var(--ifm-pills-spacing);padding-left:0}.pills__item{border-radius:.5rem;cursor:pointer;display:inline-block;padding:.25rem 1rem;transition:background var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.tabs,:not(.containsTaskList_mC6p>li)>.containsTaskList_mC6p{padding-left:0}.pills__item--active{color:var(--ifm-pills-color-active)}.pills__item--active,.pills__item:not(.pills__item--active):hover{background:var(--ifm-pills-color-background-active)}.pills--block{justify-content:stretch}.pills--block .pills__item{flex-grow:1;text-align:center}.tabs{color:var(--ifm-tabs-color);display:flex;margin-bottom:0;overflow-x:auto}.tabs__item{border-bottom:3px solid #0000;border-radius:var(--ifm-global-radius);cursor:pointer;display:inline-flex;padding:var(--ifm-tabs-padding-vertical) var(--ifm-tabs-padding-horizontal);transition:background-color var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.tabs__item--active{border-bottom-color:var(--ifm-tabs-color-active-border);border-bottom-left-radius:0;border-bottom-right-radius:0;color:var(--ifm-tabs-color-active)}.tabs__item:hover{background-color:var(--ifm-hover-overlay)}.tabs--block{justify-content:stretch}.tabs--block .tabs__item{flex-grow:1;justify-content:center}html[data-theme=dark]{--ifm-color-scheme:dark;--ifm-color-emphasis-0:var(--ifm-color-gray-1000);--ifm-color-emphasis-100:var(--ifm-color-gray-900);--ifm-color-emphasis-200:var(--ifm-color-gray-800);--ifm-color-emphasis-300:var(--ifm-color-gray-700);--ifm-color-emphasis-400:var(--ifm-color-gray-600);--ifm-color-emphasis-600:var(--ifm-color-gray-400);--ifm-color-emphasis-700:var(--ifm-color-gray-300);--ifm-color-emphasis-800:var(--ifm-color-gray-200);--ifm-color-emphasis-900:var(--ifm-color-gray-100);--ifm-color-emphasis-1000:var(--ifm-color-gray-0);--ifm-background-color:#1b1b1d;--ifm-background-surface-color:#242526;--ifm-hover-overlay:#ffffff0d;--ifm-color-content:#e3e3e3;--ifm-color-content-secondary:#fff;--ifm-breadcrumb-separator-filter:invert(64%) sepia(11%) saturate(0%) hue-rotate(149deg) brightness(99%) contrast(95%);--ifm-code-background:#ffffff1a;--ifm-scrollbar-track-background-color:#444;--ifm-scrollbar-thumb-background-color:#686868;--ifm-scrollbar-thumb-hover-background-color:#7a7a7a;--ifm-table-stripe-background:#ffffff12;--ifm-toc-border-color:var(--ifm-color-emphasis-200);--ifm-color-primary-contrast-background:#102445;--ifm-color-primary-contrast-foreground:#ebf2fc;--ifm-color-secondary-contrast-background:#474748;--ifm-color-secondary-contrast-foreground:#fdfdfe;--ifm-color-success-contrast-background:#003100;--ifm-color-success-contrast-foreground:#e6f6e6;--ifm-color-info-contrast-background:#193c47;--ifm-color-info-contrast-foreground:#eef9fd;--ifm-color-warning-contrast-background:#4d3800;--ifm-color-warning-contrast-foreground:#fff8e6;--ifm-color-danger-contrast-background:#4b1113;--ifm-color-danger-contrast-foreground:#ffebec}#nprogress .bar{background:var(--docusaurus-progress-bar-color);height:2px;left:0;position:fixed;top:0;width:100%;z-index:1031}#nprogress .peg{box-shadow:0 0 10px var(--docusaurus-progress-bar-color),0 0 5px var(--docusaurus-progress-bar-color);height:100%;opacity:1;position:absolute;right:0;transform:rotate(3deg) translateY(-4px);width:100px}body,h2,h3,h4,h5,h6{font-family:Fira Sans,-apple-system,sans-serif}.navbar__brand b,h1{font-family:Alfa Slab One,serif;font-weight:300}article h1{padding:25px 30px 0 5px;width:100%}h2{font-weight:600}h3,h4,h5,h6{font-weight:500}.navbar__brand b{font-size:30px}footer.footer--dark{background-color:#2a3439}body:not(.navigation-with-keyboard) :not(input):focus{outline:0}#__docusaurus-base-url-issue-banner-container,.docSidebarContainer_b6E3,.sidebarLogo_isFc,.themedImage_ToTc,[data-theme=dark] .lightToggleIcon_pyhR,[data-theme=light] .darkToggleIcon_wfgR,html[data-announcement-bar-initially-dismissed=true] .announcementBar_mb4j{display:none}.skipToContent_fXgn{background-color:var(--ifm-background-surface-color);color:var(--ifm-color-emphasis-900);left:100%;padding:calc(var(--ifm-global-spacing)/2) var(--ifm-global-spacing);position:fixed;top:1rem;z-index:calc(var(--ifm-z-index-fixed) + 1)}.skipToContent_fXgn:focus{box-shadow:var(--ifm-global-shadow-md);left:1rem}.closeButton_CVFx{line-height:0;padding:0}.content_knG7{font-size:85%;padding:5px 0;text-align:center}.content_knG7 a{color:inherit;text-decoration:underline}.announcementBar_mb4j{align-items:center;background-color:var(--ifm-color-white);border-bottom:1px solid var(--ifm-color-emphasis-100);color:var(--ifm-color-black);display:flex;height:var(--docusaurus-announcement-bar-height)}.announcementBarPlaceholder_vyr4{flex:0 0 10px}.announcementBarClose_gvF7{align-self:stretch;flex:0 0 30px}.toggle_vylO{height:2rem;width:2rem}.toggleButton_gllP{align-items:center;border-radius:50%;display:flex;height:100%;justify-content:center;transition:background var(--ifm-transition-fast);width:100%}.toggleButton_gllP:hover{background:var(--ifm-color-emphasis-200)}.toggleButtonDisabled_aARS{cursor:not-allowed}.darkNavbarColorModeToggle_X3D1:hover{background:var(--ifm-color-gray-800)}[data-theme=dark] .themedImage--dark_i4oU,[data-theme=light] .themedImage--light_HNdA{display:initial}.iconExternalLink_nPIU{margin-left:.3rem}.iconLanguage_nlXk{margin-right:5px;vertical-align:text-bottom}.navbarHideable_m1mJ{transition:transform var(--ifm-transition-fast) ease}.navbarHidden_jGov{transform:translate3d(0,calc(-100% - 2px),0)}.errorBoundaryError_a6uf{color:red;white-space:pre-wrap}.footerLogoLink_BH7S{opacity:.5;transition:opacity var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.footerLogoLink_BH7S:hover,.hash-link:focus,:hover>.hash-link{opacity:1}.mainWrapper_z2l0{display:flex;flex:1 0 auto;flex-direction:column}.docusaurus-mt-lg{margin-top:3rem}#__docusaurus{display:flex;flex-direction:column;min-height:100%}.sidebar_re4s{position:sticky;top:calc(var(--ifm-navbar-height) + 2rem)}.sidebarItemTitle_pO2u{font-size:var(--ifm-h3-font-size)}.container_mt6G,.sidebarItemList_Yudw{font-size:.9rem}.sidebarItem__DBe{margin-top:.7rem}.sidebarItemLink_mo7H{color:var(--ifm-font-color-base);display:block}.sidebarItemLinkActive_I1ZP{color:var(--ifm-color-primary)!important}.backToTopButton_sjWU{background-color:var(--ifm-color-emphasis-200);border-radius:50%;bottom:1.3rem;box-shadow:var(--ifm-global-shadow-lw);height:3rem;opacity:0;position:fixed;right:1.3rem;transform:scale(0);transition:all var(--ifm-transition-fast) var(--ifm-transition-timing-default);visibility:hidden;width:3rem;z-index:calc(var(--ifm-z-index-fixed) - 1)}.buttonGroup__atx button,.codeBlockContainer_Ckt0{background:var(--prism-background-color);color:var(--prism-color)}.backToTopButton_sjWU:after{background-color:var(--ifm-color-emphasis-1000);content:" ";display:inline-block;height:100%;-webkit-mask:var(--ifm-menu-link-sublist-icon) 50%/2rem 2rem no-repeat;mask:var(--ifm-menu-link-sublist-icon) 50%/2rem 2rem no-repeat;width:100%}.backToTopButtonShow_xfvO{opacity:1;transform:scale(1);visibility:visible}[data-theme=dark]:root{--docusaurus-collapse-button-bg:#ffffff0d;--docusaurus-collapse-button-bg-hover:#ffffff1a}.collapseSidebarButton_PEFL{display:none;margin:0}.docMainContainer_gTbr,.docPage__5DB{display:flex;width:100%}.docPage__5DB{flex:1 0}.docsWrapper_BCFX{display:flex;flex:1 0 auto}.authorCol_Hf19{flex-grow:1!important;max-width:inherit!important}.imageOnlyAuthorRow_pa_O{display:flex;flex-flow:row wrap}.imageOnlyAuthorCol_G86a{margin-left:.3rem;margin-right:.3rem}.codeBlockContainer_Ckt0{border-radius:var(--ifm-code-border-radius);box-shadow:var(--ifm-global-shadow-lw);margin-bottom:var(--ifm-leading)}.codeBlockContent_biex{border-radius:inherit;direction:ltr;position:relative}.codeBlockTitle_Ktv7{border-bottom:1px solid var(--ifm-color-emphasis-300);border-top-left-radius:inherit;border-top-right-radius:inherit;font-size:var(--ifm-code-font-size);font-weight:500;padding:.75rem var(--ifm-pre-padding)}.codeBlock_bY9V{--ifm-pre-background:var(--prism-background-color);margin:0;padding:0}.codeBlockTitle_Ktv7+.codeBlockContent_biex .codeBlock_bY9V{border-top-left-radius:0;border-top-right-radius:0}.codeBlockLines_e6Vv{float:left;font:inherit;min-width:100%;padding:var(--ifm-pre-padding)}.codeBlockLinesWithNumbering_o6Pm{display:table;padding:var(--ifm-pre-padding) 0}.buttonGroup__atx{column-gap:.2rem;display:flex;position:absolute;right:calc(var(--ifm-pre-padding)/2);top:calc(var(--ifm-pre-padding)/2)}.buttonGroup__atx button{align-items:center;border:1px solid var(--ifm-color-emphasis-300);border-radius:var(--ifm-global-radius);display:flex;line-height:0;opacity:0;padding:.4rem;transition:opacity var(--ifm-transition-fast) ease-in-out}.buttonGroup__atx button:focus-visible,.buttonGroup__atx button:hover{opacity:1!important}.theme-code-block:hover .buttonGroup__atx button{opacity:.4}.iconEdit_Z9Sw{margin-right:.3em;vertical-align:sub}:where(:root){--docusaurus-highlighted-code-line-bg:#484d5b}:where([data-theme=dark]){--docusaurus-highlighted-code-line-bg:#646464}.theme-code-block-highlighted-line{background-color:var(--docusaurus-highlighted-code-line-bg);display:block;margin:0 calc(var(--ifm-pre-padding)*-1);padding:0 var(--ifm-pre-padding)}.codeLine_lJS_{counter-increment:a;display:table-row}.codeLineNumber_Tfdd{background:var(--ifm-pre-background);display:table-cell;left:0;overflow-wrap:normal;padding:0 var(--ifm-pre-padding);position:sticky;text-align:right;width:1%}.codeLineNumber_Tfdd:before{content:counter(a);opacity:.4}.codeLineContent_feaV{padding-right:var(--ifm-pre-padding)}.tag_zVej{border:1px solid var(--docusaurus-tag-list-border);transition:border var(--ifm-transition-fast)}.tag_zVej:hover{--docusaurus-tag-list-border:var(--ifm-link-color);text-decoration:none}.tagRegular_sFm0{border-radius:var(--ifm-global-radius);font-size:90%;padding:.2rem .5rem .3rem}.tagWithCount_h2kH{align-items:center;border-left:0;display:flex;padding:0 .5rem 0 1rem;position:relative}.tagWithCount_h2kH:after,.tagWithCount_h2kH:before{border:1px solid var(--docusaurus-tag-list-border);content:"";position:absolute;top:50%;transition:inherit}.tagWithCount_h2kH:before{border-bottom:0;border-right:0;height:1.18rem;right:100%;transform:translate(50%,-50%) rotate(-45deg);width:1.18rem}.tagWithCount_h2kH:after{border-radius:50%;height:.5rem;left:0;transform:translateY(-50%);width:.5rem}.tagWithCount_h2kH span{background:var(--ifm-color-secondary);border-radius:var(--ifm-global-radius);color:var(--ifm-color-black);font-size:.7rem;line-height:1.2;margin-left:.3rem;padding:.1rem .4rem}.tag_Nnez{display:inline-block;margin:.5rem .5rem 0 1rem}.theme-code-block:hover .copyButtonCopied_obH4{opacity:1!important}.copyButtonIcons_eSgA{height:1.125rem;position:relative;width:1.125rem}.copyButtonIcon_y97N,.copyButtonSuccessIcon_LjdS{fill:currentColor;height:inherit;left:0;opacity:inherit;position:absolute;top:0;transition:all var(--ifm-transition-fast) ease;width:inherit}.copyButtonSuccessIcon_LjdS{color:#00d600;left:50%;opacity:0;top:50%;transform:translate(-50%,-50%) scale(.33)}.copyButtonCopied_obH4 .copyButtonIcon_y97N{opacity:0;transform:scale(.33)}.copyButtonCopied_obH4 .copyButtonSuccessIcon_LjdS{opacity:1;transform:translate(-50%,-50%) scale(1);transition-delay:75ms}.tags_jXut{display:inline}.tag_QGVx{display:inline-block;margin:0 .4rem .5rem 0}.lastUpdated_vwxv{font-size:smaller;font-style:italic;margin-top:.2rem}.tocCollapsibleButton_TO0P{align-items:center;display:flex;font-size:inherit;justify-content:space-between;padding:.4rem .8rem;width:100%}.tocCollapsibleButton_TO0P:after{background:var(--ifm-menu-link-sublist-icon) 50% 50%/2rem 2rem no-repeat;content:"";filter:var(--ifm-menu-link-sublist-icon-filter);height:1.25rem;transform:rotate(180deg);transition:transform var(--ifm-transition-fast);width:1.25rem}.tocCollapsibleButtonExpanded_MG3E:after,.tocCollapsibleExpanded_sAul{transform:none}.tocCollapsible_ETCw{background-color:var(--ifm-menu-color-background-active);border-radius:var(--ifm-global-radius);margin:1rem 0}.tocCollapsibleContent_vkbj>ul{border-left:none;border-top:1px solid var(--ifm-color-emphasis-300);font-size:15px;padding:.2rem 0}.tocCollapsibleContent_vkbj ul li{margin:.4rem .8rem}.tocCollapsibleContent_vkbj a{display:block}.wordWrapButtonIcon_Bwma{height:1.2rem;width:1.2rem}.details_lb9f{--docusaurus-details-summary-arrow-size:0.38rem;--docusaurus-details-transition:transform 200ms ease;--docusaurus-details-decoration-color:grey}.details_lb9f>summary{cursor:pointer;padding-left:1rem;position:relative}.details_lb9f>summary::-webkit-details-marker{display:none}.details_lb9f>summary:before{border-color:#0000 #0000 #0000 var(--docusaurus-details-decoration-color);border-style:solid;border-width:var(--docusaurus-details-summary-arrow-size);content:"";left:0;position:absolute;top:.45rem;transform:rotate(0);transform-origin:calc(var(--docusaurus-details-summary-arrow-size)/2) 50%;transition:var(--docusaurus-details-transition)}.collapsibleContent_i85q{border-top:1px solid var(--docusaurus-details-decoration-color);margin-top:1rem;padding-top:1rem}.details_b_Ee{--docusaurus-details-decoration-color:var(--ifm-alert-border-color);--docusaurus-details-transition:transform var(--ifm-transition-fast) ease;border:1px solid var(--ifm-alert-border-color);margin:0 0 var(--ifm-spacing-vertical)}.anchorWithStickyNavbar_LWe7{scroll-margin-top:calc(var(--ifm-navbar-height) + .5rem)}.anchorWithHideOnScrollNavbar_WYt5{scroll-margin-top:.5rem}.hash-link{opacity:0;padding-left:.5rem;transition:opacity var(--ifm-transition-fast);-webkit-user-select:none;user-select:none}.hash-link:before{content:"#"}.img_ev3q{height:auto}.admonition_LlT9{margin-bottom:1em}.admonitionHeading_tbUL{font:var(--ifm-heading-font-weight) var(--ifm-h5-font-size)/var(--ifm-heading-line-height) var(--ifm-heading-font-family);margin-bottom:.3rem}.admonitionHeading_tbUL code{text-transform:none}.admonitionIcon_kALy{display:inline-block;margin-right:.4em;vertical-align:middle}.admonitionIcon_kALy svg{fill:var(--ifm-alert-foreground-color);display:inline-block;height:1.6em;width:1.6em}.blogPostFooterDetailsFull_mRVl{flex-direction:column}.tableOfContents_bqdL{position:sticky;top:calc(var(--ifm-navbar-height) + 1rem)}.breadcrumbHomeIcon_YNFT{height:1.1rem;position:relative;top:1px;vertical-align:top;width:1.1rem}.breadcrumbsContainer_Z_bl{--ifm-breadcrumb-size-multiplier:0.8;margin-bottom:.8rem}@media (min-width:997px){.collapseSidebarButton_PEFL,.expandButton_m80_{background-color:var(--docusaurus-collapse-button-bg)}:root{--docusaurus-announcement-bar-height:30px}.announcementBarClose_gvF7,.announcementBarPlaceholder_vyr4{flex-basis:50px}.searchBox_ZlJk{padding:var(--ifm-navbar-item-padding-vertical) var(--ifm-navbar-item-padding-horizontal)}.collapseSidebarButton_PEFL{border:1px solid var(--ifm-toc-border-color);border-radius:0;bottom:0;display:block!important;height:40px;position:sticky}.collapseSidebarButtonIcon_kv0_{margin-top:4px;transform:rotate(180deg)}.expandButtonIcon_BlDH,[dir=rtl] .collapseSidebarButtonIcon_kv0_{transform:rotate(0)}.collapseSidebarButton_PEFL:focus,.collapseSidebarButton_PEFL:hover,.expandButton_m80_:focus,.expandButton_m80_:hover{background-color:var(--docusaurus-collapse-button-bg-hover)}.menuHtmlItem_M9Kj{padding:var(--ifm-menu-link-padding-vertical) var(--ifm-menu-link-padding-horizontal)}.menu_SIkG{flex-grow:1;padding:.5rem}@supports (scrollbar-gutter:stable){.menu_SIkG{padding:.5rem 0 .5rem .5rem;scrollbar-gutter:stable}}.menuWithAnnouncementBar_GW3s{margin-bottom:var(--docusaurus-announcement-bar-height)}.sidebar_njMd{display:flex;flex-direction:column;height:100%;padding-top:var(--ifm-navbar-height);width:var(--doc-sidebar-width)}.sidebarWithHideableNavbar_wUlq{padding-top:0}.sidebarHidden_VK0M{opacity:0;visibility:hidden}.sidebarLogo_isFc{align-items:center;color:inherit!important;display:flex!important;margin:0 var(--ifm-navbar-padding-horizontal);max-height:var(--ifm-navbar-height);min-height:var(--ifm-navbar-height);text-decoration:none!important}.sidebarLogo_isFc img{height:2rem;margin-right:.5rem}.expandButton_m80_{align-items:center;display:flex;height:100%;justify-content:center;position:absolute;right:0;top:0;transition:background-color var(--ifm-transition-fast) ease;width:100%}[dir=rtl] .expandButtonIcon_BlDH{transform:rotate(180deg)}.docSidebarContainer_b6E3{border-right:1px solid var(--ifm-toc-border-color);-webkit-clip-path:inset(0);clip-path:inset(0);display:block;margin-top:calc(var(--ifm-navbar-height)*-1);transition:width var(--ifm-transition-fast) ease;width:var(--doc-sidebar-width);will-change:width}.docSidebarContainerHidden_b3ry{cursor:pointer;width:var(--doc-sidebar-hidden-width)}.sidebarViewport_Xe31{height:100%;max-height:100vh;position:sticky;top:0}.docMainContainer_gTbr{flex-grow:1;max-width:calc(100% - var(--doc-sidebar-width))}.docMainContainerEnhanced_Uz_u{max-width:calc(100% - var(--doc-sidebar-hidden-width))}.docItemWrapperEnhanced_czyv{max-width:calc(var(--ifm-container-width) + var(--doc-sidebar-width))!important}.lastUpdated_vwxv{text-align:right}.tocMobile_ITEo{display:none}.docItemCol_VOVn{max-width:75%!important}}@media (min-width:1440px){.container{max-width:var(--ifm-container-width-xl)}}@media (max-width:996px){.col{--ifm-col-width:100%;flex-basis:var(--ifm-col-width);margin-left:0}.footer{--ifm-footer-padding-horizontal:0}.colorModeToggle_DEke,.footer__link-separator,.navbar__item,.sidebar_re4s,.tableOfContents_bqdL{display:none}.footer__col{margin-bottom:calc(var(--ifm-spacing-vertical)*3)}.footer__link-item{display:block}.hero{padding-left:0;padding-right:0}.navbar>.container,.navbar>.container-fluid{padding:0}.navbar__toggle{display:inherit}.navbar__search-input{width:9rem}.pills--block,.tabs--block{flex-direction:column}.searchBox_ZlJk{position:absolute;right:var(--ifm-navbar-padding-horizontal)}.docItemContainer_F8PC{padding:0 .3rem}}@media (max-width:576px){.markdown h1:first-child{--ifm-h1-font-size:2rem}.markdown>h2{--ifm-h2-font-size:1.5rem}.markdown>h3{--ifm-h3-font-size:1.25rem}.title_f1Hy{font-size:2rem}}@media (hover:hover){.backToTopButton_sjWU:hover{background-color:var(--ifm-color-emphasis-300)}}@media (pointer:fine){.thin-scrollbar{scrollbar-width:thin}.thin-scrollbar::-webkit-scrollbar{height:var(--ifm-scrollbar-size);width:var(--ifm-scrollbar-size)}.thin-scrollbar::-webkit-scrollbar-track{background:var(--ifm-scrollbar-track-background-color);border-radius:10px}.thin-scrollbar::-webkit-scrollbar-thumb{background:var(--ifm-scrollbar-thumb-background-color);border-radius:10px}.thin-scrollbar::-webkit-scrollbar-thumb:hover{background:var(--ifm-scrollbar-thumb-hover-background-color)}}@media (prefers-reduced-motion:reduce){:root{--ifm-transition-fast:0ms;--ifm-transition-slow:0ms}}@media print{.announcementBar_mb4j,.footer,.menu,.navbar,.pagination-nav,.table-of-contents,.tocMobile_ITEo{display:none}.tabs{page-break-inside:avoid}.codeBlockLines_e6Vv{white-space:pre-wrap}} \ No newline at end of file +@import url(https://fonts.googleapis.com/css2?family=Fira+Sans:wght@400;500;600&display=swap);@import url(https://fonts.googleapis.com/css2?family=Alfa+Slab+One&display=swap);.col,.container{padding:0 var(--ifm-spacing-horizontal);width:100%}.markdown>h2,.markdown>h3,.markdown>h4,.markdown>h5,.markdown>h6{margin-bottom:calc(var(--ifm-heading-vertical-rhythm-bottom)*var(--ifm-leading))}body,ol ol,ol ul,ul ol,ul ul{margin:0}pre,table{overflow:auto}blockquote,pre{margin:0 0 var(--ifm-spacing-vertical)}.breadcrumbs__link,.button{transition-timing-function:var(--ifm-transition-timing-default)}.button,code{vertical-align:middle}.button--outline.button--active,.button--outline:active,.button--outline:hover,:root{--ifm-button-color:var(--ifm-font-color-base-inverse)}.menu__link:hover,a{transition:color var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.navbar--dark,:root{--ifm-navbar-link-hover-color:var(--ifm-color-primary)}.menu,.navbar-sidebar{overflow-x:hidden}:root,html[data-theme=dark]{--ifm-color-emphasis-500:var(--ifm-color-gray-500)}.markdown li,article h1,body{word-wrap:break-word}.toggleButton_gllP,html{-webkit-tap-highlight-color:transparent}.clean-list,.containsTaskList_mC6p,.details_lb9f>summary,.dropdown__menu,.menu__list{list-style:none}:root{--ifm-color-scheme:light;--ifm-dark-value:10%;--ifm-darker-value:15%;--ifm-darkest-value:30%;--ifm-light-value:15%;--ifm-lighter-value:30%;--ifm-lightest-value:50%;--ifm-contrast-background-value:90%;--ifm-contrast-foreground-value:70%;--ifm-contrast-background-dark-value:70%;--ifm-contrast-foreground-dark-value:90%;--ifm-color-primary:#3578e5;--ifm-color-secondary:#ebedf0;--ifm-color-success:#00a400;--ifm-color-info:#54c7ec;--ifm-color-warning:#ffba00;--ifm-color-danger:#fa383e;--ifm-color-primary-dark:#306cce;--ifm-color-primary-darker:#2d66c3;--ifm-color-primary-darkest:#2554a0;--ifm-color-primary-light:#538ce9;--ifm-color-primary-lighter:#72a1ed;--ifm-color-primary-lightest:#9abcf2;--ifm-color-primary-contrast-background:#ebf2fc;--ifm-color-primary-contrast-foreground:#102445;--ifm-color-secondary-dark:#d4d5d8;--ifm-color-secondary-darker:#c8c9cc;--ifm-color-secondary-darkest:#a4a6a8;--ifm-color-secondary-light:#eef0f2;--ifm-color-secondary-lighter:#f1f2f5;--ifm-color-secondary-lightest:#f5f6f8;--ifm-color-secondary-contrast-background:#fdfdfe;--ifm-color-secondary-contrast-foreground:#474748;--ifm-color-success-dark:#009400;--ifm-color-success-darker:#008b00;--ifm-color-success-darkest:#007300;--ifm-color-success-light:#26b226;--ifm-color-success-lighter:#4dbf4d;--ifm-color-success-lightest:#80d280;--ifm-color-success-contrast-background:#e6f6e6;--ifm-color-success-contrast-foreground:#003100;--ifm-color-info-dark:#4cb3d4;--ifm-color-info-darker:#47a9c9;--ifm-color-info-darkest:#3b8ba5;--ifm-color-info-light:#6ecfef;--ifm-color-info-lighter:#87d8f2;--ifm-color-info-lightest:#aae3f6;--ifm-color-info-contrast-background:#eef9fd;--ifm-color-info-contrast-foreground:#193c47;--ifm-color-warning-dark:#e6a700;--ifm-color-warning-darker:#d99e00;--ifm-color-warning-darkest:#b38200;--ifm-color-warning-light:#ffc426;--ifm-color-warning-lighter:#ffcf4d;--ifm-color-warning-lightest:#ffdd80;--ifm-color-warning-contrast-background:#fff8e6;--ifm-color-warning-contrast-foreground:#4d3800;--ifm-color-danger-dark:#e13238;--ifm-color-danger-darker:#d53035;--ifm-color-danger-darkest:#af272b;--ifm-color-danger-light:#fb565b;--ifm-color-danger-lighter:#fb7478;--ifm-color-danger-lightest:#fd9c9f;--ifm-color-danger-contrast-background:#ffebec;--ifm-color-danger-contrast-foreground:#4b1113;--ifm-color-white:#fff;--ifm-color-black:#000;--ifm-color-gray-0:var(--ifm-color-white);--ifm-color-gray-100:#f5f6f7;--ifm-color-gray-200:#ebedf0;--ifm-color-gray-300:#dadde1;--ifm-color-gray-400:#ccd0d5;--ifm-color-gray-500:#bec3c9;--ifm-color-gray-600:#8d949e;--ifm-color-gray-700:#606770;--ifm-color-gray-800:#444950;--ifm-color-gray-900:#1c1e21;--ifm-color-gray-1000:var(--ifm-color-black);--ifm-color-emphasis-0:var(--ifm-color-gray-0);--ifm-color-emphasis-100:var(--ifm-color-gray-100);--ifm-color-emphasis-200:var(--ifm-color-gray-200);--ifm-color-emphasis-300:var(--ifm-color-gray-300);--ifm-color-emphasis-400:var(--ifm-color-gray-400);--ifm-color-emphasis-600:var(--ifm-color-gray-600);--ifm-color-emphasis-700:var(--ifm-color-gray-700);--ifm-color-emphasis-800:var(--ifm-color-gray-800);--ifm-color-emphasis-900:var(--ifm-color-gray-900);--ifm-color-emphasis-1000:var(--ifm-color-gray-1000);--ifm-color-content:var(--ifm-color-emphasis-900);--ifm-color-content-inverse:var(--ifm-color-emphasis-0);--ifm-color-content-secondary:#525860;--ifm-background-color:#0000;--ifm-background-surface-color:var(--ifm-color-content-inverse);--ifm-global-border-width:1px;--ifm-global-radius:0.4rem;--ifm-hover-overlay:#0000000d;--ifm-font-color-base:var(--ifm-color-content);--ifm-font-color-base-inverse:var(--ifm-color-content-inverse);--ifm-font-color-secondary:var(--ifm-color-content-secondary);--ifm-font-family-base:system-ui,-apple-system,Segoe UI,Roboto,Ubuntu,Cantarell,Noto Sans,sans-serif,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";--ifm-font-family-monospace:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--ifm-font-size-base:100%;--ifm-font-weight-light:300;--ifm-font-weight-normal:400;--ifm-font-weight-semibold:500;--ifm-font-weight-bold:700;--ifm-font-weight-base:var(--ifm-font-weight-normal);--ifm-line-height-base:1.65;--ifm-global-spacing:1rem;--ifm-spacing-vertical:var(--ifm-global-spacing);--ifm-spacing-horizontal:var(--ifm-global-spacing);--ifm-transition-fast:200ms;--ifm-transition-slow:400ms;--ifm-transition-timing-default:cubic-bezier(0.08,0.52,0.52,1);--ifm-global-shadow-lw:0 1px 2px 0 #0000001a;--ifm-global-shadow-md:0 5px 40px #0003;--ifm-global-shadow-tl:0 12px 28px 0 #0003,0 2px 4px 0 #0000001a;--ifm-z-index-dropdown:100;--ifm-z-index-fixed:200;--ifm-z-index-overlay:400;--ifm-container-width:1140px;--ifm-container-width-xl:1320px;--ifm-code-background:#f6f7f8;--ifm-code-border-radius:var(--ifm-global-radius);--ifm-code-font-size:90%;--ifm-code-padding-horizontal:0.1rem;--ifm-code-padding-vertical:0.1rem;--ifm-pre-background:var(--ifm-code-background);--ifm-pre-border-radius:var(--ifm-code-border-radius);--ifm-pre-color:inherit;--ifm-pre-line-height:1.45;--ifm-pre-padding:1rem;--ifm-heading-color:inherit;--ifm-heading-margin-top:0;--ifm-heading-margin-bottom:var(--ifm-spacing-vertical);--ifm-heading-font-family:var(--ifm-font-family-base);--ifm-heading-font-weight:var(--ifm-font-weight-bold);--ifm-heading-line-height:1.25;--ifm-h1-font-size:2rem;--ifm-h2-font-size:1.5rem;--ifm-h3-font-size:1.25rem;--ifm-h4-font-size:1rem;--ifm-h5-font-size:0.875rem;--ifm-h6-font-size:0.85rem;--ifm-image-alignment-padding:1.25rem;--ifm-leading-desktop:1.25;--ifm-leading:calc(var(--ifm-leading-desktop)*1rem);--ifm-list-left-padding:2rem;--ifm-list-margin:1rem;--ifm-list-item-margin:0.25rem;--ifm-list-paragraph-margin:1rem;--ifm-table-cell-padding:0.75rem;--ifm-table-background:#0000;--ifm-table-stripe-background:#00000008;--ifm-table-border-width:1px;--ifm-table-border-color:var(--ifm-color-emphasis-300);--ifm-table-head-background:inherit;--ifm-table-head-color:inherit;--ifm-table-head-font-weight:var(--ifm-font-weight-bold);--ifm-table-cell-color:inherit;--ifm-link-color:var(--ifm-color-primary);--ifm-link-decoration:none;--ifm-link-hover-color:var(--ifm-link-color);--ifm-link-hover-decoration:underline;--ifm-paragraph-margin-bottom:var(--ifm-leading);--ifm-blockquote-font-size:var(--ifm-font-size-base);--ifm-blockquote-border-left-width:2px;--ifm-blockquote-padding-horizontal:var(--ifm-spacing-horizontal);--ifm-blockquote-padding-vertical:0;--ifm-blockquote-shadow:none;--ifm-blockquote-color:var(--ifm-color-emphasis-800);--ifm-blockquote-border-color:var(--ifm-color-emphasis-300);--ifm-hr-background-color:var(--ifm-color-emphasis-500);--ifm-hr-height:1px;--ifm-hr-margin-vertical:1.5rem;--ifm-scrollbar-size:7px;--ifm-scrollbar-track-background-color:#f1f1f1;--ifm-scrollbar-thumb-background-color:silver;--ifm-scrollbar-thumb-hover-background-color:#a7a7a7;--ifm-alert-background-color:inherit;--ifm-alert-border-color:inherit;--ifm-alert-border-radius:var(--ifm-global-radius);--ifm-alert-border-width:0px;--ifm-alert-border-left-width:5px;--ifm-alert-color:var(--ifm-font-color-base);--ifm-alert-padding-horizontal:var(--ifm-spacing-horizontal);--ifm-alert-padding-vertical:var(--ifm-spacing-vertical);--ifm-alert-shadow:var(--ifm-global-shadow-lw);--ifm-avatar-intro-margin:1rem;--ifm-avatar-intro-alignment:inherit;--ifm-avatar-photo-size:3rem;--ifm-badge-background-color:inherit;--ifm-badge-border-color:inherit;--ifm-badge-border-radius:var(--ifm-global-radius);--ifm-badge-border-width:var(--ifm-global-border-width);--ifm-badge-color:var(--ifm-color-white);--ifm-badge-padding-horizontal:calc(var(--ifm-spacing-horizontal)*0.5);--ifm-badge-padding-vertical:calc(var(--ifm-spacing-vertical)*0.25);--ifm-breadcrumb-border-radius:1.5rem;--ifm-breadcrumb-spacing:0.5rem;--ifm-breadcrumb-color-active:var(--ifm-color-primary);--ifm-breadcrumb-item-background-active:var(--ifm-hover-overlay);--ifm-breadcrumb-padding-horizontal:0.8rem;--ifm-breadcrumb-padding-vertical:0.4rem;--ifm-breadcrumb-size-multiplier:1;--ifm-breadcrumb-separator:url('data:image/svg+xml;utf8,');--ifm-breadcrumb-separator-filter:none;--ifm-breadcrumb-separator-size:0.5rem;--ifm-breadcrumb-separator-size-multiplier:1.25;--ifm-button-background-color:inherit;--ifm-button-border-color:var(--ifm-button-background-color);--ifm-button-border-width:var(--ifm-global-border-width);--ifm-button-font-weight:var(--ifm-font-weight-bold);--ifm-button-padding-horizontal:1.5rem;--ifm-button-padding-vertical:0.375rem;--ifm-button-size-multiplier:1;--ifm-button-transition-duration:var(--ifm-transition-fast);--ifm-button-border-radius:calc(var(--ifm-global-radius)*var(--ifm-button-size-multiplier));--ifm-button-group-spacing:2px;--ifm-card-background-color:var(--ifm-background-surface-color);--ifm-card-border-radius:calc(var(--ifm-global-radius)*2);--ifm-card-horizontal-spacing:var(--ifm-global-spacing);--ifm-card-vertical-spacing:var(--ifm-global-spacing);--ifm-toc-border-color:var(--ifm-color-emphasis-300);--ifm-toc-link-color:var(--ifm-color-content-secondary);--ifm-toc-padding-vertical:0.5rem;--ifm-toc-padding-horizontal:0.5rem;--ifm-dropdown-background-color:var(--ifm-background-surface-color);--ifm-dropdown-font-weight:var(--ifm-font-weight-semibold);--ifm-dropdown-link-color:var(--ifm-font-color-base);--ifm-dropdown-hover-background-color:var(--ifm-hover-overlay);--ifm-footer-background-color:var(--ifm-color-emphasis-100);--ifm-footer-color:inherit;--ifm-footer-link-color:var(--ifm-color-emphasis-700);--ifm-footer-link-hover-color:var(--ifm-color-primary);--ifm-footer-link-horizontal-spacing:0.5rem;--ifm-footer-padding-horizontal:calc(var(--ifm-spacing-horizontal)*2);--ifm-footer-padding-vertical:calc(var(--ifm-spacing-vertical)*2);--ifm-footer-title-color:inherit;--ifm-footer-logo-max-width:min(30rem,90vw);--ifm-hero-background-color:var(--ifm-background-surface-color);--ifm-hero-text-color:var(--ifm-color-emphasis-800);--ifm-menu-color:var(--ifm-color-emphasis-700);--ifm-menu-color-active:var(--ifm-color-primary);--ifm-menu-color-background-active:var(--ifm-hover-overlay);--ifm-menu-color-background-hover:var(--ifm-hover-overlay);--ifm-menu-link-padding-horizontal:0.75rem;--ifm-menu-link-padding-vertical:0.375rem;--ifm-menu-link-sublist-icon:url('data:image/svg+xml;utf8,');--ifm-menu-link-sublist-icon-filter:none;--ifm-navbar-background-color:var(--ifm-background-surface-color);--ifm-navbar-height:3.75rem;--ifm-navbar-item-padding-horizontal:0.75rem;--ifm-navbar-item-padding-vertical:0.25rem;--ifm-navbar-link-color:var(--ifm-font-color-base);--ifm-navbar-link-active-color:var(--ifm-link-color);--ifm-navbar-padding-horizontal:var(--ifm-spacing-horizontal);--ifm-navbar-padding-vertical:calc(var(--ifm-spacing-vertical)*0.5);--ifm-navbar-shadow:var(--ifm-global-shadow-lw);--ifm-navbar-search-input-background-color:var(--ifm-color-emphasis-200);--ifm-navbar-search-input-color:var(--ifm-color-emphasis-800);--ifm-navbar-search-input-placeholder-color:var(--ifm-color-emphasis-500);--ifm-navbar-search-input-icon:url('data:image/svg+xml;utf8,');--ifm-navbar-sidebar-width:83vw;--ifm-pagination-border-radius:var(--ifm-global-radius);--ifm-pagination-color-active:var(--ifm-color-primary);--ifm-pagination-font-size:1rem;--ifm-pagination-item-active-background:var(--ifm-hover-overlay);--ifm-pagination-page-spacing:0.2em;--ifm-pagination-padding-horizontal:calc(var(--ifm-spacing-horizontal)*1);--ifm-pagination-padding-vertical:calc(var(--ifm-spacing-vertical)*0.25);--ifm-pagination-nav-border-radius:var(--ifm-global-radius);--ifm-pagination-nav-color-hover:var(--ifm-color-primary);--ifm-pills-color-active:var(--ifm-color-primary);--ifm-pills-color-background-active:var(--ifm-hover-overlay);--ifm-pills-spacing:0.125rem;--ifm-tabs-color:var(--ifm-font-color-secondary);--ifm-tabs-color-active:var(--ifm-color-primary);--ifm-tabs-color-active-border:var(--ifm-tabs-color-active);--ifm-tabs-padding-horizontal:1rem;--ifm-tabs-padding-vertical:1rem;--docusaurus-progress-bar-color:var(--ifm-color-primary);--ifm-color-primary:#0077be;--ifm-color-primary-dark:#005fa3;--ifm-color-primary-darker:#004c87;--ifm-color-primary-darkest:#003c6b;--ifm-color-primary-light:#0093e8;--ifm-color-primary-lighter:#00a3ff;--ifm-color-primary-lightest:#00baff;--ifm-code-font-size:95%;--docusaurus-highlighted-code-line-bg:#0000001a;--docusaurus-announcement-bar-height:auto;--docusaurus-collapse-button-bg:#0000;--docusaurus-collapse-button-bg-hover:#0000001a;--doc-sidebar-width:300px;--doc-sidebar-hidden-width:30px;--docusaurus-tag-list-border:var(--ifm-color-emphasis-300)}.badge--danger,.badge--info,.badge--primary,.badge--secondary,.badge--success,.badge--warning{--ifm-badge-border-color:var(--ifm-badge-background-color)}.button--link,.button--outline{--ifm-button-background-color:#0000}*{box-sizing:border-box}html{-webkit-font-smoothing:antialiased;-webkit-text-size-adjust:100%;text-size-adjust:100%;background-color:var(--ifm-background-color);color:var(--ifm-font-color-base);color-scheme:var(--ifm-color-scheme);font:var(--ifm-font-size-base)/var(--ifm-line-height-base) var(--ifm-font-family-base);text-rendering:optimizelegibility}iframe{border:0;color-scheme:auto}.container{margin:0 auto;max-width:var(--ifm-container-width)}.container--fluid{max-width:inherit}.row{display:flex;flex-wrap:wrap;margin:0 calc(var(--ifm-spacing-horizontal)*-1)}.margin-bottom--none,.margin-vert--none,.markdown>:last-child{margin-bottom:0!important}.margin-top--none,.margin-vert--none{margin-top:0!important}.row--no-gutters{margin-left:0;margin-right:0}.margin-horiz--none,.margin-right--none{margin-right:0!important}.row--no-gutters>.col{padding-left:0;padding-right:0}.row--align-top{align-items:flex-start}.row--align-bottom{align-items:flex-end}.menuExternalLink_NmtK,.row--align-center{align-items:center}.row--align-stretch{align-items:stretch}.row--align-baseline{align-items:baseline}.col{--ifm-col-width:100%;flex:1 0;margin-left:0;max-width:var(--ifm-col-width)}.padding-bottom--none,.padding-vert--none{padding-bottom:0!important}.padding-top--none,.padding-vert--none{padding-top:0!important}.padding-horiz--none,.padding-left--none{padding-left:0!important}.padding-horiz--none,.padding-right--none{padding-right:0!important}.col[class*=col--]{flex:0 0 var(--ifm-col-width)}.col--1{--ifm-col-width:8.33333%}.col--offset-1{margin-left:8.33333%}.col--2{--ifm-col-width:16.66667%}.col--offset-2{margin-left:16.66667%}.col--3{--ifm-col-width:25%}.col--offset-3{margin-left:25%}.col--4{--ifm-col-width:33.33333%}.col--offset-4{margin-left:33.33333%}.col--5{--ifm-col-width:41.66667%}.col--offset-5{margin-left:41.66667%}.col--6{--ifm-col-width:50%}.col--offset-6{margin-left:50%}.col--7{--ifm-col-width:58.33333%}.col--offset-7{margin-left:58.33333%}.col--8{--ifm-col-width:66.66667%}.col--offset-8{margin-left:66.66667%}.col--9{--ifm-col-width:75%}.col--offset-9{margin-left:75%}.col--10{--ifm-col-width:83.33333%}.col--offset-10{margin-left:83.33333%}.col--11{--ifm-col-width:91.66667%}.col--offset-11{margin-left:91.66667%}.col--12{--ifm-col-width:100%}.col--offset-12{margin-left:100%}.margin-horiz--none,.margin-left--none{margin-left:0!important}.margin--none{margin:0!important}.margin-bottom--xs,.margin-vert--xs{margin-bottom:.25rem!important}.margin-top--xs,.margin-vert--xs{margin-top:.25rem!important}.margin-horiz--xs,.margin-left--xs{margin-left:.25rem!important}.margin-horiz--xs,.margin-right--xs{margin-right:.25rem!important}.margin--xs{margin:.25rem!important}.margin-bottom--sm,.margin-vert--sm{margin-bottom:.5rem!important}.margin-top--sm,.margin-vert--sm{margin-top:.5rem!important}.margin-horiz--sm,.margin-left--sm{margin-left:.5rem!important}.margin-horiz--sm,.margin-right--sm{margin-right:.5rem!important}.margin--sm{margin:.5rem!important}.margin-bottom--md,.margin-vert--md{margin-bottom:1rem!important}.margin-top--md,.margin-vert--md{margin-top:1rem!important}.margin-horiz--md,.margin-left--md{margin-left:1rem!important}.margin-horiz--md,.margin-right--md{margin-right:1rem!important}.margin--md{margin:1rem!important}.margin-bottom--lg,.margin-vert--lg{margin-bottom:2rem!important}.margin-top--lg,.margin-vert--lg{margin-top:2rem!important}.margin-horiz--lg,.margin-left--lg{margin-left:2rem!important}.margin-horiz--lg,.margin-right--lg{margin-right:2rem!important}.margin--lg{margin:2rem!important}.margin-bottom--xl,.margin-vert--xl{margin-bottom:5rem!important}.margin-top--xl,.margin-vert--xl{margin-top:5rem!important}.margin-horiz--xl,.margin-left--xl{margin-left:5rem!important}.margin-horiz--xl,.margin-right--xl{margin-right:5rem!important}.margin--xl{margin:5rem!important}.padding--none{padding:0!important}.padding-bottom--xs,.padding-vert--xs{padding-bottom:.25rem!important}.padding-top--xs,.padding-vert--xs{padding-top:.25rem!important}.padding-horiz--xs,.padding-left--xs{padding-left:.25rem!important}.padding-horiz--xs,.padding-right--xs{padding-right:.25rem!important}.padding--xs{padding:.25rem!important}.padding-bottom--sm,.padding-vert--sm{padding-bottom:.5rem!important}.padding-top--sm,.padding-vert--sm{padding-top:.5rem!important}.padding-horiz--sm,.padding-left--sm{padding-left:.5rem!important}.padding-horiz--sm,.padding-right--sm{padding-right:.5rem!important}.padding--sm{padding:.5rem!important}.padding-bottom--md,.padding-vert--md{padding-bottom:1rem!important}.padding-top--md,.padding-vert--md{padding-top:1rem!important}.padding-horiz--md,.padding-left--md{padding-left:1rem!important}.padding-horiz--md,.padding-right--md{padding-right:1rem!important}.padding--md{padding:1rem!important}.padding-bottom--lg,.padding-vert--lg{padding-bottom:2rem!important}.padding-top--lg,.padding-vert--lg{padding-top:2rem!important}.padding-horiz--lg,.padding-left--lg{padding-left:2rem!important}.padding-horiz--lg,.padding-right--lg{padding-right:2rem!important}.padding--lg{padding:2rem!important}.padding-bottom--xl,.padding-vert--xl{padding-bottom:5rem!important}.padding-top--xl,.padding-vert--xl{padding-top:5rem!important}.padding-horiz--xl,.padding-left--xl{padding-left:5rem!important}.padding-horiz--xl,.padding-right--xl{padding-right:5rem!important}.padding--xl{padding:5rem!important}code{background-color:var(--ifm-code-background);border:.1rem solid #0000001a;border-radius:var(--ifm-code-border-radius);font-family:var(--ifm-font-family-monospace);font-size:var(--ifm-code-font-size);padding:var(--ifm-code-padding-vertical) var(--ifm-code-padding-horizontal)}a code{color:inherit}pre{background-color:var(--ifm-pre-background);border-radius:var(--ifm-pre-border-radius);color:var(--ifm-pre-color);font:var(--ifm-code-font-size)/var(--ifm-pre-line-height) var(--ifm-font-family-monospace);padding:var(--ifm-pre-padding)}pre code{background-color:initial;border:none;font-size:100%;line-height:inherit;padding:0}kbd{background-color:var(--ifm-color-emphasis-0);border:1px solid var(--ifm-color-emphasis-400);border-radius:.2rem;box-shadow:inset 0 -1px 0 var(--ifm-color-emphasis-400);color:var(--ifm-color-emphasis-800);font:80% var(--ifm-font-family-monospace);padding:.15rem .3rem}h1,h2,h3,h4,h5,h6{color:var(--ifm-heading-color);font-family:var(--ifm-heading-font-family);font-weight:var(--ifm-heading-font-weight);line-height:var(--ifm-heading-line-height);margin:var(--ifm-heading-margin-top) 0 var(--ifm-heading-margin-bottom) 0}h1{font-size:var(--ifm-h1-font-size)}h2{font-size:var(--ifm-h2-font-size)}h3{font-size:var(--ifm-h3-font-size)}h4{font-size:var(--ifm-h4-font-size)}h5{font-size:var(--ifm-h5-font-size)}h6{font-size:var(--ifm-h6-font-size)}img{max-width:100%}img[align=right]{padding-left:var(--image-alignment-padding)}img[align=left]{padding-right:var(--image-alignment-padding)}.markdown{--ifm-h1-vertical-rhythm-top:3;--ifm-h2-vertical-rhythm-top:2;--ifm-h3-vertical-rhythm-top:1.5;--ifm-heading-vertical-rhythm-top:1.25;--ifm-h1-vertical-rhythm-bottom:1.25;--ifm-heading-vertical-rhythm-bottom:1}.markdown:after,.markdown:before{content:"";display:table}.markdown:after{clear:both}.markdown h1:first-child{--ifm-h1-font-size:3rem;margin-bottom:calc(var(--ifm-h1-vertical-rhythm-bottom)*var(--ifm-leading))}.markdown>h2{--ifm-h2-font-size:2rem;margin-top:calc(var(--ifm-h2-vertical-rhythm-top)*var(--ifm-leading))}.markdown>h3{--ifm-h3-font-size:1.5rem;margin-top:calc(var(--ifm-h3-vertical-rhythm-top)*var(--ifm-leading))}.markdown>h4,.markdown>h5,.markdown>h6{margin-top:calc(var(--ifm-heading-vertical-rhythm-top)*var(--ifm-leading))}.markdown>p,.markdown>pre,.markdown>ul{margin-bottom:var(--ifm-leading)}.markdown li>p{margin-top:var(--ifm-list-paragraph-margin)}.markdown li+li{margin-top:var(--ifm-list-item-margin)}ol,ul{margin:0 0 var(--ifm-list-margin);padding-left:var(--ifm-list-left-padding)}ol ol,ul ol{list-style-type:lower-roman}ol ol ol,ol ul ol,ul ol ol,ul ul ol{list-style-type:lower-alpha}table{border-collapse:collapse;display:block;margin-bottom:var(--ifm-spacing-vertical)}table thead tr{border-bottom:2px solid var(--ifm-table-border-color)}table thead,table tr:nth-child(2n){background-color:var(--ifm-table-stripe-background)}table tr{background-color:var(--ifm-table-background);border-top:var(--ifm-table-border-width) solid var(--ifm-table-border-color)}table td,table th{border:var(--ifm-table-border-width) solid var(--ifm-table-border-color);padding:var(--ifm-table-cell-padding)}table th{background-color:var(--ifm-table-head-background);color:var(--ifm-table-head-color);font-weight:var(--ifm-table-head-font-weight)}table td{color:var(--ifm-table-cell-color)}strong{font-weight:var(--ifm-font-weight-bold)}a{color:var(--ifm-link-color);text-decoration:var(--ifm-link-decoration)}a:hover{color:var(--ifm-link-hover-color);text-decoration:var(--ifm-link-hover-decoration)}.button:hover,.text--no-decoration,.text--no-decoration:hover,a:not([href]){text-decoration:none}p{margin:0 0 var(--ifm-paragraph-margin-bottom)}blockquote{border-left:var(--ifm-blockquote-border-left-width) solid var(--ifm-blockquote-border-color);box-shadow:var(--ifm-blockquote-shadow);color:var(--ifm-blockquote-color);font-size:var(--ifm-blockquote-font-size);padding:var(--ifm-blockquote-padding-vertical) var(--ifm-blockquote-padding-horizontal)}blockquote>:first-child{margin-top:0}blockquote>:last-child{margin-bottom:0}hr{background-color:var(--ifm-hr-background-color);border:0;height:var(--ifm-hr-height);margin:var(--ifm-hr-margin-vertical) 0}.shadow--lw{box-shadow:var(--ifm-global-shadow-lw)!important}.shadow--md{box-shadow:var(--ifm-global-shadow-md)!important}.shadow--tl{box-shadow:var(--ifm-global-shadow-tl)!important}.text--primary,.wordWrapButtonEnabled_EoeP .wordWrapButtonIcon_Bwma{color:var(--ifm-color-primary)}.text--secondary{color:var(--ifm-color-secondary)}.text--success{color:var(--ifm-color-success)}.text--info{color:var(--ifm-color-info)}.text--warning{color:var(--ifm-color-warning)}.text--danger{color:var(--ifm-color-danger)}.text--center{text-align:center}.text--left{text-align:left}.text--justify{text-align:justify}.text--right{text-align:right}.text--capitalize{text-transform:capitalize}.text--lowercase{text-transform:lowercase}.admonitionHeading_tbUL,.alert__heading,.text--uppercase{text-transform:uppercase}.text--light{font-weight:var(--ifm-font-weight-light)}.text--normal{font-weight:var(--ifm-font-weight-normal)}.text--semibold{font-weight:var(--ifm-font-weight-semibold)}.text--bold{font-weight:var(--ifm-font-weight-bold)}.text--italic{font-style:italic}.text--truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.text--break{word-wrap:break-word!important;word-break:break-word!important}.clean-btn{background:none;border:none;color:inherit;cursor:pointer;font-family:inherit;padding:0}.alert,.alert .close{color:var(--ifm-alert-foreground-color)}.clean-list{padding-left:0}.alert--primary{--ifm-alert-background-color:var(--ifm-color-primary-contrast-background);--ifm-alert-background-color-highlight:#3578e526;--ifm-alert-foreground-color:var(--ifm-color-primary-contrast-foreground);--ifm-alert-border-color:var(--ifm-color-primary-dark)}.alert--secondary{--ifm-alert-background-color:var(--ifm-color-secondary-contrast-background);--ifm-alert-background-color-highlight:#ebedf026;--ifm-alert-foreground-color:var(--ifm-color-secondary-contrast-foreground);--ifm-alert-border-color:var(--ifm-color-secondary-dark)}.alert--success{--ifm-alert-background-color:var(--ifm-color-success-contrast-background);--ifm-alert-background-color-highlight:#00a40026;--ifm-alert-foreground-color:var(--ifm-color-success-contrast-foreground);--ifm-alert-border-color:var(--ifm-color-success-dark)}.alert--info{--ifm-alert-background-color:var(--ifm-color-info-contrast-background);--ifm-alert-background-color-highlight:#54c7ec26;--ifm-alert-foreground-color:var(--ifm-color-info-contrast-foreground);--ifm-alert-border-color:var(--ifm-color-info-dark)}.alert--warning{--ifm-alert-background-color:var(--ifm-color-warning-contrast-background);--ifm-alert-background-color-highlight:#ffba0026;--ifm-alert-foreground-color:var(--ifm-color-warning-contrast-foreground);--ifm-alert-border-color:var(--ifm-color-warning-dark)}.alert--danger{--ifm-alert-background-color:var(--ifm-color-danger-contrast-background);--ifm-alert-background-color-highlight:#fa383e26;--ifm-alert-foreground-color:var(--ifm-color-danger-contrast-foreground);--ifm-alert-border-color:var(--ifm-color-danger-dark)}.alert{--ifm-code-background:var(--ifm-alert-background-color-highlight);--ifm-link-color:var(--ifm-alert-foreground-color);--ifm-link-hover-color:var(--ifm-alert-foreground-color);--ifm-link-decoration:underline;--ifm-tabs-color:var(--ifm-alert-foreground-color);--ifm-tabs-color-active:var(--ifm-alert-foreground-color);--ifm-tabs-color-active-border:var(--ifm-alert-border-color);background-color:var(--ifm-alert-background-color);border:var(--ifm-alert-border-width) solid var(--ifm-alert-border-color);border-left-width:var(--ifm-alert-border-left-width);border-radius:var(--ifm-alert-border-radius);box-shadow:var(--ifm-alert-shadow);padding:var(--ifm-alert-padding-vertical) var(--ifm-alert-padding-horizontal)}.alert__heading{align-items:center;display:flex;font:700 var(--ifm-h5-font-size)/var(--ifm-heading-line-height) var(--ifm-heading-font-family);margin-bottom:.5rem}.alert__icon{display:inline-flex;margin-right:.4em}.alert__icon svg{fill:var(--ifm-alert-foreground-color);stroke:var(--ifm-alert-foreground-color);stroke-width:0}.alert .close{margin:calc(var(--ifm-alert-padding-vertical)*-1) calc(var(--ifm-alert-padding-horizontal)*-1) 0 0;opacity:.75}.alert .close:focus,.alert .close:hover{opacity:1}.alert a{text-decoration-color:var(--ifm-alert-border-color)}.alert a:hover{text-decoration-thickness:2px}.avatar{column-gap:var(--ifm-avatar-intro-margin);display:flex}.avatar__photo{border-radius:50%;display:block;height:var(--ifm-avatar-photo-size);overflow:hidden;width:var(--ifm-avatar-photo-size)}.card--full-height,.navbar__logo img,body,html{height:100%}.avatar__photo--sm{--ifm-avatar-photo-size:2rem}.avatar__photo--lg{--ifm-avatar-photo-size:4rem}.avatar__photo--xl{--ifm-avatar-photo-size:6rem}.avatar__intro{display:flex;flex:1 1;flex-direction:column;justify-content:center;text-align:var(--ifm-avatar-intro-alignment)}.badge,.breadcrumbs__item,.breadcrumbs__link,.button,.dropdown>.navbar__link:after{display:inline-block}.avatar__name{font:700 var(--ifm-h4-font-size)/var(--ifm-heading-line-height) var(--ifm-font-family-base)}.avatar__subtitle{margin-top:.25rem}.avatar--vertical{--ifm-avatar-intro-alignment:center;--ifm-avatar-intro-margin:0.5rem;align-items:center;flex-direction:column}.badge{background-color:var(--ifm-badge-background-color);border:var(--ifm-badge-border-width) solid var(--ifm-badge-border-color);border-radius:var(--ifm-badge-border-radius);color:var(--ifm-badge-color);font-size:75%;font-weight:var(--ifm-font-weight-bold);line-height:1;padding:var(--ifm-badge-padding-vertical) var(--ifm-badge-padding-horizontal)}.badge--primary{--ifm-badge-background-color:var(--ifm-color-primary)}.badge--secondary{--ifm-badge-background-color:var(--ifm-color-secondary);color:var(--ifm-color-black)}.breadcrumbs__link,.button.button--secondary.button--outline:not(.button--active):not(:hover){color:var(--ifm-font-color-base)}.badge--success{--ifm-badge-background-color:var(--ifm-color-success)}.badge--info{--ifm-badge-background-color:var(--ifm-color-info)}.badge--warning{--ifm-badge-background-color:var(--ifm-color-warning)}.badge--danger{--ifm-badge-background-color:var(--ifm-color-danger)}.breadcrumbs{margin-bottom:0;padding-left:0}.breadcrumbs__item:not(:last-child):after{background:var(--ifm-breadcrumb-separator) center;content:" ";display:inline-block;filter:var(--ifm-breadcrumb-separator-filter);height:calc(var(--ifm-breadcrumb-separator-size)*var(--ifm-breadcrumb-size-multiplier)*var(--ifm-breadcrumb-separator-size-multiplier));margin:0 var(--ifm-breadcrumb-spacing);opacity:.5;width:calc(var(--ifm-breadcrumb-separator-size)*var(--ifm-breadcrumb-size-multiplier)*var(--ifm-breadcrumb-separator-size-multiplier))}.breadcrumbs__item--active .breadcrumbs__link{background:var(--ifm-breadcrumb-item-background-active);color:var(--ifm-breadcrumb-color-active)}.breadcrumbs__link{border-radius:var(--ifm-breadcrumb-border-radius);font-size:calc(1rem*var(--ifm-breadcrumb-size-multiplier));padding:calc(var(--ifm-breadcrumb-padding-vertical)*var(--ifm-breadcrumb-size-multiplier)) calc(var(--ifm-breadcrumb-padding-horizontal)*var(--ifm-breadcrumb-size-multiplier));transition-duration:var(--ifm-transition-fast);transition-property:background,color}.breadcrumbs__link:any-link:hover,.breadcrumbs__link:link:hover,.breadcrumbs__link:visited:hover,area[href].breadcrumbs__link:hover{background:var(--ifm-breadcrumb-item-background-active);text-decoration:none}.breadcrumbs--sm{--ifm-breadcrumb-size-multiplier:0.8}.breadcrumbs--lg{--ifm-breadcrumb-size-multiplier:1.2}.button{background-color:var(--ifm-button-background-color);border:var(--ifm-button-border-width) solid var(--ifm-button-border-color);border-radius:var(--ifm-button-border-radius);cursor:pointer;font-size:calc(.875rem*var(--ifm-button-size-multiplier));font-weight:var(--ifm-button-font-weight);line-height:1.5;padding:calc(var(--ifm-button-padding-vertical)*var(--ifm-button-size-multiplier)) calc(var(--ifm-button-padding-horizontal)*var(--ifm-button-size-multiplier));text-align:center;transition-duration:var(--ifm-button-transition-duration);transition-property:color,background,border-color;-webkit-user-select:none;user-select:none;white-space:nowrap}.button,.button:hover{color:var(--ifm-button-color)}.button--outline{--ifm-button-color:var(--ifm-button-border-color)}.button--outline:hover{--ifm-button-background-color:var(--ifm-button-border-color)}.button--link{--ifm-button-border-color:#0000;color:var(--ifm-link-color);text-decoration:var(--ifm-link-decoration)}.button--link.button--active,.button--link:active,.button--link:hover{color:var(--ifm-link-hover-color);text-decoration:var(--ifm-link-hover-decoration)}.button.disabled,.button:disabled,.button[disabled]{opacity:.65;pointer-events:none}.button--sm{--ifm-button-size-multiplier:0.8}.button--lg{--ifm-button-size-multiplier:1.35}.button--block{display:block;width:100%}.button.button--secondary{color:var(--ifm-color-gray-900)}:where(.button--primary){--ifm-button-background-color:var(--ifm-color-primary);--ifm-button-border-color:var(--ifm-color-primary)}:where(.button--primary):not(.button--outline):hover{--ifm-button-background-color:var(--ifm-color-primary-dark);--ifm-button-border-color:var(--ifm-color-primary-dark)}.button--primary.button--active,.button--primary:active{--ifm-button-background-color:var(--ifm-color-primary-darker);--ifm-button-border-color:var(--ifm-color-primary-darker)}:where(.button--secondary){--ifm-button-background-color:var(--ifm-color-secondary);--ifm-button-border-color:var(--ifm-color-secondary)}:where(.button--secondary):not(.button--outline):hover{--ifm-button-background-color:var(--ifm-color-secondary-dark);--ifm-button-border-color:var(--ifm-color-secondary-dark)}.button--secondary.button--active,.button--secondary:active{--ifm-button-background-color:var(--ifm-color-secondary-darker);--ifm-button-border-color:var(--ifm-color-secondary-darker)}:where(.button--success){--ifm-button-background-color:var(--ifm-color-success);--ifm-button-border-color:var(--ifm-color-success)}:where(.button--success):not(.button--outline):hover{--ifm-button-background-color:var(--ifm-color-success-dark);--ifm-button-border-color:var(--ifm-color-success-dark)}.button--success.button--active,.button--success:active{--ifm-button-background-color:var(--ifm-color-success-darker);--ifm-button-border-color:var(--ifm-color-success-darker)}:where(.button--info){--ifm-button-background-color:var(--ifm-color-info);--ifm-button-border-color:var(--ifm-color-info)}:where(.button--info):not(.button--outline):hover{--ifm-button-background-color:var(--ifm-color-info-dark);--ifm-button-border-color:var(--ifm-color-info-dark)}.button--info.button--active,.button--info:active{--ifm-button-background-color:var(--ifm-color-info-darker);--ifm-button-border-color:var(--ifm-color-info-darker)}:where(.button--warning){--ifm-button-background-color:var(--ifm-color-warning);--ifm-button-border-color:var(--ifm-color-warning)}:where(.button--warning):not(.button--outline):hover{--ifm-button-background-color:var(--ifm-color-warning-dark);--ifm-button-border-color:var(--ifm-color-warning-dark)}.button--warning.button--active,.button--warning:active{--ifm-button-background-color:var(--ifm-color-warning-darker);--ifm-button-border-color:var(--ifm-color-warning-darker)}:where(.button--danger){--ifm-button-background-color:var(--ifm-color-danger);--ifm-button-border-color:var(--ifm-color-danger)}:where(.button--danger):not(.button--outline):hover{--ifm-button-background-color:var(--ifm-color-danger-dark);--ifm-button-border-color:var(--ifm-color-danger-dark)}.button--danger.button--active,.button--danger:active{--ifm-button-background-color:var(--ifm-color-danger-darker);--ifm-button-border-color:var(--ifm-color-danger-darker)}.button-group{display:inline-flex;gap:var(--ifm-button-group-spacing)}.button-group>.button:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.button-group>.button:not(:last-child){border-bottom-right-radius:0;border-top-right-radius:0}.button-group--block{display:flex;justify-content:stretch}.button-group--block>.button{flex-grow:1}.card{background-color:var(--ifm-card-background-color);border-radius:var(--ifm-card-border-radius);box-shadow:var(--ifm-global-shadow-lw);display:flex;flex-direction:column;overflow:hidden}.card__image{padding-top:var(--ifm-card-vertical-spacing)}.card__image:first-child{padding-top:0}.card__body,.card__footer,.card__header{padding:var(--ifm-card-vertical-spacing) var(--ifm-card-horizontal-spacing)}.card__body:not(:last-child),.card__footer:not(:last-child),.card__header:not(:last-child){padding-bottom:0}.card__body>:last-child,.card__footer>:last-child,.card__header>:last-child{margin-bottom:0}.card__footer{margin-top:auto}.table-of-contents{font-size:.8rem;margin-bottom:0;padding:var(--ifm-toc-padding-vertical) 0}.table-of-contents,.table-of-contents ul{list-style:none;padding-left:var(--ifm-toc-padding-horizontal)}.table-of-contents li{margin:var(--ifm-toc-padding-vertical) var(--ifm-toc-padding-horizontal)}.table-of-contents__left-border{border-left:1px solid var(--ifm-toc-border-color)}.table-of-contents__link{color:var(--ifm-toc-link-color);display:block}.table-of-contents__link--active,.table-of-contents__link--active code,.table-of-contents__link:hover,.table-of-contents__link:hover code{color:var(--ifm-color-primary);text-decoration:none}.close{color:var(--ifm-color-black);float:right;font-size:1.5rem;font-weight:var(--ifm-font-weight-bold);line-height:1;opacity:.5;padding:1rem;transition:opacity var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.close:hover{opacity:.7}.close:focus,.theme-code-block-highlighted-line .codeLineNumber_Tfdd:before{opacity:.8}.dropdown{display:inline-flex;font-weight:var(--ifm-dropdown-font-weight);position:relative;vertical-align:top}.dropdown--hoverable:hover .dropdown__menu,.dropdown--show .dropdown__menu{opacity:1;pointer-events:all;transform:translateY(-1px);visibility:visible}#nprogress,.dropdown__menu,.navbar__item.dropdown .navbar__link:not([href]){pointer-events:none}.dropdown--right .dropdown__menu{left:inherit;right:0}.dropdown--nocaret .navbar__link:after{content:none!important}.dropdown__menu{background-color:var(--ifm-dropdown-background-color);border-radius:var(--ifm-global-radius);box-shadow:var(--ifm-global-shadow-md);left:0;max-height:80vh;min-width:10rem;opacity:0;overflow-y:auto;padding:.5rem;position:absolute;top:calc(100% - var(--ifm-navbar-item-padding-vertical) + .3rem);transform:translateY(-.625rem);transition-duration:var(--ifm-transition-fast);transition-property:opacity,transform,visibility;transition-timing-function:var(--ifm-transition-timing-default);visibility:hidden;z-index:var(--ifm-z-index-dropdown)}.sidebar_re4s,.tableOfContents_bqdL{max-height:calc(100vh - var(--ifm-navbar-height) - 2rem);overflow-y:auto}.menu__caret,.menu__link,.menu__list-item-collapsible{border-radius:.25rem;transition:background var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.dropdown__link{border-radius:.25rem;color:var(--ifm-dropdown-link-color);display:block;font-size:.875rem;margin-top:.2rem;padding:.25rem .5rem;white-space:nowrap}.dropdown__link--active,.dropdown__link:hover{background-color:var(--ifm-dropdown-hover-background-color);color:var(--ifm-dropdown-link-color);text-decoration:none}.dropdown__link--active,.dropdown__link--active:hover{--ifm-dropdown-link-color:var(--ifm-link-color)}.dropdown>.navbar__link:after{border-color:currentcolor #0000;border-style:solid;border-width:.4em .4em 0;content:"";margin-left:.3em;position:relative;top:2px;transform:translateY(-50%)}.footer{background-color:var(--ifm-footer-background-color);color:var(--ifm-footer-color);padding:var(--ifm-footer-padding-vertical) var(--ifm-footer-padding-horizontal)}.footer--dark{--ifm-footer-background-color:#303846;--ifm-footer-color:var(--ifm-footer-link-color);--ifm-footer-link-color:var(--ifm-color-secondary);--ifm-footer-title-color:var(--ifm-color-white)}.footer__links{margin-bottom:1rem}.footer__link-item{color:var(--ifm-footer-link-color);line-height:2}.footer__link-item:hover{color:var(--ifm-footer-link-hover-color)}.footer__link-separator{margin:0 var(--ifm-footer-link-horizontal-spacing)}.footer__logo{margin-top:1rem;max-width:var(--ifm-footer-logo-max-width)}.footer__title{color:var(--ifm-footer-title-color);font:700 var(--ifm-h4-font-size)/var(--ifm-heading-line-height) var(--ifm-font-family-base);margin-bottom:var(--ifm-heading-margin-bottom)}.menu,.navbar__link{font-weight:var(--ifm-font-weight-semibold)}.docItemContainer_Djhp article>:first-child,.docItemContainer_Djhp header+*,.footer__item{margin-top:0}.admonitionContent_S0QG>:last-child,.collapsibleContent_i85q>:last-child,.footer__items{margin-bottom:0}.codeBlockStandalone_MEMb,[type=checkbox]{padding:0}.hero{align-items:center;background-color:var(--ifm-hero-background-color);color:var(--ifm-hero-text-color);display:flex;padding:4rem 2rem}.hero--primary{--ifm-hero-background-color:var(--ifm-color-primary);--ifm-hero-text-color:var(--ifm-font-color-base-inverse)}.hero--dark{--ifm-hero-background-color:#303846;--ifm-hero-text-color:var(--ifm-color-white)}.hero__title,.title_f1Hy{font-size:3rem}.hero__subtitle{font-size:1.5rem}.menu__list{margin:0;padding-left:0}.menu__caret,.menu__link{padding:var(--ifm-menu-link-padding-vertical) var(--ifm-menu-link-padding-horizontal)}.menu__list .menu__list{flex:0 0 100%;margin-top:.25rem;padding-left:var(--ifm-menu-link-padding-horizontal)}.menu__list-item:not(:first-child){margin-top:.25rem}.menu__list-item--collapsed .menu__list{height:0;overflow:hidden}.details_lb9f[data-collapsed=false].isBrowser_bmU9>summary:before,.details_lb9f[open]:not(.isBrowser_bmU9)>summary:before,.menu__list-item--collapsed .menu__caret:before,.menu__list-item--collapsed .menu__link--sublist:after{transform:rotate(90deg)}.menu__list-item-collapsible{display:flex;flex-wrap:wrap;position:relative}.menu__caret:hover,.menu__link:hover,.menu__list-item-collapsible--active,.menu__list-item-collapsible:hover{background:var(--ifm-menu-color-background-hover)}.menu__list-item-collapsible .menu__link--active,.menu__list-item-collapsible .menu__link:hover{background:none!important}.menu__caret,.menu__link{align-items:center;display:flex}.menu__link{color:var(--ifm-menu-color);flex:1;line-height:1.25}.menu__link:hover{color:var(--ifm-menu-color);text-decoration:none}.menu__caret:before,.menu__link--sublist-caret:after{content:"";height:1.25rem;transform:rotate(180deg);transition:transform var(--ifm-transition-fast) linear;width:1.25rem;filter:var(--ifm-menu-link-sublist-icon-filter)}.menu__link--sublist-caret:after{background:var(--ifm-menu-link-sublist-icon) 50%/2rem 2rem;margin-left:auto;min-width:1.25rem}.menu__link--active,.menu__link--active:hover{color:var(--ifm-menu-color-active)}.navbar__brand,.navbar__link{color:var(--ifm-navbar-link-color)}.menu__link--active:not(.menu__link--sublist){background-color:var(--ifm-menu-color-background-active)}.menu__caret:before{background:var(--ifm-menu-link-sublist-icon) 50%/2rem 2rem}.navbar--dark,html[data-theme=dark]{--ifm-menu-link-sublist-icon-filter:invert(100%) sepia(94%) saturate(17%) hue-rotate(223deg) brightness(104%) contrast(98%)}.navbar{background-color:var(--ifm-navbar-background-color);box-shadow:var(--ifm-navbar-shadow);height:var(--ifm-navbar-height);padding:var(--ifm-navbar-padding-vertical) var(--ifm-navbar-padding-horizontal)}.navbar,.navbar>.container,.navbar>.container-fluid{display:flex}.navbar--fixed-top{position:sticky;top:0;z-index:var(--ifm-z-index-fixed)}.navbar-sidebar,.navbar-sidebar__backdrop{bottom:0;opacity:0;position:fixed;transition-duration:var(--ifm-transition-fast);transition-timing-function:ease-in-out;left:0;top:0;visibility:hidden}.navbar__inner{display:flex;flex-wrap:wrap;justify-content:space-between;width:100%}.navbar__brand{align-items:center;display:flex;margin-right:1rem;min-width:0}.navbar__brand:hover{color:var(--ifm-navbar-link-hover-color);text-decoration:none}.announcementBarContent_xLdY,.navbar__title{flex:1 1 auto}.navbar__toggle{display:none;margin-right:.5rem}.navbar__logo{flex:0 0 auto;height:2rem;margin-right:.5rem}.navbar__items{align-items:center;display:flex;flex:1;min-width:0}.navbar__items--center{flex:0 0 auto}.navbar__items--center .navbar__brand{margin:0}.navbar__items--center+.navbar__items--right{flex:1}.navbar__items--right{flex:0 0 auto;justify-content:flex-end}.navbar__items--right>:last-child{padding-right:0}.navbar__item{display:inline-block;padding:var(--ifm-navbar-item-padding-vertical) var(--ifm-navbar-item-padding-horizontal)}.navbar__link--active,.navbar__link:hover{color:var(--ifm-navbar-link-hover-color);text-decoration:none}.navbar--dark,.navbar--primary{--ifm-menu-color:var(--ifm-color-gray-300);--ifm-navbar-link-color:var(--ifm-color-gray-100);--ifm-navbar-search-input-background-color:#ffffff1a;--ifm-navbar-search-input-placeholder-color:#ffffff80;color:var(--ifm-color-white)}.navbar--dark{--ifm-navbar-background-color:#242526;--ifm-menu-color-background-active:#ffffff0d;--ifm-navbar-search-input-color:var(--ifm-color-white)}.navbar--primary{--ifm-navbar-background-color:var(--ifm-color-primary);--ifm-navbar-link-hover-color:var(--ifm-color-white);--ifm-menu-color-active:var(--ifm-color-white);--ifm-navbar-search-input-color:var(--ifm-color-emphasis-500)}.navbar__search-input{-webkit-appearance:none;appearance:none;background:var(--ifm-navbar-search-input-background-color) var(--ifm-navbar-search-input-icon) no-repeat .75rem center/1rem 1rem;border:none;border-radius:2rem;color:var(--ifm-navbar-search-input-color);cursor:text;display:inline-block;font-size:.9rem;height:2rem;padding:0 .5rem 0 2.25rem;width:12.5rem}.navbar__search-input::placeholder{color:var(--ifm-navbar-search-input-placeholder-color)}.navbar-sidebar{background-color:var(--ifm-navbar-background-color);box-shadow:var(--ifm-global-shadow-md);transform:translate3d(-100%,0,0);transition-property:opacity,visibility,transform;width:var(--ifm-navbar-sidebar-width)}.navbar-sidebar--show .navbar-sidebar,.navbar-sidebar__items{transform:translateZ(0)}.navbar-sidebar--show .navbar-sidebar,.navbar-sidebar--show .navbar-sidebar__backdrop{opacity:1;visibility:visible}.navbar-sidebar__backdrop{background-color:#0009;right:0;transition-property:opacity,visibility}.navbar-sidebar__brand{align-items:center;box-shadow:var(--ifm-navbar-shadow);display:flex;flex:1;height:var(--ifm-navbar-height);padding:var(--ifm-navbar-padding-vertical) var(--ifm-navbar-padding-horizontal)}.navbar-sidebar__items{display:flex;height:calc(100% - var(--ifm-navbar-height));transition:transform var(--ifm-transition-fast) ease-in-out}.navbar-sidebar__items--show-secondary{transform:translate3d(calc((var(--ifm-navbar-sidebar-width))*-1),0,0)}.navbar-sidebar__item{flex-shrink:0;padding:.5rem;width:calc(var(--ifm-navbar-sidebar-width))}.navbar-sidebar__back{background:var(--ifm-menu-color-background-active);font-size:15px;font-weight:var(--ifm-button-font-weight);margin:0 0 .2rem -.5rem;padding:.6rem 1.5rem;position:relative;text-align:left;top:-.5rem;width:calc(100% + 1rem)}.navbar-sidebar__close{display:flex;margin-left:auto}.pagination{column-gap:var(--ifm-pagination-page-spacing);display:flex;font-size:var(--ifm-pagination-font-size);padding-left:0}.pagination--sm{--ifm-pagination-font-size:0.8rem;--ifm-pagination-padding-horizontal:0.8rem;--ifm-pagination-padding-vertical:0.2rem}.pagination--lg{--ifm-pagination-font-size:1.2rem;--ifm-pagination-padding-horizontal:1.2rem;--ifm-pagination-padding-vertical:0.3rem}.pagination__item{display:inline-flex}.pagination__item>span{padding:var(--ifm-pagination-padding-vertical)}.pagination__item--active .pagination__link{color:var(--ifm-pagination-color-active)}.pagination__item--active .pagination__link,.pagination__item:not(.pagination__item--active):hover .pagination__link{background:var(--ifm-pagination-item-active-background)}.pagination__item--disabled,.pagination__item[disabled]{opacity:.25;pointer-events:none}.pagination__link{border-radius:var(--ifm-pagination-border-radius);color:var(--ifm-font-color-base);display:inline-block;padding:var(--ifm-pagination-padding-vertical) var(--ifm-pagination-padding-horizontal);transition:background var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.pagination__link:hover,.sidebarItemLink_mo7H:hover{text-decoration:none}.pagination-nav{grid-gap:var(--ifm-spacing-horizontal);display:grid;gap:var(--ifm-spacing-horizontal);grid-template-columns:repeat(2,1fr)}.pagination-nav__link{border:1px solid var(--ifm-color-emphasis-300);border-radius:var(--ifm-pagination-nav-border-radius);display:block;height:100%;line-height:var(--ifm-heading-line-height);padding:var(--ifm-global-spacing);transition:border-color var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.pagination-nav__link:hover{border-color:var(--ifm-pagination-nav-color-hover);text-decoration:none}.pagination-nav__link--next{grid-column:2/3;text-align:right}.pagination-nav__label{font-size:var(--ifm-h4-font-size);font-weight:var(--ifm-heading-font-weight);word-break:break-word}.pagination-nav__link--prev .pagination-nav__label:before{content:"« "}.pagination-nav__link--next .pagination-nav__label:after{content:" »"}.pagination-nav__sublabel{color:var(--ifm-color-content-secondary);font-size:var(--ifm-h5-font-size);font-weight:var(--ifm-font-weight-semibold);margin-bottom:.25rem}.pills__item,.sidebarItemTitle_pO2u,.tabs{font-weight:var(--ifm-font-weight-bold)}.pills{display:flex;gap:var(--ifm-pills-spacing);padding-left:0}.pills__item{border-radius:.5rem;cursor:pointer;display:inline-block;padding:.25rem 1rem;transition:background var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.tabs,:not(.containsTaskList_mC6p>li)>.containsTaskList_mC6p{padding-left:0}.pills__item--active{color:var(--ifm-pills-color-active)}.pills__item--active,.pills__item:not(.pills__item--active):hover{background:var(--ifm-pills-color-background-active)}.pills--block{justify-content:stretch}.pills--block .pills__item{flex-grow:1;text-align:center}.tabs{color:var(--ifm-tabs-color);display:flex;margin-bottom:0;overflow-x:auto}.tabs__item{border-bottom:3px solid #0000;border-radius:var(--ifm-global-radius);cursor:pointer;display:inline-flex;padding:var(--ifm-tabs-padding-vertical) var(--ifm-tabs-padding-horizontal);transition:background-color var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.tabs__item--active{border-bottom-color:var(--ifm-tabs-color-active-border);border-bottom-left-radius:0;border-bottom-right-radius:0;color:var(--ifm-tabs-color-active)}.tabs__item:hover{background-color:var(--ifm-hover-overlay)}.tabs--block{justify-content:stretch}.tabs--block .tabs__item{flex-grow:1;justify-content:center}html[data-theme=dark]{--ifm-color-scheme:dark;--ifm-color-emphasis-0:var(--ifm-color-gray-1000);--ifm-color-emphasis-100:var(--ifm-color-gray-900);--ifm-color-emphasis-200:var(--ifm-color-gray-800);--ifm-color-emphasis-300:var(--ifm-color-gray-700);--ifm-color-emphasis-400:var(--ifm-color-gray-600);--ifm-color-emphasis-600:var(--ifm-color-gray-400);--ifm-color-emphasis-700:var(--ifm-color-gray-300);--ifm-color-emphasis-800:var(--ifm-color-gray-200);--ifm-color-emphasis-900:var(--ifm-color-gray-100);--ifm-color-emphasis-1000:var(--ifm-color-gray-0);--ifm-background-color:#1b1b1d;--ifm-background-surface-color:#242526;--ifm-hover-overlay:#ffffff0d;--ifm-color-content:#e3e3e3;--ifm-color-content-secondary:#fff;--ifm-breadcrumb-separator-filter:invert(64%) sepia(11%) saturate(0%) hue-rotate(149deg) brightness(99%) contrast(95%);--ifm-code-background:#ffffff1a;--ifm-scrollbar-track-background-color:#444;--ifm-scrollbar-thumb-background-color:#686868;--ifm-scrollbar-thumb-hover-background-color:#7a7a7a;--ifm-table-stripe-background:#ffffff12;--ifm-toc-border-color:var(--ifm-color-emphasis-200);--ifm-color-primary-contrast-background:#102445;--ifm-color-primary-contrast-foreground:#ebf2fc;--ifm-color-secondary-contrast-background:#474748;--ifm-color-secondary-contrast-foreground:#fdfdfe;--ifm-color-success-contrast-background:#003100;--ifm-color-success-contrast-foreground:#e6f6e6;--ifm-color-info-contrast-background:#193c47;--ifm-color-info-contrast-foreground:#eef9fd;--ifm-color-warning-contrast-background:#4d3800;--ifm-color-warning-contrast-foreground:#fff8e6;--ifm-color-danger-contrast-background:#4b1113;--ifm-color-danger-contrast-foreground:#ffebec}#nprogress .bar{background:var(--docusaurus-progress-bar-color);height:2px;left:0;position:fixed;top:0;width:100%;z-index:1031}#nprogress .peg{box-shadow:0 0 10px var(--docusaurus-progress-bar-color),0 0 5px var(--docusaurus-progress-bar-color);height:100%;opacity:1;position:absolute;right:0;transform:rotate(3deg) translateY(-4px);width:100px}body,h2,h3,h4,h5,h6{font-family:Fira Sans,-apple-system,sans-serif}.navbar__brand b,h1{font-family:Alfa Slab One,serif;font-weight:300}article h1{padding:25px 30px 0 5px;width:100%}h2{font-weight:600}h3,h4,h5,h6{font-weight:500}.navbar__brand b{font-size:30px}footer.footer--dark{background-color:#2a3439}body:not(.navigation-with-keyboard) :not(input):focus{outline:0}#__docusaurus-base-url-issue-banner-container,.docSidebarContainer_b6E3,.sidebarLogo_isFc,.themedImage_ToTc,[data-theme=dark] .lightToggleIcon_pyhR,[data-theme=light] .darkToggleIcon_wfgR,html[data-announcement-bar-initially-dismissed=true] .announcementBar_mb4j{display:none}.skipToContent_fXgn{background-color:var(--ifm-background-surface-color);color:var(--ifm-color-emphasis-900);left:100%;padding:calc(var(--ifm-global-spacing)/2) var(--ifm-global-spacing);position:fixed;top:1rem;z-index:calc(var(--ifm-z-index-fixed) + 1)}.skipToContent_fXgn:focus{box-shadow:var(--ifm-global-shadow-md);left:1rem}.closeButton_CVFx{line-height:0;padding:0}.content_knG7{font-size:85%;padding:5px 0;text-align:center}.content_knG7 a{color:inherit;text-decoration:underline}.announcementBar_mb4j{align-items:center;background-color:var(--ifm-color-white);border-bottom:1px solid var(--ifm-color-emphasis-100);color:var(--ifm-color-black);display:flex;height:var(--docusaurus-announcement-bar-height)}.announcementBarPlaceholder_vyr4{flex:0 0 10px}.announcementBarClose_gvF7{align-self:stretch;flex:0 0 30px}.toggle_vylO{height:2rem;width:2rem}.toggleButton_gllP{align-items:center;border-radius:50%;display:flex;height:100%;justify-content:center;transition:background var(--ifm-transition-fast);width:100%}.toggleButton_gllP:hover{background:var(--ifm-color-emphasis-200)}.toggleButtonDisabled_aARS{cursor:not-allowed}.darkNavbarColorModeToggle_X3D1:hover{background:var(--ifm-color-gray-800)}[data-theme=dark] .themedImage--dark_i4oU,[data-theme=light] .themedImage--light_HNdA,html:not([data-theme]) .themedComponent--light_NU7w{display:initial}.iconExternalLink_nPIU{margin-left:.3rem}.iconLanguage_nlXk{margin-right:5px;vertical-align:text-bottom}.navbarHideable_m1mJ{transition:transform var(--ifm-transition-fast) ease}.navbarHidden_jGov{transform:translate3d(0,calc(-100% - 2px),0)}.errorBoundaryError_a6uf{color:red;white-space:pre-wrap}.footerLogoLink_BH7S{opacity:.5;transition:opacity var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.footerLogoLink_BH7S:hover,.hash-link:focus,:hover>.hash-link{opacity:1}.mainWrapper_z2l0{display:flex;flex:1 0 auto;flex-direction:column}.docusaurus-mt-lg{margin-top:3rem}#__docusaurus{display:flex;flex-direction:column;min-height:100%}.sidebar_re4s{position:sticky;top:calc(var(--ifm-navbar-height) + 2rem)}.sidebarItemTitle_pO2u{font-size:var(--ifm-h3-font-size)}.container_mt6G,.sidebarItemList_Yudw{font-size:.9rem}.sidebarItem__DBe{margin-top:.7rem}.sidebarItemLink_mo7H{color:var(--ifm-font-color-base);display:block}.sidebarItemLinkActive_I1ZP{color:var(--ifm-color-primary)!important}.backToTopButton_sjWU{background-color:var(--ifm-color-emphasis-200);border-radius:50%;bottom:1.3rem;box-shadow:var(--ifm-global-shadow-lw);height:3rem;opacity:0;position:fixed;right:1.3rem;transform:scale(0);transition:all var(--ifm-transition-fast) var(--ifm-transition-timing-default);visibility:hidden;width:3rem;z-index:calc(var(--ifm-z-index-fixed) - 1)}.buttonGroup__atx button,.codeBlockContainer_Ckt0{background:var(--prism-background-color);color:var(--prism-color)}.backToTopButton_sjWU:after{background-color:var(--ifm-color-emphasis-1000);content:" ";display:inline-block;height:100%;-webkit-mask:var(--ifm-menu-link-sublist-icon) 50%/2rem 2rem no-repeat;mask:var(--ifm-menu-link-sublist-icon) 50%/2rem 2rem no-repeat;width:100%}.backToTopButtonShow_xfvO{opacity:1;transform:scale(1);visibility:visible}[data-theme=dark]:root{--docusaurus-collapse-button-bg:#ffffff0d;--docusaurus-collapse-button-bg-hover:#ffffff1a}.collapseSidebarButton_PEFL{display:none;margin:0}.docMainContainer_gTbr,.docPage__5DB{display:flex;width:100%}.docPage__5DB{flex:1 0}.docsWrapper_BCFX{display:flex;flex:1 0 auto}.authorCol_Hf19{flex-grow:1!important;max-width:inherit!important}.imageOnlyAuthorRow_pa_O{display:flex;flex-flow:row wrap}.imageOnlyAuthorCol_G86a{margin-left:.3rem;margin-right:.3rem}.codeBlockContainer_Ckt0{border-radius:var(--ifm-code-border-radius);box-shadow:var(--ifm-global-shadow-lw);margin-bottom:var(--ifm-leading)}.codeBlockContent_biex{border-radius:inherit;direction:ltr;position:relative}.codeBlockTitle_Ktv7{border-bottom:1px solid var(--ifm-color-emphasis-300);border-top-left-radius:inherit;border-top-right-radius:inherit;font-size:var(--ifm-code-font-size);font-weight:500;padding:.75rem var(--ifm-pre-padding)}.codeBlock_bY9V{--ifm-pre-background:var(--prism-background-color);margin:0;padding:0}.codeBlockTitle_Ktv7+.codeBlockContent_biex .codeBlock_bY9V{border-top-left-radius:0;border-top-right-radius:0}.codeBlockLines_e6Vv{float:left;font:inherit;min-width:100%;padding:var(--ifm-pre-padding)}.codeBlockLinesWithNumbering_o6Pm{display:table;padding:var(--ifm-pre-padding) 0}.buttonGroup__atx{column-gap:.2rem;display:flex;position:absolute;right:calc(var(--ifm-pre-padding)/2);top:calc(var(--ifm-pre-padding)/2)}.buttonGroup__atx button{align-items:center;border:1px solid var(--ifm-color-emphasis-300);border-radius:var(--ifm-global-radius);display:flex;line-height:0;opacity:0;padding:.4rem;transition:opacity var(--ifm-transition-fast) ease-in-out}.buttonGroup__atx button:focus-visible,.buttonGroup__atx button:hover{opacity:1!important}.theme-code-block:hover .buttonGroup__atx button{opacity:.4}.iconEdit_Z9Sw{margin-right:.3em;vertical-align:sub}:where(:root){--docusaurus-highlighted-code-line-bg:#484d5b}:where([data-theme=dark]){--docusaurus-highlighted-code-line-bg:#646464}.theme-code-block-highlighted-line{background-color:var(--docusaurus-highlighted-code-line-bg);display:block;margin:0 calc(var(--ifm-pre-padding)*-1);padding:0 var(--ifm-pre-padding)}.codeLine_lJS_{counter-increment:a;display:table-row}.codeLineNumber_Tfdd{background:var(--ifm-pre-background);display:table-cell;left:0;overflow-wrap:normal;padding:0 var(--ifm-pre-padding);position:sticky;text-align:right;width:1%}.codeLineNumber_Tfdd:before{content:counter(a);opacity:.4}.codeLineContent_feaV{padding-right:var(--ifm-pre-padding)}.tag_zVej{border:1px solid var(--docusaurus-tag-list-border);transition:border var(--ifm-transition-fast)}.tag_zVej:hover{--docusaurus-tag-list-border:var(--ifm-link-color);text-decoration:none}.tagRegular_sFm0{border-radius:var(--ifm-global-radius);font-size:90%;padding:.2rem .5rem .3rem}.tagWithCount_h2kH{align-items:center;border-left:0;display:flex;padding:0 .5rem 0 1rem;position:relative}.tagWithCount_h2kH:after,.tagWithCount_h2kH:before{border:1px solid var(--docusaurus-tag-list-border);content:"";position:absolute;top:50%;transition:inherit}.tagWithCount_h2kH:before{border-bottom:0;border-right:0;height:1.18rem;right:100%;transform:translate(50%,-50%) rotate(-45deg);width:1.18rem}.tagWithCount_h2kH:after{border-radius:50%;height:.5rem;left:0;transform:translateY(-50%);width:.5rem}.tagWithCount_h2kH span{background:var(--ifm-color-secondary);border-radius:var(--ifm-global-radius);color:var(--ifm-color-black);font-size:.7rem;line-height:1.2;margin-left:.3rem;padding:.1rem .4rem}.tag_Nnez{display:inline-block;margin:.5rem .5rem 0 1rem}.theme-code-block:hover .copyButtonCopied_obH4{opacity:1!important}.copyButtonIcons_eSgA{height:1.125rem;position:relative;width:1.125rem}.copyButtonIcon_y97N,.copyButtonSuccessIcon_LjdS{fill:currentColor;height:inherit;left:0;opacity:inherit;position:absolute;top:0;transition:all var(--ifm-transition-fast) ease;width:inherit}.copyButtonSuccessIcon_LjdS{color:#00d600;left:50%;opacity:0;top:50%;transform:translate(-50%,-50%) scale(.33)}.copyButtonCopied_obH4 .copyButtonIcon_y97N{opacity:0;transform:scale(.33)}.copyButtonCopied_obH4 .copyButtonSuccessIcon_LjdS{opacity:1;transform:translate(-50%,-50%) scale(1);transition-delay:75ms}.tags_jXut{display:inline}.tag_QGVx{display:inline-block;margin:0 .4rem .5rem 0}.lastUpdated_vwxv{font-size:smaller;font-style:italic;margin-top:.2rem}.tocCollapsibleButton_TO0P{align-items:center;display:flex;font-size:inherit;justify-content:space-between;padding:.4rem .8rem;width:100%}.tocCollapsibleButton_TO0P:after{background:var(--ifm-menu-link-sublist-icon) 50% 50%/2rem 2rem no-repeat;content:"";filter:var(--ifm-menu-link-sublist-icon-filter);height:1.25rem;transform:rotate(180deg);transition:transform var(--ifm-transition-fast);width:1.25rem}.tocCollapsibleButtonExpanded_MG3E:after,.tocCollapsibleExpanded_sAul{transform:none}.tocCollapsible_ETCw{background-color:var(--ifm-menu-color-background-active);border-radius:var(--ifm-global-radius);margin:1rem 0}.tocCollapsibleContent_vkbj>ul{border-left:none;border-top:1px solid var(--ifm-color-emphasis-300);font-size:15px;padding:.2rem 0}.tocCollapsibleContent_vkbj ul li{margin:.4rem .8rem}.tocCollapsibleContent_vkbj a{display:block}.wordWrapButtonIcon_Bwma{height:1.2rem;width:1.2rem}.details_lb9f{--docusaurus-details-summary-arrow-size:0.38rem;--docusaurus-details-transition:transform 200ms ease;--docusaurus-details-decoration-color:grey}.details_lb9f>summary{cursor:pointer;padding-left:1rem;position:relative}.details_lb9f>summary::-webkit-details-marker{display:none}.details_lb9f>summary:before{border-color:#0000 #0000 #0000 var(--docusaurus-details-decoration-color);border-style:solid;border-width:var(--docusaurus-details-summary-arrow-size);content:"";left:0;position:absolute;top:.45rem;transform:rotate(0);transform-origin:calc(var(--docusaurus-details-summary-arrow-size)/2) 50%;transition:var(--docusaurus-details-transition)}.collapsibleContent_i85q{border-top:1px solid var(--docusaurus-details-decoration-color);margin-top:1rem;padding-top:1rem}.details_b_Ee{--docusaurus-details-decoration-color:var(--ifm-alert-border-color);--docusaurus-details-transition:transform var(--ifm-transition-fast) ease;border:1px solid var(--ifm-alert-border-color);margin:0 0 var(--ifm-spacing-vertical)}.anchorWithStickyNavbar_LWe7{scroll-margin-top:calc(var(--ifm-navbar-height) + .5rem)}.anchorWithHideOnScrollNavbar_WYt5{scroll-margin-top:.5rem}.hash-link{opacity:0;padding-left:.5rem;transition:opacity var(--ifm-transition-fast);-webkit-user-select:none;user-select:none}.hash-link:before{content:"#"}.img_ev3q{height:auto}.admonition_LlT9{margin-bottom:1em}.admonitionHeading_tbUL{font:var(--ifm-heading-font-weight) var(--ifm-h5-font-size)/var(--ifm-heading-line-height) var(--ifm-heading-font-family);margin-bottom:.3rem}.admonitionHeading_tbUL code{text-transform:none}.admonitionIcon_kALy{display:inline-block;margin-right:.4em;vertical-align:middle}.admonitionIcon_kALy svg{fill:var(--ifm-alert-foreground-color);display:inline-block;height:1.6em;width:1.6em}.blogPostFooterDetailsFull_mRVl{flex-direction:column}.tableOfContents_bqdL{position:sticky;top:calc(var(--ifm-navbar-height) + 1rem)}.breadcrumbHomeIcon_YNFT{height:1.1rem;position:relative;top:1px;vertical-align:top;width:1.1rem}.breadcrumbsContainer_Z_bl{--ifm-breadcrumb-size-multiplier:0.8;margin-bottom:.8rem}@media (min-width:997px){.collapseSidebarButton_PEFL,.expandButton_m80_{background-color:var(--docusaurus-collapse-button-bg)}:root{--docusaurus-announcement-bar-height:30px}.announcementBarClose_gvF7,.announcementBarPlaceholder_vyr4{flex-basis:50px}.searchBox_ZlJk{padding:var(--ifm-navbar-item-padding-vertical) var(--ifm-navbar-item-padding-horizontal)}.collapseSidebarButton_PEFL{border:1px solid var(--ifm-toc-border-color);border-radius:0;bottom:0;display:block!important;height:40px;position:sticky}.collapseSidebarButtonIcon_kv0_{margin-top:4px;transform:rotate(180deg)}.expandButtonIcon_BlDH,[dir=rtl] .collapseSidebarButtonIcon_kv0_{transform:rotate(0)}.collapseSidebarButton_PEFL:focus,.collapseSidebarButton_PEFL:hover,.expandButton_m80_:focus,.expandButton_m80_:hover{background-color:var(--docusaurus-collapse-button-bg-hover)}.menuHtmlItem_M9Kj{padding:var(--ifm-menu-link-padding-vertical) var(--ifm-menu-link-padding-horizontal)}.menu_SIkG{flex-grow:1;padding:.5rem}@supports (scrollbar-gutter:stable){.menu_SIkG{padding:.5rem 0 .5rem .5rem;scrollbar-gutter:stable}}.menuWithAnnouncementBar_GW3s{margin-bottom:var(--docusaurus-announcement-bar-height)}.sidebar_njMd{display:flex;flex-direction:column;height:100%;padding-top:var(--ifm-navbar-height);width:var(--doc-sidebar-width)}.sidebarWithHideableNavbar_wUlq{padding-top:0}.sidebarHidden_VK0M{opacity:0;visibility:hidden}.sidebarLogo_isFc{align-items:center;color:inherit!important;display:flex!important;margin:0 var(--ifm-navbar-padding-horizontal);max-height:var(--ifm-navbar-height);min-height:var(--ifm-navbar-height);text-decoration:none!important}.sidebarLogo_isFc img{height:2rem;margin-right:.5rem}.expandButton_m80_{align-items:center;display:flex;height:100%;justify-content:center;position:absolute;right:0;top:0;transition:background-color var(--ifm-transition-fast) ease;width:100%}[dir=rtl] .expandButtonIcon_BlDH{transform:rotate(180deg)}.docSidebarContainer_b6E3{border-right:1px solid var(--ifm-toc-border-color);-webkit-clip-path:inset(0);clip-path:inset(0);display:block;margin-top:calc(var(--ifm-navbar-height)*-1);transition:width var(--ifm-transition-fast) ease;width:var(--doc-sidebar-width);will-change:width}.docSidebarContainerHidden_b3ry{cursor:pointer;width:var(--doc-sidebar-hidden-width)}.sidebarViewport_Xe31{height:100%;max-height:100vh;position:sticky;top:0}.docMainContainer_gTbr{flex-grow:1;max-width:calc(100% - var(--doc-sidebar-width))}.docMainContainerEnhanced_Uz_u{max-width:calc(100% - var(--doc-sidebar-hidden-width))}.docItemWrapperEnhanced_czyv{max-width:calc(var(--ifm-container-width) + var(--doc-sidebar-width))!important}.lastUpdated_vwxv{text-align:right}.tocMobile_ITEo{display:none}.docItemCol_VOVn{max-width:75%!important}}@media (min-width:1440px){.container{max-width:var(--ifm-container-width-xl)}}@media (max-width:996px){.col{--ifm-col-width:100%;flex-basis:var(--ifm-col-width);margin-left:0}.footer{--ifm-footer-padding-horizontal:0}.colorModeToggle_DEke,.footer__link-separator,.navbar__item,.sidebar_re4s,.tableOfContents_bqdL{display:none}.footer__col{margin-bottom:calc(var(--ifm-spacing-vertical)*3)}.footer__link-item{display:block}.hero{padding-left:0;padding-right:0}.navbar>.container,.navbar>.container-fluid{padding:0}.navbar__toggle{display:inherit}.navbar__search-input{width:9rem}.pills--block,.tabs--block{flex-direction:column}.searchBox_ZlJk{position:absolute;right:var(--ifm-navbar-padding-horizontal)}.docItemContainer_F8PC{padding:0 .3rem}}@media (max-width:576px){.markdown h1:first-child{--ifm-h1-font-size:2rem}.markdown>h2{--ifm-h2-font-size:1.5rem}.markdown>h3{--ifm-h3-font-size:1.25rem}.title_f1Hy{font-size:2rem}}@media (hover:hover){.backToTopButton_sjWU:hover{background-color:var(--ifm-color-emphasis-300)}}@media (pointer:fine){.thin-scrollbar{scrollbar-width:thin}.thin-scrollbar::-webkit-scrollbar{height:var(--ifm-scrollbar-size);width:var(--ifm-scrollbar-size)}.thin-scrollbar::-webkit-scrollbar-track{background:var(--ifm-scrollbar-track-background-color);border-radius:10px}.thin-scrollbar::-webkit-scrollbar-thumb{background:var(--ifm-scrollbar-thumb-background-color);border-radius:10px}.thin-scrollbar::-webkit-scrollbar-thumb:hover{background:var(--ifm-scrollbar-thumb-hover-background-color)}}@media (prefers-reduced-motion:reduce){:root{--ifm-transition-fast:0ms;--ifm-transition-slow:0ms}}@media print{.announcementBar_mb4j,.footer,.menu,.navbar,.pagination-nav,.table-of-contents,.tocMobile_ITEo{display:none}.tabs{page-break-inside:avoid}.codeBlockLines_e6Vv{white-space:pre-wrap}} \ No newline at end of file diff --git a/docs/dev/assets/js/1be78505.584d3a15.js b/docs/dev/assets/js/1be78505.efcc4864.js similarity index 76% rename from docs/dev/assets/js/1be78505.584d3a15.js rename to docs/dev/assets/js/1be78505.efcc4864.js index ba7c7563..0794ba49 100644 --- a/docs/dev/assets/js/1be78505.584d3a15.js +++ b/docs/dev/assets/js/1be78505.efcc4864.js @@ -1 +1 @@ -"use strict";(self.webpackChunkdocs=self.webpackChunkdocs||[]).push([[9514,4972],{9963:(e,t,n)=>{n.r(t),n.d(t,{default:()=>ge});var a=n(7294),o=n(6010),l=n(1944),r=n(5281),c=n(3320),i=n(2802),s=n(4477),d=n(1116),m=n(7961),u=n(5999),b=n(2466),p=n(5936);const h={backToTopButton:"backToTopButton_sjWU",backToTopButtonShow:"backToTopButtonShow_xfvO"};function E(){const{shown:e,scrollToTop:t}=function(e){let{threshold:t}=e;const[n,o]=(0,a.useState)(!1),l=(0,a.useRef)(!1),{startScroll:r,cancelScroll:c}=(0,b.Ct)();return(0,b.RF)(((e,n)=>{let{scrollY:a}=e;const r=n?.scrollY;r&&(l.current?l.current=!1:a>=r?(c(),o(!1)):a{e.location.hash&&(l.current=!0,o(!1))})),{shown:n,scrollToTop:()=>r(0)}}({threshold:300});return a.createElement("button",{"aria-label":(0,u.I)({id:"theme.BackToTopButton.buttonAriaLabel",message:"Scroll back to top",description:"The ARIA label for the back to top button"}),className:(0,o.Z)("clean-btn",r.k.common.backToTopButton,h.backToTopButton,e&&h.backToTopButtonShow),type:"button",onClick:t})}var f=n(1442),g=n(6550),v=n(7524),k=n(6668),_=n(1327),C=n(7462);function S(e){return a.createElement("svg",(0,C.Z)({width:"20",height:"20","aria-hidden":"true"},e),a.createElement("g",{fill:"#7a7a7a"},a.createElement("path",{d:"M9.992 10.023c0 .2-.062.399-.172.547l-4.996 7.492a.982.982 0 01-.828.454H1c-.55 0-1-.453-1-1 0-.2.059-.403.168-.551l4.629-6.942L.168 3.078A.939.939 0 010 2.528c0-.548.45-.997 1-.997h2.996c.352 0 .649.18.828.45L9.82 9.472c.11.148.172.347.172.55zm0 0"}),a.createElement("path",{d:"M19.98 10.023c0 .2-.058.399-.168.547l-4.996 7.492a.987.987 0 01-.828.454h-3c-.547 0-.996-.453-.996-1 0-.2.059-.403.168-.551l4.625-6.942-4.625-6.945a.939.939 0 01-.168-.55 1 1 0 01.996-.997h3c.348 0 .649.18.828.45l4.996 7.492c.11.148.168.347.168.55zm0 0"})))}const I={collapseSidebarButton:"collapseSidebarButton_PEFL",collapseSidebarButtonIcon:"collapseSidebarButtonIcon_kv0_"};function N(e){let{onClick:t}=e;return a.createElement("button",{type:"button",title:(0,u.I)({id:"theme.docs.sidebar.collapseButtonTitle",message:"Collapse sidebar",description:"The title attribute for collapse button of doc sidebar"}),"aria-label":(0,u.I)({id:"theme.docs.sidebar.collapseButtonAriaLabel",message:"Collapse sidebar",description:"The title attribute for collapse button of doc sidebar"}),className:(0,o.Z)("button button--secondary button--outline",I.collapseSidebarButton),onClick:t},a.createElement(S,{className:I.collapseSidebarButtonIcon}))}var T=n(9689),x=n(902);const Z=Symbol("EmptyContext"),B=a.createContext(Z);function y(e){let{children:t}=e;const[n,o]=(0,a.useState)(null),l=(0,a.useMemo)((()=>({expandedItem:n,setExpandedItem:o})),[n]);return a.createElement(B.Provider,{value:l},t)}var w=n(6043),L=n(8596),A=n(9960),M=n(2389);function F(e){let{categoryLabel:t,onClick:n}=e;return a.createElement("button",{"aria-label":(0,u.I)({id:"theme.DocSidebarItem.toggleCollapsedCategoryAriaLabel",message:"Toggle the collapsible sidebar category '{label}'",description:"The ARIA label to toggle the collapsible sidebar category"},{label:t}),type:"button",className:"clean-btn menu__caret",onClick:n})}function H(e){let{item:t,onItemClick:n,activePath:l,level:c,index:s,...d}=e;const{items:m,label:u,collapsible:b,className:p,href:h}=t,{docs:{sidebar:{autoCollapseCategories:E}}}=(0,k.L)(),f=function(e){const t=(0,M.Z)();return(0,a.useMemo)((()=>e.href?e.href:!t&&e.collapsible?(0,i.Wl)(e):void 0),[e,t])}(t),g=(0,i._F)(t,l),v=(0,L.Mg)(h,l),{collapsed:_,setCollapsed:S}=(0,w.u)({initialState:()=>!!b&&(!g&&t.collapsed)}),{expandedItem:I,setExpandedItem:N}=function(){const e=(0,a.useContext)(B);if(e===Z)throw new x.i6("DocSidebarItemsExpandedStateProvider");return e}(),T=function(e){void 0===e&&(e=!_),N(e?null:s),S(e)};return function(e){let{isActive:t,collapsed:n,updateCollapsed:o}=e;const l=(0,x.D9)(t);(0,a.useEffect)((()=>{t&&!l&&n&&o(!1)}),[t,l,n,o])}({isActive:g,collapsed:_,updateCollapsed:T}),(0,a.useEffect)((()=>{b&&null!=I&&I!==s&&E&&S(!0)}),[b,I,s,S,E]),a.createElement("li",{className:(0,o.Z)(r.k.docs.docSidebarItemCategory,r.k.docs.docSidebarItemCategoryLevel(c),"menu__list-item",{"menu__list-item--collapsed":_},p)},a.createElement("div",{className:(0,o.Z)("menu__list-item-collapsible",{"menu__list-item-collapsible--active":v})},a.createElement(A.Z,(0,C.Z)({className:(0,o.Z)("menu__link",{"menu__link--sublist":b,"menu__link--sublist-caret":!h&&b,"menu__link--active":g}),onClick:b?e=>{n?.(t),h?T(!1):(e.preventDefault(),T())}:()=>{n?.(t)},"aria-current":v?"page":void 0,"aria-expanded":b?!_:void 0,href:b?f??"#":f},d),u),h&&b&&a.createElement(F,{categoryLabel:u,onClick:e=>{e.preventDefault(),T()}})),a.createElement(w.z,{lazy:!0,as:"ul",className:"menu__list",collapsed:_},a.createElement(j,{items:m,tabIndex:_?-1:0,onItemClick:n,activePath:l,level:c+1})))}var P=n(3919),W=n(9471);const D={menuExternalLink:"menuExternalLink_NmtK"};function R(e){let{item:t,onItemClick:n,activePath:l,level:c,index:s,...d}=e;const{href:m,label:u,className:b,autoAddBaseUrl:p}=t,h=(0,i._F)(t,l),E=(0,P.Z)(m);return a.createElement("li",{className:(0,o.Z)(r.k.docs.docSidebarItemLink,r.k.docs.docSidebarItemLinkLevel(c),"menu__list-item",b),key:u},a.createElement(A.Z,(0,C.Z)({className:(0,o.Z)("menu__link",!E&&D.menuExternalLink,{"menu__link--active":h}),autoAddBaseUrl:p,"aria-current":h?"page":void 0,to:m},E&&{onClick:n?()=>n(t):void 0},d),u,!E&&a.createElement(W.Z,null)))}const V={menuHtmlItem:"menuHtmlItem_M9Kj"};function z(e){let{item:t,level:n,index:l}=e;const{value:c,defaultStyle:i,className:s}=t;return a.createElement("li",{className:(0,o.Z)(r.k.docs.docSidebarItemLink,r.k.docs.docSidebarItemLinkLevel(n),i&&[V.menuHtmlItem,"menu__list-item"],s),key:l,dangerouslySetInnerHTML:{__html:c}})}function U(e){let{item:t,...n}=e;switch(t.type){case"category":return a.createElement(H,(0,C.Z)({item:t},n));case"html":return a.createElement(z,(0,C.Z)({item:t},n));default:return a.createElement(R,(0,C.Z)({item:t},n))}}function K(e){let{items:t,...n}=e;return a.createElement(y,null,t.map(((e,t)=>a.createElement(U,(0,C.Z)({key:t,item:e,index:t},n)))))}const j=(0,a.memo)(K),q={menu:"menu_SIkG",menuWithAnnouncementBar:"menuWithAnnouncementBar_GW3s"};function G(e){let{path:t,sidebar:n,className:l}=e;const c=function(){const{isActive:e}=(0,T.nT)(),[t,n]=(0,a.useState)(e);return(0,b.RF)((t=>{let{scrollY:a}=t;e&&n(0===a)}),[e]),e&&t}();return a.createElement("nav",{"aria-label":(0,u.I)({id:"theme.docs.sidebar.navAriaLabel",message:"Docs sidebar",description:"The ARIA label for the sidebar navigation"}),className:(0,o.Z)("menu thin-scrollbar",q.menu,c&&q.menuWithAnnouncementBar,l)},a.createElement("ul",{className:(0,o.Z)(r.k.docs.docSidebarMenu,"menu__list")},a.createElement(j,{items:n,activePath:t,level:1})))}const Y="sidebar_njMd",O="sidebarWithHideableNavbar_wUlq",X="sidebarHidden_VK0M",J="sidebarLogo_isFc";function Q(e){let{path:t,sidebar:n,onCollapse:l,isHidden:r}=e;const{navbar:{hideOnScroll:c},docs:{sidebar:{hideable:i}}}=(0,k.L)();return a.createElement("div",{className:(0,o.Z)(Y,c&&O,r&&X)},c&&a.createElement(_.Z,{tabIndex:-1,className:J}),a.createElement(G,{path:t,sidebar:n}),i&&a.createElement(N,{onClick:l}))}const $=a.memo(Q);var ee=n(3102),te=n(2961);const ne=e=>{let{sidebar:t,path:n}=e;const l=(0,te.e)();return a.createElement("ul",{className:(0,o.Z)(r.k.docs.docSidebarMenu,"menu__list")},a.createElement(j,{items:t,activePath:n,onItemClick:e=>{"category"===e.type&&e.href&&l.toggle(),"link"===e.type&&l.toggle()},level:1}))};function ae(e){return a.createElement(ee.Zo,{component:ne,props:e})}const oe=a.memo(ae);function le(e){const t=(0,v.i)(),n="desktop"===t||"ssr"===t,o="mobile"===t;return a.createElement(a.Fragment,null,n&&a.createElement($,e),o&&a.createElement(oe,e))}const re={expandButton:"expandButton_m80_",expandButtonIcon:"expandButtonIcon_BlDH"};function ce(e){let{toggleSidebar:t}=e;return a.createElement("div",{className:re.expandButton,title:(0,u.I)({id:"theme.docs.sidebar.expandButtonTitle",message:"Expand sidebar",description:"The ARIA label and title attribute for expand button of doc sidebar"}),"aria-label":(0,u.I)({id:"theme.docs.sidebar.expandButtonAriaLabel",message:"Expand sidebar",description:"The ARIA label and title attribute for expand button of doc sidebar"}),tabIndex:0,role:"button",onKeyDown:t,onClick:t},a.createElement(S,{className:re.expandButtonIcon}))}const ie={docSidebarContainer:"docSidebarContainer_b6E3",docSidebarContainerHidden:"docSidebarContainerHidden_b3ry",sidebarViewport:"sidebarViewport_Xe31"};function se(e){let{children:t}=e;const n=(0,d.V)();return a.createElement(a.Fragment,{key:n?.name??"noSidebar"},t)}function de(e){let{sidebar:t,hiddenSidebarContainer:n,setHiddenSidebarContainer:l}=e;const{pathname:c}=(0,g.TH)(),[i,s]=(0,a.useState)(!1),d=(0,a.useCallback)((()=>{i&&s(!1),!i&&(0,f.n)()&&s(!0),l((e=>!e))}),[l,i]);return a.createElement("aside",{className:(0,o.Z)(r.k.docs.docSidebarContainer,ie.docSidebarContainer,n&&ie.docSidebarContainerHidden),onTransitionEnd:e=>{e.currentTarget.classList.contains(ie.docSidebarContainer)&&n&&s(!0)}},a.createElement(se,null,a.createElement("div",{className:(0,o.Z)(ie.sidebarViewport,i&&ie.sidebarViewportHidden)},a.createElement(le,{sidebar:t,path:c,onCollapse:d,isHidden:i}),i&&a.createElement(ce,{toggleSidebar:d}))))}const me={docMainContainer:"docMainContainer_gTbr",docMainContainerEnhanced:"docMainContainerEnhanced_Uz_u",docItemWrapperEnhanced:"docItemWrapperEnhanced_czyv"};function ue(e){let{hiddenSidebarContainer:t,children:n}=e;const l=(0,d.V)();return a.createElement("main",{className:(0,o.Z)(me.docMainContainer,(t||!l)&&me.docMainContainerEnhanced)},a.createElement("div",{className:(0,o.Z)("container padding-top--md padding-bottom--lg",me.docItemWrapper,t&&me.docItemWrapperEnhanced)},n))}const be={docPage:"docPage__5DB",docsWrapper:"docsWrapper_BCFX"};function pe(e){let{children:t}=e;const n=(0,d.V)(),[o,l]=(0,a.useState)(!1);return a.createElement(m.Z,{wrapperClassName:be.docsWrapper},a.createElement(E,null),a.createElement("div",{className:be.docPage},n&&a.createElement(de,{sidebar:n.items,hiddenSidebarContainer:o,setHiddenSidebarContainer:l}),a.createElement(ue,{hiddenSidebarContainer:o},t)))}var he=n(4972),Ee=n(197);function fe(e){const{versionMetadata:t}=e;return a.createElement(a.Fragment,null,a.createElement(Ee.Z,{version:t.version,tag:(0,c.os)(t.pluginId,t.version)}),a.createElement(l.d,null,t.noIndex&&a.createElement("meta",{name:"robots",content:"noindex, nofollow"})))}function ge(e){const{versionMetadata:t}=e,n=(0,i.hI)(e);if(!n)return a.createElement(he.default,null);const{docElement:c,sidebarName:m,sidebarItems:u}=n;return a.createElement(a.Fragment,null,a.createElement(fe,e),a.createElement(l.FG,{className:(0,o.Z)(r.k.wrapper.docsPages,r.k.page.docsDocPage,e.versionMetadata.className)},a.createElement(s.q,{version:t},a.createElement(d.b,{name:m,items:u},a.createElement(pe,null,c)))))}},4972:(e,t,n)=>{n.r(t),n.d(t,{default:()=>c});var a=n(7294),o=n(5999),l=n(1944),r=n(7961);function c(){return a.createElement(a.Fragment,null,a.createElement(l.d,{title:(0,o.I)({id:"theme.NotFound.title",message:"Page Not Found"})}),a.createElement(r.Z,null,a.createElement("main",{className:"container margin-vert--xl"},a.createElement("div",{className:"row"},a.createElement("div",{className:"col col--6 col--offset-3"},a.createElement("h1",{className:"hero__title"},a.createElement(o.Z,{id:"theme.NotFound.title",description:"The title of the 404 page"},"Page Not Found")),a.createElement("p",null,a.createElement(o.Z,{id:"theme.NotFound.p1",description:"The first paragraph of the 404 page"},"We could not find what you were looking for.")),a.createElement("p",null,a.createElement(o.Z,{id:"theme.NotFound.p2",description:"The 2nd paragraph of the 404 page"},"Please contact the owner of the site that linked you to the original URL and let them know their link is broken.")))))))}},4477:(e,t,n)=>{n.d(t,{E:()=>c,q:()=>r});var a=n(7294),o=n(902);const l=a.createContext(null);function r(e){let{children:t,version:n}=e;return a.createElement(l.Provider,{value:n},t)}function c(){const e=(0,a.useContext)(l);if(null===e)throw new o.i6("DocsVersionProvider");return e}}}]); \ No newline at end of file +"use strict";(self.webpackChunkdocs=self.webpackChunkdocs||[]).push([[9514,4972],{9963:(e,t,n)=>{n.r(t),n.d(t,{default:()=>ge});var a=n(7294),o=n(6010),l=n(1944),r=n(5281),c=n(3320),i=n(2802),s=n(4477),d=n(1116),m=n(7961),u=n(5999),b=n(2466),p=n(5936);const h={backToTopButton:"backToTopButton_sjWU",backToTopButtonShow:"backToTopButtonShow_xfvO"};function E(){const{shown:e,scrollToTop:t}=function(e){let{threshold:t}=e;const[n,o]=(0,a.useState)(!1),l=(0,a.useRef)(!1),{startScroll:r,cancelScroll:c}=(0,b.Ct)();return(0,b.RF)(((e,n)=>{let{scrollY:a}=e;const r=n?.scrollY;r&&(l.current?l.current=!1:a>=r?(c(),o(!1)):a{e.location.hash&&(l.current=!0,o(!1))})),{shown:n,scrollToTop:()=>r(0)}}({threshold:300});return a.createElement("button",{"aria-label":(0,u.I)({id:"theme.BackToTopButton.buttonAriaLabel",message:"Scroll back to top",description:"The ARIA label for the back to top button"}),className:(0,o.Z)("clean-btn",r.k.common.backToTopButton,h.backToTopButton,e&&h.backToTopButtonShow),type:"button",onClick:t})}var f=n(1442),g=n(6550),v=n(7524),k=n(6668),_=n(1327),C=n(7462);function S(e){return a.createElement("svg",(0,C.Z)({width:"20",height:"20","aria-hidden":"true"},e),a.createElement("g",{fill:"#7a7a7a"},a.createElement("path",{d:"M9.992 10.023c0 .2-.062.399-.172.547l-4.996 7.492a.982.982 0 01-.828.454H1c-.55 0-1-.453-1-1 0-.2.059-.403.168-.551l4.629-6.942L.168 3.078A.939.939 0 010 2.528c0-.548.45-.997 1-.997h2.996c.352 0 .649.18.828.45L9.82 9.472c.11.148.172.347.172.55zm0 0"}),a.createElement("path",{d:"M19.98 10.023c0 .2-.058.399-.168.547l-4.996 7.492a.987.987 0 01-.828.454h-3c-.547 0-.996-.453-.996-1 0-.2.059-.403.168-.551l4.625-6.942-4.625-6.945a.939.939 0 01-.168-.55 1 1 0 01.996-.997h3c.348 0 .649.18.828.45l4.996 7.492c.11.148.168.347.168.55zm0 0"})))}const I={collapseSidebarButton:"collapseSidebarButton_PEFL",collapseSidebarButtonIcon:"collapseSidebarButtonIcon_kv0_"};function N(e){let{onClick:t}=e;return a.createElement("button",{type:"button",title:(0,u.I)({id:"theme.docs.sidebar.collapseButtonTitle",message:"Collapse sidebar",description:"The title attribute for collapse button of doc sidebar"}),"aria-label":(0,u.I)({id:"theme.docs.sidebar.collapseButtonAriaLabel",message:"Collapse sidebar",description:"The title attribute for collapse button of doc sidebar"}),className:(0,o.Z)("button button--secondary button--outline",I.collapseSidebarButton),onClick:t},a.createElement(S,{className:I.collapseSidebarButtonIcon}))}var T=n(9689),x=n(902);const Z=Symbol("EmptyContext"),B=a.createContext(Z);function w(e){let{children:t}=e;const[n,o]=(0,a.useState)(null),l=(0,a.useMemo)((()=>({expandedItem:n,setExpandedItem:o})),[n]);return a.createElement(B.Provider,{value:l},t)}var y=n(6043),L=n(8596),A=n(9960),M=n(2389);function F(e){let{categoryLabel:t,onClick:n}=e;return a.createElement("button",{"aria-label":(0,u.I)({id:"theme.DocSidebarItem.toggleCollapsedCategoryAriaLabel",message:"Toggle the collapsible sidebar category '{label}'",description:"The ARIA label to toggle the collapsible sidebar category"},{label:t}),type:"button",className:"clean-btn menu__caret",onClick:n})}function H(e){let{item:t,onItemClick:n,activePath:l,level:c,index:s,...d}=e;const{items:m,label:u,collapsible:b,className:p,href:h}=t,{docs:{sidebar:{autoCollapseCategories:E}}}=(0,k.L)(),f=function(e){const t=(0,M.Z)();return(0,a.useMemo)((()=>e.href?e.href:!t&&e.collapsible?(0,i.Wl)(e):void 0),[e,t])}(t),g=(0,i._F)(t,l),v=(0,L.Mg)(h,l),{collapsed:_,setCollapsed:S}=(0,y.u)({initialState:()=>!!b&&(!g&&t.collapsed)}),{expandedItem:I,setExpandedItem:N}=function(){const e=(0,a.useContext)(B);if(e===Z)throw new x.i6("DocSidebarItemsExpandedStateProvider");return e}(),T=function(e){void 0===e&&(e=!_),N(e?null:s),S(e)};return function(e){let{isActive:t,collapsed:n,updateCollapsed:o}=e;const l=(0,x.D9)(t);(0,a.useEffect)((()=>{t&&!l&&n&&o(!1)}),[t,l,n,o])}({isActive:g,collapsed:_,updateCollapsed:T}),(0,a.useEffect)((()=>{b&&null!=I&&I!==s&&E&&S(!0)}),[b,I,s,S,E]),a.createElement("li",{className:(0,o.Z)(r.k.docs.docSidebarItemCategory,r.k.docs.docSidebarItemCategoryLevel(c),"menu__list-item",{"menu__list-item--collapsed":_},p)},a.createElement("div",{className:(0,o.Z)("menu__list-item-collapsible",{"menu__list-item-collapsible--active":v})},a.createElement(A.Z,(0,C.Z)({className:(0,o.Z)("menu__link",{"menu__link--sublist":b,"menu__link--sublist-caret":!h&&b,"menu__link--active":g}),onClick:b?e=>{n?.(t),h?T(!1):(e.preventDefault(),T())}:()=>{n?.(t)},"aria-current":v?"page":void 0,"aria-expanded":b?!_:void 0,href:b?f??"#":f},d),u),h&&b&&a.createElement(F,{categoryLabel:u,onClick:e=>{e.preventDefault(),T()}})),a.createElement(y.z,{lazy:!0,as:"ul",className:"menu__list",collapsed:_},a.createElement(j,{items:m,tabIndex:_?-1:0,onItemClick:n,activePath:l,level:c+1})))}var P=n(3919),W=n(9471);const D={menuExternalLink:"menuExternalLink_NmtK"};function R(e){let{item:t,onItemClick:n,activePath:l,level:c,index:s,...d}=e;const{href:m,label:u,className:b,autoAddBaseUrl:p}=t,h=(0,i._F)(t,l),E=(0,P.Z)(m);return a.createElement("li",{className:(0,o.Z)(r.k.docs.docSidebarItemLink,r.k.docs.docSidebarItemLinkLevel(c),"menu__list-item",b),key:u},a.createElement(A.Z,(0,C.Z)({className:(0,o.Z)("menu__link",!E&&D.menuExternalLink,{"menu__link--active":h}),autoAddBaseUrl:p,"aria-current":h?"page":void 0,to:m},E&&{onClick:n?()=>n(t):void 0},d),u,!E&&a.createElement(W.Z,null)))}const V={menuHtmlItem:"menuHtmlItem_M9Kj"};function U(e){let{item:t,level:n,index:l}=e;const{value:c,defaultStyle:i,className:s}=t;return a.createElement("li",{className:(0,o.Z)(r.k.docs.docSidebarItemLink,r.k.docs.docSidebarItemLinkLevel(n),i&&[V.menuHtmlItem,"menu__list-item"],s),key:l,dangerouslySetInnerHTML:{__html:c}})}function z(e){let{item:t,...n}=e;switch(t.type){case"category":return a.createElement(H,(0,C.Z)({item:t},n));case"html":return a.createElement(U,(0,C.Z)({item:t},n));default:return a.createElement(R,(0,C.Z)({item:t},n))}}function K(e){let{items:t,...n}=e;return a.createElement(w,null,t.map(((e,t)=>a.createElement(z,(0,C.Z)({key:t,item:e,index:t},n)))))}const j=(0,a.memo)(K),q={menu:"menu_SIkG",menuWithAnnouncementBar:"menuWithAnnouncementBar_GW3s"};function G(e){let{path:t,sidebar:n,className:l}=e;const c=function(){const{isActive:e}=(0,T.nT)(),[t,n]=(0,a.useState)(e);return(0,b.RF)((t=>{let{scrollY:a}=t;e&&n(0===a)}),[e]),e&&t}();return a.createElement("nav",{"aria-label":(0,u.I)({id:"theme.docs.sidebar.navAriaLabel",message:"Docs sidebar",description:"The ARIA label for the sidebar navigation"}),className:(0,o.Z)("menu thin-scrollbar",q.menu,c&&q.menuWithAnnouncementBar,l)},a.createElement("ul",{className:(0,o.Z)(r.k.docs.docSidebarMenu,"menu__list")},a.createElement(j,{items:n,activePath:t,level:1})))}const Y="sidebar_njMd",O="sidebarWithHideableNavbar_wUlq",X="sidebarHidden_VK0M",J="sidebarLogo_isFc";function Q(e){let{path:t,sidebar:n,onCollapse:l,isHidden:r}=e;const{navbar:{hideOnScroll:c},docs:{sidebar:{hideable:i}}}=(0,k.L)();return a.createElement("div",{className:(0,o.Z)(Y,c&&O,r&&X)},c&&a.createElement(_.Z,{tabIndex:-1,className:J}),a.createElement(G,{path:t,sidebar:n}),i&&a.createElement(N,{onClick:l}))}const $=a.memo(Q);var ee=n(3102),te=n(2961);const ne=e=>{let{sidebar:t,path:n}=e;const l=(0,te.e)();return a.createElement("ul",{className:(0,o.Z)(r.k.docs.docSidebarMenu,"menu__list")},a.createElement(j,{items:t,activePath:n,onItemClick:e=>{"category"===e.type&&e.href&&l.toggle(),"link"===e.type&&l.toggle()},level:1}))};function ae(e){return a.createElement(ee.Zo,{component:ne,props:e})}const oe=a.memo(ae);function le(e){const t=(0,v.i)(),n="desktop"===t||"ssr"===t,o="mobile"===t;return a.createElement(a.Fragment,null,n&&a.createElement($,e),o&&a.createElement(oe,e))}const re={expandButton:"expandButton_m80_",expandButtonIcon:"expandButtonIcon_BlDH"};function ce(e){let{toggleSidebar:t}=e;return a.createElement("div",{className:re.expandButton,title:(0,u.I)({id:"theme.docs.sidebar.expandButtonTitle",message:"Expand sidebar",description:"The ARIA label and title attribute for expand button of doc sidebar"}),"aria-label":(0,u.I)({id:"theme.docs.sidebar.expandButtonAriaLabel",message:"Expand sidebar",description:"The ARIA label and title attribute for expand button of doc sidebar"}),tabIndex:0,role:"button",onKeyDown:t,onClick:t},a.createElement(S,{className:re.expandButtonIcon}))}const ie={docSidebarContainer:"docSidebarContainer_b6E3",docSidebarContainerHidden:"docSidebarContainerHidden_b3ry",sidebarViewport:"sidebarViewport_Xe31"};function se(e){let{children:t}=e;const n=(0,d.V)();return a.createElement(a.Fragment,{key:n?.name??"noSidebar"},t)}function de(e){let{sidebar:t,hiddenSidebarContainer:n,setHiddenSidebarContainer:l}=e;const{pathname:c}=(0,g.TH)(),[i,s]=(0,a.useState)(!1),d=(0,a.useCallback)((()=>{i&&s(!1),!i&&(0,f.n)()&&s(!0),l((e=>!e))}),[l,i]);return a.createElement("aside",{className:(0,o.Z)(r.k.docs.docSidebarContainer,ie.docSidebarContainer,n&&ie.docSidebarContainerHidden),onTransitionEnd:e=>{e.currentTarget.classList.contains(ie.docSidebarContainer)&&n&&s(!0)}},a.createElement(se,null,a.createElement("div",{className:(0,o.Z)(ie.sidebarViewport,i&&ie.sidebarViewportHidden)},a.createElement(le,{sidebar:t,path:c,onCollapse:d,isHidden:i}),i&&a.createElement(ce,{toggleSidebar:d}))))}const me={docMainContainer:"docMainContainer_gTbr",docMainContainerEnhanced:"docMainContainerEnhanced_Uz_u",docItemWrapperEnhanced:"docItemWrapperEnhanced_czyv"};function ue(e){let{hiddenSidebarContainer:t,children:n}=e;const l=(0,d.V)();return a.createElement("main",{className:(0,o.Z)(me.docMainContainer,(t||!l)&&me.docMainContainerEnhanced)},a.createElement("div",{className:(0,o.Z)("container padding-top--md padding-bottom--lg",me.docItemWrapper,t&&me.docItemWrapperEnhanced)},n))}const be={docPage:"docPage__5DB",docsWrapper:"docsWrapper_BCFX","themedComponent--light":"themedComponent--light_NU7w"};function pe(e){let{children:t}=e;const n=(0,d.V)(),[o,l]=(0,a.useState)(!1);return a.createElement(m.Z,{wrapperClassName:be.docsWrapper},a.createElement(E,null),a.createElement("div",{className:be.docPage},n&&a.createElement(de,{sidebar:n.items,hiddenSidebarContainer:o,setHiddenSidebarContainer:l}),a.createElement(ue,{hiddenSidebarContainer:o},t)))}var he=n(4972),Ee=n(197);function fe(e){const{versionMetadata:t}=e;return a.createElement(a.Fragment,null,a.createElement(Ee.Z,{version:t.version,tag:(0,c.os)(t.pluginId,t.version)}),a.createElement(l.d,null,t.noIndex&&a.createElement("meta",{name:"robots",content:"noindex, nofollow"})))}function ge(e){const{versionMetadata:t}=e,n=(0,i.hI)(e);if(!n)return a.createElement(he.default,null);const{docElement:c,sidebarName:m,sidebarItems:u}=n;return a.createElement(a.Fragment,null,a.createElement(fe,e),a.createElement(l.FG,{className:(0,o.Z)(r.k.wrapper.docsPages,r.k.page.docsDocPage,e.versionMetadata.className)},a.createElement(s.q,{version:t},a.createElement(d.b,{name:m,items:u},a.createElement(pe,null,c)))))}},4972:(e,t,n)=>{n.r(t),n.d(t,{default:()=>c});var a=n(7294),o=n(5999),l=n(1944),r=n(7961);function c(){return a.createElement(a.Fragment,null,a.createElement(l.d,{title:(0,o.I)({id:"theme.NotFound.title",message:"Page Not Found"})}),a.createElement(r.Z,null,a.createElement("main",{className:"container margin-vert--xl"},a.createElement("div",{className:"row"},a.createElement("div",{className:"col col--6 col--offset-3"},a.createElement("h1",{className:"hero__title"},a.createElement(o.Z,{id:"theme.NotFound.title",description:"The title of the 404 page"},"Page Not Found")),a.createElement("p",null,a.createElement(o.Z,{id:"theme.NotFound.p1",description:"The first paragraph of the 404 page"},"We could not find what you were looking for.")),a.createElement("p",null,a.createElement(o.Z,{id:"theme.NotFound.p2",description:"The 2nd paragraph of the 404 page"},"Please contact the owner of the site that linked you to the original URL and let them know their link is broken.")))))))}},4477:(e,t,n)=>{n.d(t,{E:()=>c,q:()=>r});var a=n(7294),o=n(902);const l=a.createContext(null);function r(e){let{children:t,version:n}=e;return a.createElement(l.Provider,{value:n},t)}function c(){const e=(0,a.useContext)(l);if(null===e)throw new o.i6("DocsVersionProvider");return e}}}]); \ No newline at end of file diff --git a/docs/dev/assets/js/4d9df5b1.b04a94c6.js b/docs/dev/assets/js/4d9df5b1.b04a94c6.js new file mode 100644 index 00000000..4fd13ae7 --- /dev/null +++ b/docs/dev/assets/js/4d9df5b1.b04a94c6.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs=self.webpackChunkdocs||[]).push([[4818],{3905:(e,t,n)=>{n.d(t,{Zo:()=>u,kt:()=>d});var r=n(7294);function l(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function i(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function a(e){for(var t=1;t=0||(l[n]=e[n]);return l}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(l[n]=e[n])}return l}var s=r.createContext({}),c=function(e){var t=r.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):a(a({},t),e)),n},u=function(e){var t=c(e.components);return r.createElement(s.Provider,{value:t},e.children)},p="mdxType",m={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},f=r.forwardRef((function(e,t){var n=e.components,l=e.mdxType,i=e.originalType,s=e.parentName,u=o(e,["components","mdxType","originalType","parentName"]),p=c(n),f=l,d=p["".concat(s,".").concat(f)]||p[f]||m[f]||i;return n?r.createElement(d,a(a({ref:t},u),{},{components:n})):r.createElement(d,a({ref:t},u))}));function d(e,t){var n=arguments,l=t&&t.mdxType;if("string"==typeof e||l){var i=n.length,a=new Array(i);a[0]=f;var o={};for(var s in t)hasOwnProperty.call(t,s)&&(o[s]=t[s]);o.originalType=e,o[p]="string"==typeof e?e:l,a[1]=o;for(var c=2;c{n.r(t),n.d(t,{assets:()=>s,contentTitle:()=>a,default:()=>m,frontMatter:()=>i,metadata:()=>o,toc:()=>c});var r=n(7462),l=(n(7294),n(3905));const i={},a='SQL Function - "SPLICE"',o={unversionedId:"sql-syntax/functions/list-map/splice",id:"sql-syntax/functions/list-map/splice",title:'SQL Function - "SPLICE"',description:'The "SPLICE" function in GlueSQL is used to modify elements in a list. It allows you to remove or replace elements in a list. The syntax for the "SPLICE" function is as follows:',source:"@site/docs/sql-syntax/functions/list-map/splice.md",sourceDirName:"sql-syntax/functions/list-map",slug:"/sql-syntax/functions/list-map/splice",permalink:"/docs/dev/sql-syntax/functions/list-map/splice",draft:!1,tags:[],version:"current",frontMatter:{},sidebar:"autoSidebar",previous:{title:"PREPEND",permalink:"/docs/dev/sql-syntax/functions/list-map/prepend"},next:{title:"CALC_DISTANCE",permalink:"/docs/dev/sql-syntax/functions/geometry/calc-distance"}},s={},c=[{value:"Example",id:"example",level:2},{value:"Error",id:"error",level:2}],u={toc:c},p="wrapper";function m(e){let{components:t,...n}=e;return(0,l.kt)(p,(0,r.Z)({},u,n,{components:t,mdxType:"MDXLayout"}),(0,l.kt)("h1",{id:"sql-function---splice"},'SQL Function - "SPLICE"'),(0,l.kt)("p",null,'The "SPLICE" function in GlueSQL is used to modify elements in a list. It allows you to remove or replace elements in a list. The syntax for the "SPLICE" function is as follows:'),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-sql"},"SPLICE(list1, start_index, end_index [, list2])\n")),(0,l.kt)("ul",null,(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"list1"),": The list you want to modify."),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"start_index"),": The position at which you want to start the modification."),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"end_index"),": The exclusive end position for the modification."),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"list2")," (optional): A list of elements to insert in place of the removed elements.")),(0,l.kt)("h2",{id:"example"},"Example"),(0,l.kt)("p",null,'We can use the "SPLICE" function to modify the list in various ways:'),(0,l.kt)("ol",null,(0,l.kt)("li",{parentName:"ol"},"Remove elements from a list:")),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-sql"},"-- Remove elements at 1, 2 from the list '[1, 2, 3]'\nSELECT SPLICE(CAST('[1, 2, 3, 4, 5]' AS List), 1, 3) AS result;\n-- Output: '[1, 4, 5]'\n")),(0,l.kt)("ol",{start:2},(0,l.kt)("li",{parentName:"ol"},"Replace elements in a list:")),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-sql"},"-- Replace elements at 1, 2, 3 with '[100, 99]' in the list '[1, 2, 3, 4, 5]'\nSELECT SPLICE(CAST('[1, 2, 3, 4, 5]' AS List), 1, 4, CAST('[100, 99]' AS List)) AS result;\n-- Output: '[1, 100, 99, 5]'\n")),(0,l.kt)("ol",{start:3},(0,l.kt)("li",{parentName:"ol"},"'start' is processed so that it is not less than 0 and 'end' is not greater than the length of the list.")),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-sql"},"SELECT SPLICE(CAST('[1, 2, 3]' AS List), -1, 2, CAST('[100, 99]' AS List)) AS result;\n-- Output: '[100, 99, 3]'\n")),(0,l.kt)("h2",{id:"error"},"Error"),(0,l.kt)("p",null,'If you use the "SPLICE" function with invalid inputs, it will result in an error. For example:'),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-sql"},"-- Using SPLICE on a non-list value will result in an error.\nSELECT SPLICE(3, 1, 2) AS result;\n-- EvaluateError::ListTypeRequired\n")))}m.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/dev/assets/js/6048.b8e3eb8d.js b/docs/dev/assets/js/6048.b8e3eb8d.js deleted file mode 100644 index b5ee7ff3..00000000 --- a/docs/dev/assets/js/6048.b8e3eb8d.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkdocs=self.webpackChunkdocs||[]).push([[6048],{9058:(e,t,a)=>{a.d(t,{Z:()=>h});var l=a(7294),r=a(6010),n=a(7961),o=a(7524),s=a(9960),i=a(5999);const m={sidebar:"sidebar_re4s",sidebarItemTitle:"sidebarItemTitle_pO2u",sidebarItemList:"sidebarItemList_Yudw",sidebarItem:"sidebarItem__DBe",sidebarItemLink:"sidebarItemLink_mo7H",sidebarItemLinkActive:"sidebarItemLinkActive_I1ZP"};function c(e){let{sidebar:t}=e;return l.createElement("aside",{className:"col col--3"},l.createElement("nav",{className:(0,r.Z)(m.sidebar,"thin-scrollbar"),"aria-label":(0,i.I)({id:"theme.blog.sidebar.navAriaLabel",message:"Blog recent posts navigation",description:"The ARIA label for recent posts in the blog sidebar"})},l.createElement("div",{className:(0,r.Z)(m.sidebarItemTitle,"margin-bottom--md")},t.title),l.createElement("ul",{className:(0,r.Z)(m.sidebarItemList,"clean-list")},t.items.map((e=>l.createElement("li",{key:e.permalink,className:m.sidebarItem},l.createElement(s.Z,{isNavLink:!0,to:e.permalink,className:m.sidebarItemLink,activeClassName:m.sidebarItemLinkActive},e.title)))))))}var u=a(3102);function d(e){let{sidebar:t}=e;return l.createElement("ul",{className:"menu__list"},t.items.map((e=>l.createElement("li",{key:e.permalink,className:"menu__list-item"},l.createElement(s.Z,{isNavLink:!0,to:e.permalink,className:"menu__link",activeClassName:"menu__link--active"},e.title)))))}function g(e){return l.createElement(u.Zo,{component:d,props:e})}function p(e){let{sidebar:t}=e;const a=(0,o.i)();return t?.items.length?"mobile"===a?l.createElement(g,{sidebar:t}):l.createElement(c,{sidebar:t}):null}function h(e){const{sidebar:t,toc:a,children:o,...s}=e,i=t&&t.items.length>0;return l.createElement(n.Z,s,l.createElement("div",{className:"container margin-vert--lg"},l.createElement("div",{className:"row"},l.createElement(p,{sidebar:t}),l.createElement("main",{className:(0,r.Z)("col",{"col--7":i,"col--9 col--offset-1":!i}),itemScope:!0,itemType:"http://schema.org/Blog"},o),a&&l.createElement("div",{className:"col col--2"},a))))}},390:(e,t,a)=>{a.d(t,{Z:()=>A});var l=a(7294),r=a(6010),n=a(9460),o=a(4996);function s(e){let{children:t,className:a}=e;const{frontMatter:r,assets:s}=(0,n.C)(),{withBaseUrl:i}=(0,o.C)(),m=s.image??r.image;return l.createElement("article",{className:a,itemProp:"blogPost",itemScope:!0,itemType:"http://schema.org/BlogPosting"},m&&l.createElement("meta",{itemProp:"image",content:i(m,{absolute:!0})}),t)}var i=a(9960);const m={title:"title_f1Hy"};function c(e){let{className:t}=e;const{metadata:a,isBlogPostPage:o}=(0,n.C)(),{permalink:s,title:c}=a,u=o?"h1":"h2";return l.createElement(u,{className:(0,r.Z)(m.title,t),itemProp:"headline"},o?c:l.createElement(i.Z,{itemProp:"url",to:s},c))}var u=a(5999),d=a(8824);const g={container:"container_mt6G"};function p(e){let{readingTime:t}=e;const a=function(){const{selectMessage:e}=(0,d.c)();return t=>{const a=Math.ceil(t);return e(a,(0,u.I)({id:"theme.blog.post.readingTime.plurals",description:'Pluralized label for "{readingTime} min read". Use as much plural forms (separated by "|") as your language support (see https://www.unicode.org/cldr/cldr-aux/charts/34/supplemental/language_plural_rules.html)',message:"One min read|{readingTime} min read"},{readingTime:a}))}}();return l.createElement(l.Fragment,null,a(t))}function h(e){let{date:t,formattedDate:a}=e;return l.createElement("time",{dateTime:t,itemProp:"datePublished"},a)}function E(){return l.createElement(l.Fragment,null," \xb7 ")}function b(e){let{className:t}=e;const{metadata:a}=(0,n.C)(),{date:o,formattedDate:s,readingTime:i}=a;return l.createElement("div",{className:(0,r.Z)(g.container,"margin-vert--md",t)},l.createElement(h,{date:o,formattedDate:s}),void 0!==i&&l.createElement(l.Fragment,null,l.createElement(E,null),l.createElement(p,{readingTime:i})))}function f(e){return e.href?l.createElement(i.Z,e):l.createElement(l.Fragment,null,e.children)}function v(e){let{author:t,className:a}=e;const{name:n,title:o,url:s,imageURL:i,email:m}=t,c=s||m&&`mailto:${m}`||void 0;return l.createElement("div",{className:(0,r.Z)("avatar margin-bottom--sm",a)},i&&l.createElement(f,{href:c,className:"avatar__photo-link"},l.createElement("img",{className:"avatar__photo",src:i,alt:n})),n&&l.createElement("div",{className:"avatar__intro",itemProp:"author",itemScope:!0,itemType:"https://schema.org/Person"},l.createElement("div",{className:"avatar__name"},l.createElement(f,{href:c,itemProp:"url"},l.createElement("span",{itemProp:"name"},n))),o&&l.createElement("small",{className:"avatar__subtitle",itemProp:"description"},o)))}const P={authorCol:"authorCol_Hf19",imageOnlyAuthorRow:"imageOnlyAuthorRow_pa_O",imageOnlyAuthorCol:"imageOnlyAuthorCol_G86a"};function N(e){let{className:t}=e;const{metadata:{authors:a},assets:o}=(0,n.C)();if(0===a.length)return null;const s=a.every((e=>{let{name:t}=e;return!t}));return l.createElement("div",{className:(0,r.Z)("margin-top--md margin-bottom--sm",s?P.imageOnlyAuthorRow:"row",t)},a.map(((e,t)=>l.createElement("div",{className:(0,r.Z)(!s&&"col col--6",s?P.imageOnlyAuthorCol:P.authorCol),key:t},l.createElement(v,{author:{...e,imageURL:o.authorsImageUrls[t]??e.imageURL}})))))}function _(){return l.createElement("header",null,l.createElement(c,null),l.createElement(b,null),l.createElement(N,null))}var Z=a(8780),k=a(1506);function I(e){let{children:t,className:a}=e;const{isBlogPostPage:o}=(0,n.C)();return l.createElement("div",{id:o?Z.blogPostContainerID:void 0,className:(0,r.Z)("markdown",a),itemProp:"articleBody"},l.createElement(k.Z,null,t))}var C=a(4881),w=a(1526),T=a(7462);function y(){return l.createElement("b",null,l.createElement(u.Z,{id:"theme.blog.post.readMore",description:"The label used in blog post item excerpts to link to full blog posts"},"Read More"))}function F(e){const{blogPostTitle:t,...a}=e;return l.createElement(i.Z,(0,T.Z)({"aria-label":(0,u.I)({message:"Read more about {title}",id:"theme.blog.post.readMoreLabel",description:"The ARIA label for the link to full blog posts from excerpts"},{title:t})},a),l.createElement(y,null))}const L={blogPostFooterDetailsFull:"blogPostFooterDetailsFull_mRVl"};function B(){const{metadata:e,isBlogPostPage:t}=(0,n.C)(),{tags:a,title:o,editUrl:s,hasTruncateMarker:i}=e,m=!t&&i,c=a.length>0;return c||m||s?l.createElement("footer",{className:(0,r.Z)("row docusaurus-mt-lg",t&&L.blogPostFooterDetailsFull)},c&&l.createElement("div",{className:(0,r.Z)("col",{"col--9":m})},l.createElement(w.Z,{tags:a})),t&&s&&l.createElement("div",{className:"col margin-top--sm"},l.createElement(C.Z,{editUrl:s})),m&&l.createElement("div",{className:(0,r.Z)("col text--right",{"col--3":c})},l.createElement(F,{blogPostTitle:o,to:e.permalink}))):null}function A(e){let{children:t,className:a}=e;const o=function(){const{isBlogPostPage:e}=(0,n.C)();return e?void 0:"margin-bottom--xl"}();return l.createElement(s,{className:(0,r.Z)(o,a)},l.createElement(_,null),l.createElement(I,null,t),l.createElement(B,null))}},9460:(e,t,a)=>{a.d(t,{C:()=>s,n:()=>o});var l=a(7294),r=a(902);const n=l.createContext(null);function o(e){let{children:t,content:a,isBlogPostPage:r=!1}=e;const o=function(e){let{content:t,isBlogPostPage:a}=e;return(0,l.useMemo)((()=>({metadata:t.metadata,frontMatter:t.frontMatter,assets:t.assets,toc:t.toc,isBlogPostPage:a})),[t,a])}({content:a,isBlogPostPage:r});return l.createElement(n.Provider,{value:o},t)}function s(){const e=(0,l.useContext)(n);if(null===e)throw new r.i6("BlogPostProvider");return e}},8824:(e,t,a)=>{a.d(t,{c:()=>m});var l=a(7294),r=a(2263);const n=["zero","one","two","few","many","other"];function o(e){return n.filter((t=>e.includes(t)))}const s={locale:"en",pluralForms:o(["one","other"]),select:e=>1===e?"one":"other"};function i(){const{i18n:{currentLocale:e}}=(0,r.Z)();return(0,l.useMemo)((()=>{try{return function(e){const t=new Intl.PluralRules(e);return{locale:e,pluralForms:o(t.resolvedOptions().pluralCategories),select:e=>t.select(e)}}(e)}catch(t){return console.error(`Failed to use Intl.PluralRules for locale "${e}".\nDocusaurus will fallback to the default (English) implementation.\nError: ${t.message}\n`),s}}),[e])}function m(){const e=i();return{selectMessage:(t,a)=>function(e,t,a){const l=e.split("|");if(1===l.length)return l[0];l.length>a.pluralForms.length&&console.error(`For locale=${a.locale}, a maximum of ${a.pluralForms.length} plural forms are expected (${a.pluralForms.join(",")}), but the message contains ${l.length}: ${e}`);const r=a.select(t),n=a.pluralForms.indexOf(r);return l[Math.min(n,l.length-1)]}(a,t,e)}}}}]); \ No newline at end of file diff --git a/docs/dev/assets/js/6048.fb279e73.js b/docs/dev/assets/js/6048.fb279e73.js new file mode 100644 index 00000000..1ad370ab --- /dev/null +++ b/docs/dev/assets/js/6048.fb279e73.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs=self.webpackChunkdocs||[]).push([[6048],{9058:(e,t,a)=>{a.d(t,{Z:()=>h});var l=a(7294),r=a(6010),n=a(7961),o=a(7524),s=a(9960),i=a(5999);const m={sidebar:"sidebar_re4s",sidebarItemTitle:"sidebarItemTitle_pO2u",sidebarItemList:"sidebarItemList_Yudw",sidebarItem:"sidebarItem__DBe",sidebarItemLink:"sidebarItemLink_mo7H",sidebarItemLinkActive:"sidebarItemLinkActive_I1ZP"};function c(e){let{sidebar:t}=e;return l.createElement("aside",{className:"col col--3"},l.createElement("nav",{className:(0,r.Z)(m.sidebar,"thin-scrollbar"),"aria-label":(0,i.I)({id:"theme.blog.sidebar.navAriaLabel",message:"Blog recent posts navigation",description:"The ARIA label for recent posts in the blog sidebar"})},l.createElement("div",{className:(0,r.Z)(m.sidebarItemTitle,"margin-bottom--md")},t.title),l.createElement("ul",{className:(0,r.Z)(m.sidebarItemList,"clean-list")},t.items.map((e=>l.createElement("li",{key:e.permalink,className:m.sidebarItem},l.createElement(s.Z,{isNavLink:!0,to:e.permalink,className:m.sidebarItemLink,activeClassName:m.sidebarItemLinkActive},e.title)))))))}var u=a(3102);function d(e){let{sidebar:t}=e;return l.createElement("ul",{className:"menu__list"},t.items.map((e=>l.createElement("li",{key:e.permalink,className:"menu__list-item"},l.createElement(s.Z,{isNavLink:!0,to:e.permalink,className:"menu__link",activeClassName:"menu__link--active"},e.title)))))}function g(e){return l.createElement(u.Zo,{component:d,props:e})}function p(e){let{sidebar:t}=e;const a=(0,o.i)();return t?.items.length?"mobile"===a?l.createElement(g,{sidebar:t}):l.createElement(c,{sidebar:t}):null}function h(e){const{sidebar:t,toc:a,children:o,...s}=e,i=t&&t.items.length>0;return l.createElement(n.Z,s,l.createElement("div",{className:"container margin-vert--lg"},l.createElement("div",{className:"row"},l.createElement(p,{sidebar:t}),l.createElement("main",{className:(0,r.Z)("col",{"col--7":i,"col--9 col--offset-1":!i}),itemScope:!0,itemType:"http://schema.org/Blog"},o),a&&l.createElement("div",{className:"col col--2"},a))))}},390:(e,t,a)=>{a.d(t,{Z:()=>A});var l=a(7294),r=a(6010),n=a(9460),o=a(4996);function s(e){let{children:t,className:a}=e;const{frontMatter:r,assets:s,metadata:{description:i}}=(0,n.C)(),{withBaseUrl:m}=(0,o.C)(),c=s.image??r.image,u=r.keywords??[];return l.createElement("article",{className:a,itemProp:"blogPost",itemScope:!0,itemType:"http://schema.org/BlogPosting"},i&&l.createElement("meta",{itemProp:"description",content:i}),c&&l.createElement("link",{itemProp:"image",href:m(c,{absolute:!0})}),u.length>0&&l.createElement("meta",{itemProp:"keywords",content:u.join(",")}),t)}var i=a(9960);const m={title:"title_f1Hy"};function c(e){let{className:t}=e;const{metadata:a,isBlogPostPage:o}=(0,n.C)(),{permalink:s,title:c}=a,u=o?"h1":"h2";return l.createElement(u,{className:(0,r.Z)(m.title,t),itemProp:"headline"},o?c:l.createElement(i.Z,{itemProp:"url",to:s},c))}var u=a(5999),d=a(8824);const g={container:"container_mt6G"};function p(e){let{readingTime:t}=e;const a=function(){const{selectMessage:e}=(0,d.c)();return t=>{const a=Math.ceil(t);return e(a,(0,u.I)({id:"theme.blog.post.readingTime.plurals",description:'Pluralized label for "{readingTime} min read". Use as much plural forms (separated by "|") as your language support (see https://www.unicode.org/cldr/cldr-aux/charts/34/supplemental/language_plural_rules.html)',message:"One min read|{readingTime} min read"},{readingTime:a}))}}();return l.createElement(l.Fragment,null,a(t))}function h(e){let{date:t,formattedDate:a}=e;return l.createElement("time",{dateTime:t,itemProp:"datePublished"},a)}function E(){return l.createElement(l.Fragment,null," \xb7 ")}function b(e){let{className:t}=e;const{metadata:a}=(0,n.C)(),{date:o,formattedDate:s,readingTime:i}=a;return l.createElement("div",{className:(0,r.Z)(g.container,"margin-vert--md",t)},l.createElement(h,{date:o,formattedDate:s}),void 0!==i&&l.createElement(l.Fragment,null,l.createElement(E,null),l.createElement(p,{readingTime:i})))}function f(e){return e.href?l.createElement(i.Z,e):l.createElement(l.Fragment,null,e.children)}function v(e){let{author:t,className:a}=e;const{name:n,title:o,url:s,imageURL:i,email:m}=t,c=s||m&&`mailto:${m}`||void 0;return l.createElement("div",{className:(0,r.Z)("avatar margin-bottom--sm",a)},i&&l.createElement(f,{href:c,className:"avatar__photo-link"},l.createElement("img",{className:"avatar__photo",src:i,alt:n,itemProp:"image"})),n&&l.createElement("div",{className:"avatar__intro",itemProp:"author",itemScope:!0,itemType:"https://schema.org/Person"},l.createElement("div",{className:"avatar__name"},l.createElement(f,{href:c,itemProp:"url"},l.createElement("span",{itemProp:"name"},n))),o&&l.createElement("small",{className:"avatar__subtitle",itemProp:"description"},o)))}const P={authorCol:"authorCol_Hf19",imageOnlyAuthorRow:"imageOnlyAuthorRow_pa_O",imageOnlyAuthorCol:"imageOnlyAuthorCol_G86a"};function N(e){let{className:t}=e;const{metadata:{authors:a},assets:o}=(0,n.C)();if(0===a.length)return null;const s=a.every((e=>{let{name:t}=e;return!t}));return l.createElement("div",{className:(0,r.Z)("margin-top--md margin-bottom--sm",s?P.imageOnlyAuthorRow:"row",t)},a.map(((e,t)=>l.createElement("div",{className:(0,r.Z)(!s&&"col col--6",s?P.imageOnlyAuthorCol:P.authorCol),key:t},l.createElement(v,{author:{...e,imageURL:o.authorsImageUrls[t]??e.imageURL}})))))}function _(){return l.createElement("header",null,l.createElement(c,null),l.createElement(b,null),l.createElement(N,null))}var k=a(8780),Z=a(1506);function I(e){let{children:t,className:a}=e;const{isBlogPostPage:o}=(0,n.C)();return l.createElement("div",{id:o?k.blogPostContainerID:void 0,className:(0,r.Z)("markdown",a),itemProp:"articleBody"},l.createElement(Z.Z,null,t))}var C=a(4881),w=a(1526),y=a(7462);function T(){return l.createElement("b",null,l.createElement(u.Z,{id:"theme.blog.post.readMore",description:"The label used in blog post item excerpts to link to full blog posts"},"Read More"))}function F(e){const{blogPostTitle:t,...a}=e;return l.createElement(i.Z,(0,y.Z)({"aria-label":(0,u.I)({message:"Read more about {title}",id:"theme.blog.post.readMoreLabel",description:"The ARIA label for the link to full blog posts from excerpts"},{title:t})},a),l.createElement(T,null))}const L={blogPostFooterDetailsFull:"blogPostFooterDetailsFull_mRVl"};function B(){const{metadata:e,isBlogPostPage:t}=(0,n.C)(),{tags:a,title:o,editUrl:s,hasTruncateMarker:i}=e,m=!t&&i,c=a.length>0;return c||m||s?l.createElement("footer",{className:(0,r.Z)("row docusaurus-mt-lg",t&&L.blogPostFooterDetailsFull)},c&&l.createElement("div",{className:(0,r.Z)("col",{"col--9":m})},l.createElement(w.Z,{tags:a})),t&&s&&l.createElement("div",{className:"col margin-top--sm"},l.createElement(C.Z,{editUrl:s})),m&&l.createElement("div",{className:(0,r.Z)("col text--right",{"col--3":c})},l.createElement(F,{blogPostTitle:o,to:e.permalink}))):null}function A(e){let{children:t,className:a}=e;const o=function(){const{isBlogPostPage:e}=(0,n.C)();return e?void 0:"margin-bottom--xl"}();return l.createElement(s,{className:(0,r.Z)(o,a)},l.createElement(_,null),l.createElement(I,null,t),l.createElement(B,null))}},9460:(e,t,a)=>{a.d(t,{C:()=>s,n:()=>o});var l=a(7294),r=a(902);const n=l.createContext(null);function o(e){let{children:t,content:a,isBlogPostPage:r=!1}=e;const o=function(e){let{content:t,isBlogPostPage:a}=e;return(0,l.useMemo)((()=>({metadata:t.metadata,frontMatter:t.frontMatter,assets:t.assets,toc:t.toc,isBlogPostPage:a})),[t,a])}({content:a,isBlogPostPage:r});return l.createElement(n.Provider,{value:o},t)}function s(){const e=(0,l.useContext)(n);if(null===e)throw new r.i6("BlogPostProvider");return e}},8824:(e,t,a)=>{a.d(t,{c:()=>m});var l=a(7294),r=a(2263);const n=["zero","one","two","few","many","other"];function o(e){return n.filter((t=>e.includes(t)))}const s={locale:"en",pluralForms:o(["one","other"]),select:e=>1===e?"one":"other"};function i(){const{i18n:{currentLocale:e}}=(0,r.Z)();return(0,l.useMemo)((()=>{try{return function(e){const t=new Intl.PluralRules(e);return{locale:e,pluralForms:o(t.resolvedOptions().pluralCategories),select:e=>t.select(e)}}(e)}catch(t){return console.error(`Failed to use Intl.PluralRules for locale "${e}".\nDocusaurus will fallback to the default (English) implementation.\nError: ${t.message}\n`),s}}),[e])}function m(){const e=i();return{selectMessage:(t,a)=>function(e,t,a){const l=e.split("|");if(1===l.length)return l[0];l.length>a.pluralForms.length&&console.error(`For locale=${a.locale}, a maximum of ${a.pluralForms.length} plural forms are expected (${a.pluralForms.join(",")}), but the message contains ${l.length}: ${e}`);const r=a.select(t),n=a.pluralForms.indexOf(r);return l[Math.min(n,l.length-1)]}(a,t,e)}}}}]); \ No newline at end of file diff --git a/docs/dev/assets/js/77cc432a.45eddf85.js b/docs/dev/assets/js/77cc432a.45eddf85.js new file mode 100644 index 00000000..66319f8c --- /dev/null +++ b/docs/dev/assets/js/77cc432a.45eddf85.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs=self.webpackChunkdocs||[]).push([[3159],{3905:(e,t,n)=>{n.d(t,{Zo:()=>c,kt:()=>f});var r=n(7294);function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function l(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function o(e){for(var t=1;t=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var i=r.createContext({}),s=function(e){var t=r.useContext(i),n=t;return e&&(n="function"==typeof e?e(t):o(o({},t),e)),n},c=function(e){var t=s(e.components);return r.createElement(i.Provider,{value:t},e.children)},u="mdxType",m={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},d=r.forwardRef((function(e,t){var n=e.components,a=e.mdxType,l=e.originalType,i=e.parentName,c=p(e,["components","mdxType","originalType","parentName"]),u=s(n),d=a,f=u["".concat(i,".").concat(d)]||u[d]||m[d]||l;return n?r.createElement(f,o(o({ref:t},c),{},{components:n})):r.createElement(f,o({ref:t},c))}));function f(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var l=n.length,o=new Array(l);o[0]=d;var p={};for(var i in t)hasOwnProperty.call(t,i)&&(p[i]=t[i]);p.originalType=e,p[u]="string"==typeof e?e:a,o[1]=p;for(var s=2;s{n.r(t),n.d(t,{assets:()=>i,contentTitle:()=>o,default:()=>m,frontMatter:()=>l,metadata:()=>p,toc:()=>s});var r=n(7462),a=(n(7294),n(3905));const l={},o="PREPEND",p={unversionedId:"sql-syntax/functions/list-map/prepend",id:"sql-syntax/functions/list-map/prepend",title:"PREPEND",description:"The PREPEND function in SQL is used to prepend an element to a list.",source:"@site/docs/sql-syntax/functions/list-map/prepend.md",sourceDirName:"sql-syntax/functions/list-map",slug:"/sql-syntax/functions/list-map/prepend",permalink:"/docs/dev/sql-syntax/functions/list-map/prepend",draft:!1,tags:[],version:"current",frontMatter:{},sidebar:"autoSidebar",previous:{title:"CONCAT",permalink:"/docs/dev/sql-syntax/functions/list-map/concat"},next:{title:'SQL Function - "SPLICE"',permalink:"/docs/dev/sql-syntax/functions/list-map/splice"}},i={},s=[{value:"Syntax",id:"syntax",level:2},{value:"Examples",id:"examples",level:2}],c={toc:s},u="wrapper";function m(e){let{components:t,...n}=e;return(0,a.kt)(u,(0,r.Z)({},c,n,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h1",{id:"prepend"},"PREPEND"),(0,a.kt)("p",null,"The ",(0,a.kt)("inlineCode",{parentName:"p"},"PREPEND")," function in SQL is used to prepend an element to a list."),(0,a.kt)("h2",{id:"syntax"},"Syntax"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sql"},"PREPEND(list, element)\n")),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"list"),": The list to which you want to prepend the element."),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"element"),": The element that you want to prepend to the list.")),(0,a.kt)("h2",{id:"examples"},"Examples"),(0,a.kt)("p",null,"First, create a table named ",(0,a.kt)("inlineCode",{parentName:"p"},"Prepend")," with columns for the list, an integer element, and a text element:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sql"},"CREATE TABLE Prepend (\n id INTEGER,\n items LIST,\n element INTEGER,\n element2 TEXT\n);\n")),(0,a.kt)("p",null,"Insert some data into the ",(0,a.kt)("inlineCode",{parentName:"p"},"Prepend")," table:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sql"},"INSERT INTO Prepend VALUES\n(1, '[1, 2, 3]', 0, 'Foo');\n")),(0,a.kt)("p",null,"Use the ",(0,a.kt)("inlineCode",{parentName:"p"},"PREPEND")," function to prepend the integer element to the list:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sql"},"SELECT PREPEND(items, element) AS myprepend FROM Prepend;\n")),(0,a.kt)("p",null,"Use the ",(0,a.kt)("inlineCode",{parentName:"p"},"PREPEND")," function to prepend the text element to the list:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sql"},"SELECT PREPEND(items, element2) AS myprepend FROM Prepend;\n")),(0,a.kt)("p",null,"The ",(0,a.kt)("inlineCode",{parentName:"p"},"PREPEND")," function requires a list as the first parameter. If you try to use it with a non-list value, an error will occur:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sql"},"SELECT PREPEND(element, element2) AS myprepend FROM Prepend;\n")),(0,a.kt)("p",null,"You can also use the ",(0,a.kt)("inlineCode",{parentName:"p"},"PREPEND")," function when inserting data into a table. First, create a table named ",(0,a.kt)("inlineCode",{parentName:"p"},"Foo")," with a column for the list:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sql"},"CREATE TABLE Foo (\n elements LIST\n);\n")),(0,a.kt)("p",null,"Then, insert data into the ",(0,a.kt)("inlineCode",{parentName:"p"},"Foo")," table using the ",(0,a.kt)("inlineCode",{parentName:"p"},"PREPEND")," function:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sql"},"INSERT INTO Foo VALUES (PREPEND(CAST('[1, 2, 3]' AS LIST), 0));\n")),(0,a.kt)("p",null,"Finally, retrieve the list from the ",(0,a.kt)("inlineCode",{parentName:"p"},"Foo")," table:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sql"},"SELECT elements AS myprepend FROM Foo;\n")))}m.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/dev/assets/js/77cc432a.70485db0.js b/docs/dev/assets/js/77cc432a.70485db0.js deleted file mode 100644 index 1a36665d..00000000 --- a/docs/dev/assets/js/77cc432a.70485db0.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkdocs=self.webpackChunkdocs||[]).push([[3159],{3905:(e,t,n)=>{n.d(t,{Zo:()=>c,kt:()=>f});var r=n(7294);function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function l(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function o(e){for(var t=1;t=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var i=r.createContext({}),s=function(e){var t=r.useContext(i),n=t;return e&&(n="function"==typeof e?e(t):o(o({},t),e)),n},c=function(e){var t=s(e.components);return r.createElement(i.Provider,{value:t},e.children)},u="mdxType",m={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},d=r.forwardRef((function(e,t){var n=e.components,a=e.mdxType,l=e.originalType,i=e.parentName,c=p(e,["components","mdxType","originalType","parentName"]),u=s(n),d=a,f=u["".concat(i,".").concat(d)]||u[d]||m[d]||l;return n?r.createElement(f,o(o({ref:t},c),{},{components:n})):r.createElement(f,o({ref:t},c))}));function f(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var l=n.length,o=new Array(l);o[0]=d;var p={};for(var i in t)hasOwnProperty.call(t,i)&&(p[i]=t[i]);p.originalType=e,p[u]="string"==typeof e?e:a,o[1]=p;for(var s=2;s{n.r(t),n.d(t,{assets:()=>i,contentTitle:()=>o,default:()=>m,frontMatter:()=>l,metadata:()=>p,toc:()=>s});var r=n(7462),a=(n(7294),n(3905));const l={},o="PREPEND",p={unversionedId:"sql-syntax/functions/list-map/prepend",id:"sql-syntax/functions/list-map/prepend",title:"PREPEND",description:"The PREPEND function in SQL is used to prepend an element to a list.",source:"@site/docs/sql-syntax/functions/list-map/prepend.md",sourceDirName:"sql-syntax/functions/list-map",slug:"/sql-syntax/functions/list-map/prepend",permalink:"/docs/dev/sql-syntax/functions/list-map/prepend",draft:!1,tags:[],version:"current",frontMatter:{},sidebar:"autoSidebar",previous:{title:"CONCAT",permalink:"/docs/dev/sql-syntax/functions/list-map/concat"},next:{title:"CALC_DISTANCE",permalink:"/docs/dev/sql-syntax/functions/geometry/calc-distance"}},i={},s=[{value:"Syntax",id:"syntax",level:2},{value:"Examples",id:"examples",level:2}],c={toc:s},u="wrapper";function m(e){let{components:t,...n}=e;return(0,a.kt)(u,(0,r.Z)({},c,n,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h1",{id:"prepend"},"PREPEND"),(0,a.kt)("p",null,"The ",(0,a.kt)("inlineCode",{parentName:"p"},"PREPEND")," function in SQL is used to prepend an element to a list."),(0,a.kt)("h2",{id:"syntax"},"Syntax"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sql"},"PREPEND(list, element)\n")),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"list"),": The list to which you want to prepend the element."),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"element"),": The element that you want to prepend to the list.")),(0,a.kt)("h2",{id:"examples"},"Examples"),(0,a.kt)("p",null,"First, create a table named ",(0,a.kt)("inlineCode",{parentName:"p"},"Prepend")," with columns for the list, an integer element, and a text element:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sql"},"CREATE TABLE Prepend (\n id INTEGER,\n items LIST,\n element INTEGER,\n element2 TEXT\n);\n")),(0,a.kt)("p",null,"Insert some data into the ",(0,a.kt)("inlineCode",{parentName:"p"},"Prepend")," table:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sql"},"INSERT INTO Prepend VALUES\n(1, '[1, 2, 3]', 0, 'Foo');\n")),(0,a.kt)("p",null,"Use the ",(0,a.kt)("inlineCode",{parentName:"p"},"PREPEND")," function to prepend the integer element to the list:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sql"},"SELECT PREPEND(items, element) AS myprepend FROM Prepend;\n")),(0,a.kt)("p",null,"Use the ",(0,a.kt)("inlineCode",{parentName:"p"},"PREPEND")," function to prepend the text element to the list:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sql"},"SELECT PREPEND(items, element2) AS myprepend FROM Prepend;\n")),(0,a.kt)("p",null,"The ",(0,a.kt)("inlineCode",{parentName:"p"},"PREPEND")," function requires a list as the first parameter. If you try to use it with a non-list value, an error will occur:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sql"},"SELECT PREPEND(element, element2) AS myprepend FROM Prepend;\n")),(0,a.kt)("p",null,"You can also use the ",(0,a.kt)("inlineCode",{parentName:"p"},"PREPEND")," function when inserting data into a table. First, create a table named ",(0,a.kt)("inlineCode",{parentName:"p"},"Foo")," with a column for the list:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sql"},"CREATE TABLE Foo (\n elements LIST\n);\n")),(0,a.kt)("p",null,"Then, insert data into the ",(0,a.kt)("inlineCode",{parentName:"p"},"Foo")," table using the ",(0,a.kt)("inlineCode",{parentName:"p"},"PREPEND")," function:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sql"},"INSERT INTO Foo VALUES (PREPEND(CAST('[1, 2, 3]' AS LIST), 0));\n")),(0,a.kt)("p",null,"Finally, retrieve the list from the ",(0,a.kt)("inlineCode",{parentName:"p"},"Foo")," table:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sql"},"SELECT elements AS myprepend FROM Foo;\n")))}m.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/dev/assets/js/935f2afb.6ae40558.js b/docs/dev/assets/js/935f2afb.6ae40558.js deleted file mode 100644 index 8abbb08e..00000000 --- a/docs/dev/assets/js/935f2afb.6ae40558.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkdocs=self.webpackChunkdocs||[]).push([[53],{1109:t=>{t.exports=JSON.parse('{"pluginId":"default","version":"current","label":"Next","banner":null,"badge":false,"noIndex":false,"className":"docs-version-current","isLast":true,"docsSidebars":{"autoSidebar":[{"type":"link","label":"Introduction","href":"/docs/dev/","docId":"index"},{"type":"category","label":"Getting Started","collapsible":true,"collapsed":false,"items":[{"type":"link","label":"Rust","href":"/docs/dev/getting-started/rust","docId":"getting-started/rust"},{"type":"link","label":"JavaScript (Web Browser)","href":"/docs/dev/getting-started/javascript-web","docId":"getting-started/javascript-web"},{"type":"link","label":"Node.js","href":"/docs/dev/getting-started/nodejs","docId":"getting-started/nodejs"},{"type":"link","label":"Command-Line Interface","href":"/docs/dev/getting-started/cli","docId":"getting-started/cli"}]},{"type":"category","label":"SQL Syntax","collapsible":true,"collapsed":false,"items":[{"type":"link","label":"Introduction","href":"/docs/dev/sql-syntax/intro","docId":"sql-syntax/intro"},{"type":"category","label":"Statements","collapsible":true,"collapsed":true,"items":[{"type":"category","label":"Querying","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"WHERE","href":"/docs/dev/sql-syntax/statements/querying/where","docId":"sql-syntax/statements/querying/where"},{"type":"link","label":"JOIN","href":"/docs/dev/sql-syntax/statements/querying/join","docId":"sql-syntax/statements/querying/join"},{"type":"link","label":"LIMIT & OFFSET","href":"/docs/dev/sql-syntax/statements/querying/limit","docId":"sql-syntax/statements/querying/limit"},{"type":"link","label":"Aggregation","href":"/docs/dev/sql-syntax/statements/querying/aggregation","docId":"sql-syntax/statements/querying/aggregation"},{"type":"link","label":"Schemaless Data","href":"/docs/dev/sql-syntax/statements/querying/schemaless","docId":"sql-syntax/statements/querying/schemaless"}]},{"type":"category","label":"Data definition","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"CREATE TABLE","href":"/docs/dev/sql-syntax/statements/data-definition/create-table","docId":"sql-syntax/statements/data-definition/create-table"},{"type":"link","label":"DROP TABLE","href":"/docs/dev/sql-syntax/statements/data-definition/drop-table","docId":"sql-syntax/statements/data-definition/drop-table"},{"type":"link","label":"CREATE INDEX","href":"/docs/dev/sql-syntax/statements/data-definition/create-index","docId":"sql-syntax/statements/data-definition/create-index"},{"type":"link","label":"DROP INDEX","href":"/docs/dev/sql-syntax/statements/data-definition/drop-index","docId":"sql-syntax/statements/data-definition/drop-index"},{"type":"link","label":"ALTER TABLE","href":"/docs/dev/sql-syntax/statements/data-definition/alter-table","docId":"sql-syntax/statements/data-definition/alter-table"}]},{"type":"category","label":"Data manipulation","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"INSERT","href":"/docs/dev/sql-syntax/statements/data-manipulation/insert","docId":"sql-syntax/statements/data-manipulation/insert"},{"type":"link","label":"UPDATE","href":"/docs/dev/sql-syntax/statements/data-manipulation/update","docId":"sql-syntax/statements/data-manipulation/update"},{"type":"link","label":"DELETE","href":"/docs/dev/sql-syntax/statements/data-manipulation/delete","docId":"sql-syntax/statements/data-manipulation/delete"}]},{"type":"link","label":"Transaction","href":"/docs/dev/sql-syntax/statements/transaction","docId":"sql-syntax/statements/transaction"},{"type":"category","label":"Metadata","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"SHOW TABLES","href":"/docs/dev/sql-syntax/statements/metadata/show-tables","docId":"sql-syntax/statements/metadata/show-tables"},{"type":"link","label":"Data Dictionary","href":"/docs/dev/sql-syntax/statements/metadata/data-dictionary","docId":"sql-syntax/statements/metadata/data-dictionary"}]}]},{"type":"category","label":"Data types","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"BOOLEAN","href":"/docs/dev/sql-syntax/data-types/boolean","docId":"sql-syntax/data-types/boolean"},{"type":"link","label":"Integer Types","href":"/docs/dev/sql-syntax/data-types/integers","docId":"sql-syntax/data-types/integers"},{"type":"link","label":"FLOAT","href":"/docs/dev/sql-syntax/data-types/float","docId":"sql-syntax/data-types/float"},{"type":"link","label":"TEXT","href":"/docs/dev/sql-syntax/data-types/text","docId":"sql-syntax/data-types/text"},{"type":"link","label":"DECIMAL","href":"/docs/dev/sql-syntax/data-types/decimal","docId":"sql-syntax/data-types/decimal"},{"type":"link","label":"DATE","href":"/docs/dev/sql-syntax/data-types/date","docId":"sql-syntax/data-types/date"},{"type":"link","label":"TIMESTAMP","href":"/docs/dev/sql-syntax/data-types/timestamp","docId":"sql-syntax/data-types/timestamp"},{"type":"link","label":"TIME","href":"/docs/dev/sql-syntax/data-types/time","docId":"sql-syntax/data-types/time"},{"type":"link","label":"INTERVAL","href":"/docs/dev/sql-syntax/data-types/interval","docId":"sql-syntax/data-types/interval"},{"type":"link","label":"LIST","href":"/docs/dev/sql-syntax/data-types/list","docId":"sql-syntax/data-types/list"},{"type":"link","label":"MAP","href":"/docs/dev/sql-syntax/data-types/map","docId":"sql-syntax/data-types/map"},{"type":"link","label":"BYTEA","href":"/docs/dev/sql-syntax/data-types/bytea","docId":"sql-syntax/data-types/bytea"},{"type":"link","label":"INET","href":"/docs/dev/sql-syntax/data-types/inet","docId":"sql-syntax/data-types/inet"},{"type":"link","label":"UUID","href":"/docs/dev/sql-syntax/data-types/uuid","docId":"sql-syntax/data-types/uuid"}]},{"type":"category","label":"Functions","collapsible":true,"collapsed":true,"items":[{"type":"category","label":"Text","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"ASCII","href":"/docs/dev/sql-syntax/functions/text/ascii","docId":"sql-syntax/functions/text/ascii"},{"type":"link","label":"CHR","href":"/docs/dev/sql-syntax/functions/text/chr","docId":"sql-syntax/functions/text/chr"},{"type":"link","label":"CONCAT_WS","href":"/docs/dev/sql-syntax/functions/text/concat-ws","docId":"sql-syntax/functions/text/concat-ws"},{"type":"link","label":"CONCAT","href":"/docs/dev/sql-syntax/functions/text/concat","docId":"sql-syntax/functions/text/concat"},{"type":"link","label":"FIND_IDX","href":"/docs/dev/sql-syntax/functions/text/find-idx","docId":"sql-syntax/functions/text/find-idx"},{"type":"link","label":"INITCAP","href":"/docs/dev/sql-syntax/functions/text/initcap","docId":"sql-syntax/functions/text/initcap"},{"type":"link","label":"LEFT","href":"/docs/dev/sql-syntax/functions/text/left","docId":"sql-syntax/functions/text/left"},{"type":"link","label":"LOWER","href":"/docs/dev/sql-syntax/functions/text/lower","docId":"sql-syntax/functions/text/lower"},{"type":"link","label":"LPAD","href":"/docs/dev/sql-syntax/functions/text/lpad","docId":"sql-syntax/functions/text/lpad"},{"type":"link","label":"LTRIM","href":"/docs/dev/sql-syntax/functions/text/ltrim","docId":"sql-syntax/functions/text/ltrim"},{"type":"link","label":"POSITION","href":"/docs/dev/sql-syntax/functions/text/position","docId":"sql-syntax/functions/text/position"},{"type":"link","label":"REPEAT","href":"/docs/dev/sql-syntax/functions/text/repeat","docId":"sql-syntax/functions/text/repeat"},{"type":"link","label":"REVERSE","href":"/docs/dev/sql-syntax/functions/text/reverse","docId":"sql-syntax/functions/text/reverse"},{"type":"link","label":"RIGHT","href":"/docs/dev/sql-syntax/functions/text/right","docId":"sql-syntax/functions/text/right"},{"type":"link","label":"RPAD","href":"/docs/dev/sql-syntax/functions/text/rpad","docId":"sql-syntax/functions/text/rpad"},{"type":"link","label":"RTRIM","href":"/docs/dev/sql-syntax/functions/text/rtrim","docId":"sql-syntax/functions/text/rtrim"},{"type":"link","label":"SUBSTR","href":"/docs/dev/sql-syntax/functions/text/substr","docId":"sql-syntax/functions/text/substr"},{"type":"link","label":"TRIM","href":"/docs/dev/sql-syntax/functions/text/trim","docId":"sql-syntax/functions/text/trim"},{"type":"link","label":"UPPER","href":"/docs/dev/sql-syntax/functions/text/upper","docId":"sql-syntax/functions/text/upper"}]},{"type":"category","label":"Math","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"ABS","href":"/docs/dev/sql-syntax/functions/math/abs","docId":"sql-syntax/functions/math/abs"},{"type":"link","label":"ACOS","href":"/docs/dev/sql-syntax/functions/math/acos","docId":"sql-syntax/functions/math/acos"},{"type":"link","label":"ASIN","href":"/docs/dev/sql-syntax/functions/math/asin","docId":"sql-syntax/functions/math/asin"},{"type":"link","label":"ATAN","href":"/docs/dev/sql-syntax/functions/math/atan","docId":"sql-syntax/functions/math/atan"},{"type":"link","label":"CEIL","href":"/docs/dev/sql-syntax/functions/math/ceil","docId":"sql-syntax/functions/math/ceil"},{"type":"link","label":"COS","href":"/docs/dev/sql-syntax/functions/math/cos","docId":"sql-syntax/functions/math/cos"},{"type":"link","label":"DEGREES","href":"/docs/dev/sql-syntax/functions/math/degrees","docId":"sql-syntax/functions/math/degrees"},{"type":"link","label":"DIV","href":"/docs/dev/sql-syntax/functions/math/div","docId":"sql-syntax/functions/math/div"},{"type":"link","label":"EXP","href":"/docs/dev/sql-syntax/functions/math/exp","docId":"sql-syntax/functions/math/exp"},{"type":"link","label":"FLOOR","href":"/docs/dev/sql-syntax/functions/math/floor","docId":"sql-syntax/functions/math/floor"},{"type":"link","label":"GCD","href":"/docs/dev/sql-syntax/functions/math/gcd","docId":"sql-syntax/functions/math/gcd"},{"type":"link","label":"LCM","href":"/docs/dev/sql-syntax/functions/math/lcm","docId":"sql-syntax/functions/math/lcm"},{"type":"link","label":"LN","href":"/docs/dev/sql-syntax/functions/math/ln","docId":"sql-syntax/functions/math/ln"},{"type":"link","label":"LOG","href":"/docs/dev/sql-syntax/functions/math/log","docId":"sql-syntax/functions/math/log"},{"type":"link","label":"LOG10","href":"/docs/dev/sql-syntax/functions/math/log10","docId":"sql-syntax/functions/math/log10"},{"type":"link","label":"LOG2","href":"/docs/dev/sql-syntax/functions/math/log2","docId":"sql-syntax/functions/math/log2"},{"type":"link","label":"MOD","href":"/docs/dev/sql-syntax/functions/math/mod","docId":"sql-syntax/functions/math/mod"},{"type":"link","label":"PI","href":"/docs/dev/sql-syntax/functions/math/pi","docId":"sql-syntax/functions/math/pi"},{"type":"link","label":"POWER","href":"/docs/dev/sql-syntax/functions/math/power","docId":"sql-syntax/functions/math/power"},{"type":"link","label":"RADIANS","href":"/docs/dev/sql-syntax/functions/math/radians","docId":"sql-syntax/functions/math/radians"},{"type":"link","label":"RAND","href":"/docs/dev/sql-syntax/functions/math/rand","docId":"sql-syntax/functions/math/rand"},{"type":"link","label":"ROUND","href":"/docs/dev/sql-syntax/functions/math/round","docId":"sql-syntax/functions/math/round"},{"type":"link","label":"SIGN","href":"/docs/dev/sql-syntax/functions/math/sign","docId":"sql-syntax/functions/math/sign"},{"type":"link","label":"SIN","href":"/docs/dev/sql-syntax/functions/math/sin","docId":"sql-syntax/functions/math/sin"},{"type":"link","label":"SQRT","href":"/docs/dev/sql-syntax/functions/math/sqrt","docId":"sql-syntax/functions/math/sqrt"},{"type":"link","label":"TAN","href":"/docs/dev/sql-syntax/functions/math/tan","docId":"sql-syntax/functions/math/tan"}]},{"type":"category","label":"Date & Time","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"EXTRACT","href":"/docs/dev/sql-syntax/functions/datetime/extract","docId":"sql-syntax/functions/datetime/extract"},{"type":"link","label":"FORMAT","href":"/docs/dev/sql-syntax/functions/datetime/format","docId":"sql-syntax/functions/datetime/format"},{"type":"link","label":"NOW","href":"/docs/dev/sql-syntax/functions/datetime/now","docId":"sql-syntax/functions/datetime/now"},{"type":"link","label":"TO_DATE","href":"/docs/dev/sql-syntax/functions/datetime/to-date","docId":"sql-syntax/functions/datetime/to-date"},{"type":"link","label":"TO_TIME","href":"/docs/dev/sql-syntax/functions/datetime/to-time","docId":"sql-syntax/functions/datetime/to-time"},{"type":"link","label":"TO_TIMESTAMP","href":"/docs/dev/sql-syntax/functions/datetime/to-timestamp","docId":"sql-syntax/functions/datetime/to-timestamp"}]},{"type":"category","label":"List & Map","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"APPEND","href":"/docs/dev/sql-syntax/functions/list-map/append","docId":"sql-syntax/functions/list-map/append"},{"type":"link","label":"CONCAT","href":"/docs/dev/sql-syntax/functions/list-map/concat","docId":"sql-syntax/functions/list-map/concat"},{"type":"link","label":"PREPEND","href":"/docs/dev/sql-syntax/functions/list-map/prepend","docId":"sql-syntax/functions/list-map/prepend"}]},{"type":"category","label":"Geometry","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"CALC_DISTANCE","href":"/docs/dev/sql-syntax/functions/geometry/calc-distance","docId":"sql-syntax/functions/geometry/calc-distance"},{"type":"link","label":"GET_X","href":"/docs/dev/sql-syntax/functions/geometry/get-x","docId":"sql-syntax/functions/geometry/get-x"},{"type":"link","label":"GET_Y","href":"/docs/dev/sql-syntax/functions/geometry/get-y","docId":"sql-syntax/functions/geometry/get-y"},{"type":"link","label":"POINT","href":"/docs/dev/sql-syntax/functions/geometry/point","docId":"sql-syntax/functions/geometry/point"}]},{"type":"category","label":"Others","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"CAST","href":"/docs/dev/sql-syntax/functions/others/cast","docId":"sql-syntax/functions/others/cast"},{"type":"link","label":"GENERATE_UUID","href":"/docs/dev/sql-syntax/functions/others/generate-uuid","docId":"sql-syntax/functions/others/generate-uuid"},{"type":"link","label":"IFNULL","href":"/docs/dev/sql-syntax/functions/others/ifnull","docId":"sql-syntax/functions/others/ifnull"}]}]}]},{"type":"category","label":"AST Builder","collapsible":true,"collapsed":false,"items":[{"type":"link","label":"Introduction","href":"/docs/dev/ast-builder/intro","docId":"ast-builder/intro"},{"type":"category","label":"Statements","collapsible":true,"collapsed":true,"items":[{"type":"category","label":"Querying","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"Fetching Data from Storage","href":"/docs/dev/ast-builder/statements/querying/fetching-data-from-storage","docId":"ast-builder/statements/querying/fetching-data-from-storage"},{"type":"link","label":"Using Preloaded Data","href":"/docs/dev/ast-builder/statements/querying/using-preloaded-data","docId":"ast-builder/statements/querying/using-preloaded-data"},{"type":"link","label":"Creating Derived Subqueries","href":"/docs/dev/ast-builder/statements/querying/creating-derived-subqueries","docId":"ast-builder/statements/querying/creating-derived-subqueries"},{"type":"link","label":"Data Aggregation","href":"/docs/dev/ast-builder/statements/querying/data-aggregation","docId":"ast-builder/statements/querying/data-aggregation"},{"type":"link","label":"Data Injection","href":"/docs/dev/ast-builder/statements/querying/data-injection","docId":"ast-builder/statements/querying/data-injection"},{"type":"link","label":"Data Joining","href":"/docs/dev/ast-builder/statements/querying/data-joining","docId":"ast-builder/statements/querying/data-joining"},{"type":"link","label":"Data Selection and Projection","href":"/docs/dev/ast-builder/statements/querying/data-selection-and-projection","docId":"ast-builder/statements/querying/data-selection-and-projection"},{"type":"link","label":"Data Sorting and Limiting","href":"/docs/dev/ast-builder/statements/querying/data-sorting-and-limiting","docId":"ast-builder/statements/querying/data-sorting-and-limiting"}]},{"type":"category","label":"Data Manipulation","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"Inserting Data","href":"/docs/dev/ast-builder/statements/data-manipulation/inserting-data","docId":"ast-builder/statements/data-manipulation/inserting-data"},{"type":"link","label":"Updating Data","href":"/docs/dev/ast-builder/statements/data-manipulation/updating-data","docId":"ast-builder/statements/data-manipulation/updating-data"},{"type":"link","label":"Deleting Data","href":"/docs/dev/ast-builder/statements/data-manipulation/deleting-data","docId":"ast-builder/statements/data-manipulation/deleting-data"}]}]},{"type":"category","label":"Expressions","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"Conditional","href":"/docs/dev/ast-builder/expressions/conditional","docId":"ast-builder/expressions/conditional"},{"type":"link","label":"Nested","href":"/docs/dev/ast-builder/expressions/nested","docId":"ast-builder/expressions/nested"},{"type":"link","label":"Operator Based","href":"/docs/dev/ast-builder/expressions/operator-based","docId":"ast-builder/expressions/operator-based"},{"type":"link","label":"Pattern Matching","href":"/docs/dev/ast-builder/expressions/pattern-matching","docId":"ast-builder/expressions/pattern-matching"},{"type":"link","label":"Value Checking","href":"/docs/dev/ast-builder/expressions/value-checking","docId":"ast-builder/expressions/value-checking"}]},{"type":"category","label":"Functions","collapsible":true,"collapsed":true,"items":[{"type":"category","label":"Text","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"Case Conversion","href":"/docs/dev/ast-builder/functions/text/case-conversion","docId":"ast-builder/functions/text/case-conversion"},{"type":"link","label":"Character Conversion","href":"/docs/dev/ast-builder/functions/text/character-conversion","docId":"ast-builder/functions/text/character-conversion"},{"type":"link","label":"Padding","href":"/docs/dev/ast-builder/functions/text/padding","docId":"ast-builder/functions/text/padding"},{"type":"link","label":"Position and Indexing","href":"/docs/dev/ast-builder/functions/text/position-and-indexing","docId":"ast-builder/functions/text/position-and-indexing"},{"type":"link","label":"Text Manipulation","href":"/docs/dev/ast-builder/functions/text/text-manipulation","docId":"ast-builder/functions/text/text-manipulation"},{"type":"link","label":"Trimming","href":"/docs/dev/ast-builder/functions/text/trimming","docId":"ast-builder/functions/text/trimming"}]},{"type":"category","label":"Math","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"Basic Arithmetic","href":"/docs/dev/ast-builder/functions/math/basic-arithmetic","docId":"ast-builder/functions/math/basic-arithmetic"},{"type":"link","label":"Conversion","href":"/docs/dev/ast-builder/functions/math/conversion","docId":"ast-builder/functions/math/conversion"},{"type":"link","label":"Logarithmic and Exponential","href":"/docs/dev/ast-builder/functions/math/logarithmic-and-exponential","docId":"ast-builder/functions/math/logarithmic-and-exponential"},{"type":"link","label":"Rounding","href":"/docs/dev/ast-builder/functions/math/rounding","docId":"ast-builder/functions/math/rounding"},{"type":"link","label":"Special Mathematical","href":"/docs/dev/ast-builder/functions/math/special-mathematical","docId":"ast-builder/functions/math/special-mathematical"},{"type":"link","label":"Trigonometric","href":"/docs/dev/ast-builder/functions/math/trigonometric","docId":"ast-builder/functions/math/trigonometric"}]},{"type":"category","label":"Date & Time","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"Conversion","href":"/docs/dev/ast-builder/functions/date-&-time/conversion","docId":"ast-builder/functions/date-&-time/conversion"},{"type":"link","label":"Current Date and Time","href":"/docs/dev/ast-builder/functions/date-&-time/current-date-and-time","docId":"ast-builder/functions/date-&-time/current-date-and-time"},{"type":"link","label":"Date and Time Extraction","href":"/docs/dev/ast-builder/functions/date-&-time/date-and-time-extraction","docId":"ast-builder/functions/date-&-time/date-and-time-extraction"},{"type":"link","label":"Formatting","href":"/docs/dev/ast-builder/functions/date-&-time/formatting","docId":"ast-builder/functions/date-&-time/formatting"}]},{"type":"category","label":"List & Map","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"List and Map Concatenation","href":"/docs/dev/ast-builder/functions/list-&-map/list-and-map-concatenation","docId":"ast-builder/functions/list-&-map/list-and-map-concatenation"},{"type":"link","label":"List Manipulation","href":"/docs/dev/ast-builder/functions/list-&-map/list-manipulation","docId":"ast-builder/functions/list-&-map/list-manipulation"}]},{"type":"category","label":"Geometry","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"Coordinate Extraction","href":"/docs/dev/ast-builder/functions/geometry/coordinate-extraction","docId":"ast-builder/functions/geometry/coordinate-extraction"},{"type":"link","label":"Distance Calculation","href":"/docs/dev/ast-builder/functions/geometry/distance-calculation","docId":"ast-builder/functions/geometry/distance-calculation"},{"type":"link","label":"Point Creation","href":"/docs/dev/ast-builder/functions/geometry/point-creation","docId":"ast-builder/functions/geometry/point-creation"}]},{"type":"category","label":"Others","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"Null Handling","href":"/docs/dev/ast-builder/functions/others/null-handling","docId":"ast-builder/functions/others/null-handling"},{"type":"link","label":"Type Conversion","href":"/docs/dev/ast-builder/functions/others/type-conversion","docId":"ast-builder/functions/others/type-conversion"},{"type":"link","label":"Unique Identifier","href":"/docs/dev/ast-builder/functions/others/unique-identifier","docId":"ast-builder/functions/others/unique-identifier"}]}]}]},{"type":"category","label":"Storages","collapsible":true,"collapsed":false,"items":[{"type":"link","label":"Introduction","href":"/docs/dev/storages/intro","docId":"storages/intro"},{"type":"category","label":"Supported Storages","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"Memory Storage","href":"/docs/dev/storages/supported-storages/memory-storage","docId":"storages/supported-storages/memory-storage"},{"type":"link","label":"Shared Memory Storage","href":"/docs/dev/storages/supported-storages/shared-memory-storage","docId":"storages/supported-storages/shared-memory-storage"},{"type":"link","label":"Sled Storage","href":"/docs/dev/storages/supported-storages/sled-storage","docId":"storages/supported-storages/sled-storage"},{"type":"link","label":"JSON Storage","href":"/docs/dev/storages/supported-storages/json-storage","docId":"storages/supported-storages/json-storage"},{"type":"link","label":"WebStorage (local & session)","href":"/docs/dev/storages/supported-storages/web-storage","docId":"storages/supported-storages/web-storage"},{"type":"link","label":"IndexedDB Storage","href":"/docs/dev/storages/supported-storages/idb-storage","docId":"storages/supported-storages/idb-storage"},{"type":"link","label":"Composite Storage","href":"/docs/dev/storages/supported-storages/composite-storage","docId":"storages/supported-storages/composite-storage"}]},{"type":"category","label":"Developing Custom Storages","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"Introduction","href":"/docs/dev/storages/developing-custom-storages/intro","docId":"storages/developing-custom-storages/intro"},{"type":"category","label":"Understanding Store traits","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"Store","href":"/docs/dev/storages/developing-custom-storages/store-traits/store","docId":"storages/developing-custom-storages/store-traits/store"},{"type":"link","label":"StoreMut","href":"/docs/dev/storages/developing-custom-storages/store-traits/store-mut","docId":"storages/developing-custom-storages/store-traits/store-mut"},{"type":"link","label":"AlterTable","href":"/docs/dev/storages/developing-custom-storages/store-traits/alter-table","docId":"storages/developing-custom-storages/store-traits/alter-table"},{"type":"link","label":"Transaction","href":"/docs/dev/storages/developing-custom-storages/store-traits/transaction","docId":"storages/developing-custom-storages/store-traits/transaction"},{"type":"link","label":"CustomFunction","href":"/docs/dev/storages/developing-custom-storages/store-traits/custom-function","docId":"storages/developing-custom-storages/store-traits/custom-function"},{"type":"link","label":"CustomFunctionMut","href":"/docs/dev/storages/developing-custom-storages/store-traits/custom-function-mut","docId":"storages/developing-custom-storages/store-traits/custom-function-mut"},{"type":"link","label":"Index","href":"/docs/dev/storages/developing-custom-storages/store-traits/index-trait","docId":"storages/developing-custom-storages/store-traits/index-trait"},{"type":"link","label":"IndexMut","href":"/docs/dev/storages/developing-custom-storages/store-traits/index-mut","docId":"storages/developing-custom-storages/store-traits/index-mut"},{"type":"link","label":"Metadata","href":"/docs/dev/storages/developing-custom-storages/store-traits/metadata","docId":"storages/developing-custom-storages/store-traits/metadata"}]},{"type":"link","label":"Using the Test Suite","href":"/docs/dev/storages/developing-custom-storages/using-test-suite","docId":"storages/developing-custom-storages/using-test-suite"}]}]}]},"docs":{"ast-builder/expressions/conditional":{"id":"ast-builder/expressions/conditional","title":"Conditional","description":"Todo","sidebar":"autoSidebar"},"ast-builder/expressions/nested":{"id":"ast-builder/expressions/nested","title":"Nested","description":"Todo","sidebar":"autoSidebar"},"ast-builder/expressions/operator-based":{"id":"ast-builder/expressions/operator-based","title":"Operator Based","description":"Todo","sidebar":"autoSidebar"},"ast-builder/expressions/pattern-matching":{"id":"ast-builder/expressions/pattern-matching","title":"Pattern Matching","description":"Pattern matching is a crucial feature in SQL that allows you to match rows based on specific patterns in a column. GlueSQL provides 4 pattern matching operators: like, ilike, notlike, and notilike.","sidebar":"autoSidebar"},"ast-builder/expressions/value-checking":{"id":"ast-builder/expressions/value-checking","title":"Value Checking","description":"Todo","sidebar":"autoSidebar"},"ast-builder/functions/date-&-time/conversion":{"id":"ast-builder/functions/date-&-time/conversion","title":"Conversion","description":"GlueSQL provides date and time conversion functions that allow you to convert text data to datetime data types such as Date, Time, and Timestamp. These functions are todate, totime, and to_timestamp.","sidebar":"autoSidebar"},"ast-builder/functions/date-&-time/current-date-and-time":{"id":"ast-builder/functions/date-&-time/current-date-and-time","title":"Current Date and Time","description":"GlueSQL provides a function to get the current date and time: now.","sidebar":"autoSidebar"},"ast-builder/functions/date-&-time/date-and-time-extraction":{"id":"ast-builder/functions/date-&-time/date-and-time-extraction","title":"Date and Time Extraction","description":"Todo","sidebar":"autoSidebar"},"ast-builder/functions/date-&-time/formatting":{"id":"ast-builder/functions/date-&-time/formatting","title":"Formatting","description":"In GlueSQL, you can format date, time, and timestamp values to a specific format using the format function.","sidebar":"autoSidebar"},"ast-builder/functions/geometry/coordinate-extraction":{"id":"ast-builder/functions/geometry/coordinate-extraction","title":"Coordinate Extraction","description":"Todo","sidebar":"autoSidebar"},"ast-builder/functions/geometry/distance-calculation":{"id":"ast-builder/functions/geometry/distance-calculation","title":"Distance Calculation","description":"Todo","sidebar":"autoSidebar"},"ast-builder/functions/geometry/point-creation":{"id":"ast-builder/functions/geometry/point-creation","title":"Point Creation","description":"Todo","sidebar":"autoSidebar"},"ast-builder/functions/list-&-map/list-and-map-concatenation":{"id":"ast-builder/functions/list-&-map/list-and-map-concatenation","title":"List and Map Concatenation","description":"Todo","sidebar":"autoSidebar"},"ast-builder/functions/list-&-map/list-manipulation":{"id":"ast-builder/functions/list-&-map/list-manipulation","title":"List Manipulation","description":"Todo","sidebar":"autoSidebar"},"ast-builder/functions/math/basic-arithmetic":{"id":"ast-builder/functions/math/basic-arithmetic","title":"Basic Arithmetic","description":"GlueSQL provides a number of basic arithmetic operations such as absolute value (abs), division (divide), modulo (modulo), greatest common divisor (gcd), and least common multiple (lcm).","sidebar":"autoSidebar"},"ast-builder/functions/math/conversion":{"id":"ast-builder/functions/math/conversion","title":"Conversion","description":"The AST (Abstract Syntax Tree) Builder in GlueSQL provides mathematical conversion functions like degrees and radians. These functions convert angles expressed in radians to degrees and vice versa.","sidebar":"autoSidebar"},"ast-builder/functions/math/logarithmic-and-exponential":{"id":"ast-builder/functions/math/logarithmic-and-exponential","title":"Logarithmic and Exponential","description":"Todo","sidebar":"autoSidebar"},"ast-builder/functions/math/rounding":{"id":"ast-builder/functions/math/rounding","title":"Rounding","description":"The AST (Abstract Syntax Tree) Builder in GlueSQL provides several mathematical functions, including round, ceil, and floor. These functions are used to perform rounding operations on floating-point numbers.","sidebar":"autoSidebar"},"ast-builder/functions/math/special-mathematical":{"id":"ast-builder/functions/math/special-mathematical","title":"Special Mathematical","description":"Todo","sidebar":"autoSidebar"},"ast-builder/functions/math/trigonometric":{"id":"ast-builder/functions/math/trigonometric","title":"Trigonometric","description":"Todo","sidebar":"autoSidebar"},"ast-builder/functions/others/null-handling":{"id":"ast-builder/functions/others/null-handling","title":"Null Handling","description":"In some cases, you may need to handle NULL values in your database. GlueSQL provides a function called ifnull to handle these cases.","sidebar":"autoSidebar"},"ast-builder/functions/others/type-conversion":{"id":"ast-builder/functions/others/type-conversion","title":"Type Conversion","description":"Todo","sidebar":"autoSidebar"},"ast-builder/functions/others/unique-identifier":{"id":"ast-builder/functions/others/unique-identifier","title":"Unique Identifier","description":"Todo","sidebar":"autoSidebar"},"ast-builder/functions/text/case-conversion":{"id":"ast-builder/functions/text/case-conversion","title":"Case Conversion","description":"GlueSQL provides several text case conversion functions that allow you to convert text data to upper case, lower case or capitalize each word in a string.","sidebar":"autoSidebar"},"ast-builder/functions/text/character-conversion":{"id":"ast-builder/functions/text/character-conversion","title":"Character Conversion","description":"Todo","sidebar":"autoSidebar"},"ast-builder/functions/text/padding":{"id":"ast-builder/functions/text/padding","title":"Padding","description":"Todo","sidebar":"autoSidebar"},"ast-builder/functions/text/position-and-indexing":{"id":"ast-builder/functions/text/position-and-indexing","title":"Position and Indexing","description":"GlueSQL provides several functions for text manipulation, including finding the index of a substring (find_idx), finding the position of a substring (position), and getting the leftmost or rightmost characters (left and right).","sidebar":"autoSidebar"},"ast-builder/functions/text/text-manipulation":{"id":"ast-builder/functions/text/text-manipulation","title":"Text Manipulation","description":"Todo","sidebar":"autoSidebar"},"ast-builder/functions/text/trimming":{"id":"ast-builder/functions/text/trimming","title":"Trimming","description":"GlueSQL provides several text trimming functions that allow you to remove leading or trailing characters from a text string.","sidebar":"autoSidebar"},"ast-builder/intro":{"id":"ast-builder/intro","title":"Introduction","description":"GlueSQL offers two ways to create and execute queries: using SQL statements or using the AST Builder. In this introductory page, we will focus on the AST Builder.","sidebar":"autoSidebar"},"ast-builder/statements/data-manipulation/deleting-data":{"id":"ast-builder/statements/data-manipulation/deleting-data","title":"Deleting Data","description":"In this section, we will discuss how to delete data from a table using GlueSQL.","sidebar":"autoSidebar"},"ast-builder/statements/data-manipulation/inserting-data":{"id":"ast-builder/statements/data-manipulation/inserting-data","title":"Inserting Data","description":"In this section, we will discuss how to insert data into a table using GlueSQL.","sidebar":"autoSidebar"},"ast-builder/statements/data-manipulation/updating-data":{"id":"ast-builder/statements/data-manipulation/updating-data","title":"Updating Data","description":"In this section, we will discuss how to update data in a table using GlueSQL.","sidebar":"autoSidebar"},"ast-builder/statements/querying/creating-derived-subqueries":{"id":"ast-builder/statements/querying/creating-derived-subqueries","title":"Creating Derived Subqueries","description":"This document covers the aliasas functionality of the AST Builder in the GlueSQL project. The aliasas method allows you to create a derived subquery, which is similar to subqueries in SQL. It gives you the ability to use the output of a query as a table to perform further queries.","sidebar":"autoSidebar"},"ast-builder/statements/querying/data-aggregation":{"id":"ast-builder/statements/querying/data-aggregation","title":"Data Aggregation","description":"The AST Builder API in GlueSQL allows you to construct SQL queries programmatically. This page provides an introduction to data aggregation using the AST Builder API.","sidebar":"autoSidebar"},"ast-builder/statements/querying/data-injection":{"id":"ast-builder/statements/querying/data-injection","title":"Data Injection","description":"Todo","sidebar":"autoSidebar"},"ast-builder/statements/querying/data-joining":{"id":"ast-builder/statements/querying/data-joining","title":"Data Joining","description":"Todo","sidebar":"autoSidebar"},"ast-builder/statements/querying/data-selection-and-projection":{"id":"ast-builder/statements/querying/data-selection-and-projection","title":"Data Selection and Projection","description":"Todo","sidebar":"autoSidebar"},"ast-builder/statements/querying/data-sorting-and-limiting":{"id":"ast-builder/statements/querying/data-sorting-and-limiting","title":"Data Sorting and Limiting","description":"Todo","sidebar":"autoSidebar"},"ast-builder/statements/querying/fetching-data-from-storage":{"id":"ast-builder/statements/querying/fetching-data-from-storage","title":"Fetching Data from Storage","description":"The AST Builder provides a powerful and flexible way to query data from your tables, similar to SQL\'s SELECT statement. This guide will show you how to use the AST Builder\'s table(\\"foo\\").select() method to perform various query types, including filtering, joining, grouping, ordering, and pagination.","sidebar":"autoSidebar"},"ast-builder/statements/querying/using-preloaded-data":{"id":"ast-builder/statements/querying/using-preloaded-data","title":"Using Preloaded Data","description":"This guide will show you how to use AST Builder to query data that has already been loaded into memory, as opposed to querying data from storage. This is similar to SQL\'s VALUES functionality.","sidebar":"autoSidebar"},"getting-started/cli":{"id":"getting-started/cli","title":"Command-Line Interface","description":"Introduction","sidebar":"autoSidebar"},"getting-started/javascript-web":{"id":"getting-started/javascript-web","title":"JavaScript (Web Browser)","description":"GlueSQL is a SQL database engine written in Rust, compiled to WebAssembly, and can be used in JavaScript. This guide will walk you through the process of installing and using the GlueSQL package.","sidebar":"autoSidebar"},"getting-started/nodejs":{"id":"getting-started/nodejs","title":"Node.js","description":"This guide will help you get started with GlueSQL in a Node.js project. First, install the gluesql package using npm by running the following command in your terminal:","sidebar":"autoSidebar"},"getting-started/rust":{"id":"getting-started/rust","title":"Rust","description":"To install and use GlueSQL in your Rust project, you\'ll first need to add it as a dependency from crates.io. You can do this by adding the following lines to your Cargo.toml file:","sidebar":"autoSidebar"},"index":{"id":"index","title":"Introduction","description":"crates.io","sidebar":"autoSidebar"},"sql-syntax/data-types/boolean":{"id":"sql-syntax/data-types/boolean","title":"BOOLEAN","description":"The BOOLEAN data type in SQL is used to store boolean values, which can be either TRUE or FALSE. This data type is useful for representing binary states or conditions in your data.","sidebar":"autoSidebar"},"sql-syntax/data-types/bytea":{"id":"sql-syntax/data-types/bytea","title":"BYTEA","description":"The BYTEA data type in SQL is used to store binary data, such as images, audio files, or any other type of data that needs to be stored in its raw form. In GlueSQL, the BYTEA data type is represented as a sequence of bytes.","sidebar":"autoSidebar"},"sql-syntax/data-types/date":{"id":"sql-syntax/data-types/date","title":"DATE","description":"In GlueSQL, the DATE data type is used to store date values in the format \'YYYY-MM-DD\'. Note that GlueSQL currently does not support timezones.","sidebar":"autoSidebar"},"sql-syntax/data-types/decimal":{"id":"sql-syntax/data-types/decimal","title":"DECIMAL","description":"The DECIMAL data type in SQL is used to store exact numeric values, making it suitable for financial calculations and other operations requiring a high level of precision without round-off errors. In GlueSQL, the DECIMAL data type is implemented using a pure Rust library, providing a 96-bit integer number, a scaling factor for specifying the decimal fraction, and a 1-bit sign.","sidebar":"autoSidebar"},"sql-syntax/data-types/float":{"id":"sql-syntax/data-types/float","title":"FLOAT","description":"The FLOAT data type in SQL is used to store floating-point numbers. In GlueSQL, the FLOAT data type represents a 64-bit floating-point number, providing the ability to store numbers with decimal values and a wide range of magnitude.","sidebar":"autoSidebar"},"sql-syntax/data-types/inet":{"id":"sql-syntax/data-types/inet","title":"INET","description":"The INET data type in SQL is used to store IPv4 and IPv6 addresses. These addresses can be compared, filtered, and sorted using standard SQL operations.","sidebar":"autoSidebar"},"sql-syntax/data-types/integers":{"id":"sql-syntax/data-types/integers","title":"Integer Types","description":"GlueSQL supports the following integer data types:","sidebar":"autoSidebar"},"sql-syntax/data-types/interval":{"id":"sql-syntax/data-types/interval","title":"INTERVAL","description":"The INTERVAL data type in GlueSQL is used to represent a period of time. In accordance with the ANSI SQL standard, several subtypes of INTERVAL can be used to represent different units of time, such as years, months, days, hours, minutes, and seconds. These subtypes are:","sidebar":"autoSidebar"},"sql-syntax/data-types/list":{"id":"sql-syntax/data-types/list","title":"LIST","description":"The LIST data type in GlueSQL is used to store ordered collections of elements, similar to JSON arrays. The elements can be any valid data supported by GlueSQL, such as numbers, strings, booleans, null, MAP, or even other nested LIST values. Although the input is provided in a JSON array format for convenience, it can store more than just JSON data.","sidebar":"autoSidebar"},"sql-syntax/data-types/map":{"id":"sql-syntax/data-types/map","title":"MAP","description":"The MAP data type in GlueSQL is used to store nested key-value pairs, similar to JSON objects. The object keys must be strings, and the values can be any valid data supported by GlueSQL, such as numbers, strings, booleans, null, or even other nested MAP values. Although the input is provided in a JSON object format for convenience, it can store more than just JSON data.","sidebar":"autoSidebar"},"sql-syntax/data-types/text":{"id":"sql-syntax/data-types/text","title":"TEXT","description":"The TEXT data type in SQL is used to store variable-length character strings. In GlueSQL, the TEXT data type is the only supported string data type, providing the ability to store and manage strings of varying lengths.","sidebar":"autoSidebar"},"sql-syntax/data-types/time":{"id":"sql-syntax/data-types/time","title":"TIME","description":"In GlueSQL, the TIME data type is used to store time values in the format \'HHSS.SSS\'. The code snippet provided demonstrates how to create a table with TIME columns, insert data into it, and perform various queries and operations on the data.","sidebar":"autoSidebar"},"sql-syntax/data-types/timestamp":{"id":"sql-syntax/data-types/timestamp","title":"TIMESTAMP","description":"In GlueSQL, the TIMESTAMP data type is used to store date and time values in the format \'YYYY-MM-DD HHSS.SSSS\'. Although timezone information can be included in the input string, GlueSQL stores all TIMESTAMP values in UTC, discarding the timezone information.","sidebar":"autoSidebar"},"sql-syntax/data-types/uuid":{"id":"sql-syntax/data-types/uuid","title":"UUID","description":"The UUID data type in SQL is used to store universally unique identifiers (UUIDs). These identifiers can be compared, filtered, and sorted using standard SQL operations.","sidebar":"autoSidebar"},"sql-syntax/functions/datetime/extract":{"id":"sql-syntax/functions/datetime/extract","title":"EXTRACT","description":"The EXTRACT function in SQL is used to retrieve a specific datetime field from a date, time, or interval.","sidebar":"autoSidebar"},"sql-syntax/functions/datetime/format":{"id":"sql-syntax/functions/datetime/format","title":"FORMAT","description":"The FORMAT function in SQL is used to format date, time, and timestamp values into a specified format.","sidebar":"autoSidebar"},"sql-syntax/functions/datetime/now":{"id":"sql-syntax/functions/datetime/now","title":"NOW","description":"The NOW() function in SQL returns the current date and time in UTC. You can use it to retrieve the current UTC timestamp, or as a default value for a TIMESTAMP column in a table.","sidebar":"autoSidebar"},"sql-syntax/functions/datetime/to-date":{"id":"sql-syntax/functions/datetime/to-date","title":"TO_DATE","description":"The TO_DATE function in SQL is used to convert a string into a DATE. This function takes two arguments, the string to be converted and a format string that specifies the format of the input string.","sidebar":"autoSidebar"},"sql-syntax/functions/datetime/to-time":{"id":"sql-syntax/functions/datetime/to-time","title":"TO_TIME","description":"The TO_TIME function in SQL is used to convert a string into a TIME. This function takes two arguments, the string to be converted and a format string that specifies the format of the input string.","sidebar":"autoSidebar"},"sql-syntax/functions/datetime/to-timestamp":{"id":"sql-syntax/functions/datetime/to-timestamp","title":"TO_TIMESTAMP","description":"The TO_TIMESTAMP function in SQL is used to convert a string into a TIMESTAMP. This function takes two arguments, the string to be converted and a format string that specifies the format of the input string.","sidebar":"autoSidebar"},"sql-syntax/functions/geometry/calc-distance":{"id":"sql-syntax/functions/geometry/calc-distance","title":"CALC_DISTANCE","description":"The CALC_DISTANCE function is used to calculate the Euclidean distance between two Point type geographical coordinates.","sidebar":"autoSidebar"},"sql-syntax/functions/geometry/get-x":{"id":"sql-syntax/functions/geometry/get-x","title":"GET_X","description":"The GET_X function returns the x-coordinate of a given POINT data type. It takes one POINT data type argument and returns a FLOAT value representing the x-coordinate.","sidebar":"autoSidebar"},"sql-syntax/functions/geometry/get-y":{"id":"sql-syntax/functions/geometry/get-y","title":"GET_Y","description":"The GET_Y function returns the y-coordinate of a given POINT data type. It takes one POINT data type argument and returns a FLOAT value representing the y-coordinate.","sidebar":"autoSidebar"},"sql-syntax/functions/geometry/point":{"id":"sql-syntax/functions/geometry/point","title":"POINT","description":"The POINT function creates a point value using the provided x and y coordinates. A point value represents a two-dimensional geometric point with a pair of floating-point numbers, often used for storing spatial data.","sidebar":"autoSidebar"},"sql-syntax/functions/list-map/append":{"id":"sql-syntax/functions/list-map/append","title":"APPEND","description":"The APPEND function in SQL is used to append an element to a list.","sidebar":"autoSidebar"},"sql-syntax/functions/list-map/concat":{"id":"sql-syntax/functions/list-map/concat","title":"CONCAT","description":"The CONCAT function is used to concatenate two or more list values together.","sidebar":"autoSidebar"},"sql-syntax/functions/list-map/prepend":{"id":"sql-syntax/functions/list-map/prepend","title":"PREPEND","description":"The PREPEND function in SQL is used to prepend an element to a list.","sidebar":"autoSidebar"},"sql-syntax/functions/math/abs":{"id":"sql-syntax/functions/math/abs","title":"ABS","description":"The ABS function is used to calculate the absolute value of a number. It takes a single numeric argument and returns the absolute value of that number. The argument can be an integer, decimal, or float value.","sidebar":"autoSidebar"},"sql-syntax/functions/math/acos":{"id":"sql-syntax/functions/math/acos","title":"ACOS","description":"The ACOS function is used to calculate the arccosine (inverse cosine) of a number. It takes a single numeric argument, which should be a float value in the range of -1 to 1, and returns the arccosine of that number in radians.","sidebar":"autoSidebar"},"sql-syntax/functions/math/asin":{"id":"sql-syntax/functions/math/asin","title":"ASIN","description":"The ASIN function is used to calculate the arcsine (inverse sine) of a number. It takes a single numeric argument, which should be a float value in the range of -1 to 1, and returns the arcsine of that number in radians.","sidebar":"autoSidebar"},"sql-syntax/functions/math/atan":{"id":"sql-syntax/functions/math/atan","title":"ATAN","description":"The ATAN function is used to calculate the arctangent (inverse tangent) of a number. It takes a single numeric argument, and returns the arctangent of that number in radians.","sidebar":"autoSidebar"},"sql-syntax/functions/math/ceil":{"id":"sql-syntax/functions/math/ceil","title":"CEIL","description":"The CEIL function is used to round a number up to the nearest integer value. It takes a single floating-point or integer value as its argument and returns a floating-point value.","sidebar":"autoSidebar"},"sql-syntax/functions/math/cos":{"id":"sql-syntax/functions/math/cos","title":"COS","description":"The COS function is used to calculate the cosine of a number. It takes a single numeric argument (angle in radians) and returns the cosine of that angle.","sidebar":"autoSidebar"},"sql-syntax/functions/math/degrees":{"id":"sql-syntax/functions/math/degrees","title":"DEGREES","description":"The DEGREES function is used to convert a given angle value from radians to degrees. It takes a single numeric argument (angle in radians) and returns the angle in degrees.","sidebar":"autoSidebar"},"sql-syntax/functions/math/div":{"id":"sql-syntax/functions/math/div","title":"DIV","description":"The DIV function is used to perform integer division. It takes two arguments (a dividend and a divisor) and returns the integer quotient of the division operation. Both dividend and divisor can be FLOAT or INTEGER type. The return type of the function is INTEGER.","sidebar":"autoSidebar"},"sql-syntax/functions/math/exp":{"id":"sql-syntax/functions/math/exp","title":"EXP","description":"The EXP function is used to calculate the exponential value of a number. It takes a single FLOAT or INTEGER argument and returns a FLOAT value representing the exponential value of the given number.","sidebar":"autoSidebar"},"sql-syntax/functions/math/floor":{"id":"sql-syntax/functions/math/floor","title":"FLOOR","description":"The FLOOR function is used to round a number down to the nearest integer value. It takes a single floating-point or integer value as its argument and returns a floating-point value.","sidebar":"autoSidebar"},"sql-syntax/functions/math/gcd":{"id":"sql-syntax/functions/math/gcd","title":"GCD","description":"The GCD function is used to find the greatest common divisor (GCD) of two integers. It takes two INTEGER arguments and returns an INTEGER value representing the greatest common divisor of the given integers.","sidebar":"autoSidebar"},"sql-syntax/functions/math/lcm":{"id":"sql-syntax/functions/math/lcm","title":"LCM","description":"The LCM function is used to find the least common multiple (LCM) of two integers. It takes two INTEGER arguments and returns an INTEGER value representing the least common multiple of the given integers.","sidebar":"autoSidebar"},"sql-syntax/functions/math/ln":{"id":"sql-syntax/functions/math/ln","title":"LN","description":"The LN function is used to calculate the natural logarithm (base e) of a number. It takes a single FLOAT or INTEGER argument and returns a FLOAT value representing the natural logarithm of the given number.","sidebar":"autoSidebar"},"sql-syntax/functions/math/log":{"id":"sql-syntax/functions/math/log","title":"LOG","description":"The LOG function calculates the logarithm of a number with a specified base. It takes two FLOAT or INTEGER arguments and returns a FLOAT value representing the logarithm of the first argument with the base specified by the second argument.","sidebar":"autoSidebar"},"sql-syntax/functions/math/log10":{"id":"sql-syntax/functions/math/log10","title":"LOG10","description":"The LOG10 function is used to calculate the base-10 logarithm of a number. It takes a single FLOAT or INTEGER argument and returns a FLOAT value representing the base-10 logarithm of the given number.","sidebar":"autoSidebar"},"sql-syntax/functions/math/log2":{"id":"sql-syntax/functions/math/log2","title":"LOG2","description":"The LOG2 function is used to calculate the base-2 logarithm of a number. It takes a single FLOAT or INTEGER argument and returns a FLOAT value representing the base-2 logarithm of the given number.","sidebar":"autoSidebar"},"sql-syntax/functions/math/mod":{"id":"sql-syntax/functions/math/mod","title":"MOD","description":"The MOD function is used to calculate the remainder of a division operation. It takes two arguments (a dividend and a divisor) and returns the remainder of the division operation. Both dividend and divisor can be FLOAT or INTEGER type. The return type of the function is FLOAT.","sidebar":"autoSidebar"},"sql-syntax/functions/math/pi":{"id":"sql-syntax/functions/math/pi","title":"PI","description":"The PI function is used to retrieve the mathematical constant \u03c0 (pi), which is approximately 3.141592653589793. The function takes no arguments.","sidebar":"autoSidebar"},"sql-syntax/functions/math/power":{"id":"sql-syntax/functions/math/power","title":"POWER","description":"The POWER function is used to raise a number to the power of another number. It takes two arguments, the base and the exponent, both of which must be of the FLOAT type. The result will also be of the FLOAT type.","sidebar":"autoSidebar"},"sql-syntax/functions/math/radians":{"id":"sql-syntax/functions/math/radians","title":"RADIANS","description":"The RADIANS function is used to convert a given angle value from degrees to radians. It takes a single numeric argument (angle in degrees) and returns the angle in radians.","sidebar":"autoSidebar"},"sql-syntax/functions/math/rand":{"id":"sql-syntax/functions/math/rand","title":"RAND","description":"The RAND function is used to generate a random float value between 0 (inclusive) and 1 (exclusive). The function takes an optional seed value, which must be of the FLOAT type. If a seed value is provided, the random number generator will be initialized with that seed, producing a deterministic sequence of random numbers.","sidebar":"autoSidebar"},"sql-syntax/functions/math/round":{"id":"sql-syntax/functions/math/round","title":"ROUND","description":"The ROUND function is used to round a number to the nearest integer value. It takes a single floating-point or integer value as its argument and returns a floating-point value.","sidebar":"autoSidebar"},"sql-syntax/functions/math/sign":{"id":"sql-syntax/functions/math/sign","title":"SIGN","description":"The SIGN function is used to determine the sign of a number. It takes one argument, which must be of the FLOAT type. The result will be of the INTEGER type and can be -1, 0, or 1.","sidebar":"autoSidebar"},"sql-syntax/functions/math/sin":{"id":"sql-syntax/functions/math/sin","title":"SIN","description":"The SIN function is used to calculate the sine of a number. It takes a single numeric argument (angle in radians) and returns the sine of that angle.","sidebar":"autoSidebar"},"sql-syntax/functions/math/sqrt":{"id":"sql-syntax/functions/math/sqrt","title":"SQRT","description":"The SQRT function is used to calculate the square root of a number. It takes one argument, which must be of the FLOAT type. The result will also be of the FLOAT type.","sidebar":"autoSidebar"},"sql-syntax/functions/math/tan":{"id":"sql-syntax/functions/math/tan","title":"TAN","description":"The TAN function is used to calculate the tangent of a number. It takes a single numeric argument (angle in radians) and returns the tangent of that angle.","sidebar":"autoSidebar"},"sql-syntax/functions/others/cast":{"id":"sql-syntax/functions/others/cast","title":"CAST","description":"The CAST function is used to convert a value from one data type to another. It is commonly used when you need to change the data type of a value or a column to perform a specific operation, such as arithmetic or string concatenation.","sidebar":"autoSidebar"},"sql-syntax/functions/others/generate-uuid":{"id":"sql-syntax/functions/others/generate-uuid","title":"GENERATE_UUID","description":"The GENERATE_UUID function is an SQL function provided by GlueSQL that generates a new UUID (Universally Unique Identifier) using the version 4 UUID algorithm. A UUID is a 128-bit value used to uniquely identify items in various computing systems. Version 4 UUIDs are randomly generated and have 122 bits of randomness, which ensures a very low probability of collisions.","sidebar":"autoSidebar"},"sql-syntax/functions/others/ifnull":{"id":"sql-syntax/functions/others/ifnull","title":"IFNULL","description":"The IFNULL function is used to return the first non-null value among the provided expressions. It takes two arguments and checks if the first argument is NULL. If the first argument is NULL, it returns the second argument; otherwise, it returns the first argument.","sidebar":"autoSidebar"},"sql-syntax/functions/text/ascii":{"id":"sql-syntax/functions/text/ascii","title":"ASCII","description":"The ASCII function in SQL returns the ASCII value for the first character of the specified string.","sidebar":"autoSidebar"},"sql-syntax/functions/text/chr":{"id":"sql-syntax/functions/text/chr","title":"CHR","description":"The CHR function in SQL returns the character represented by the specified ASCII value.","sidebar":"autoSidebar"},"sql-syntax/functions/text/concat":{"id":"sql-syntax/functions/text/concat","title":"CONCAT","description":"The CONCAT function in SQL concatenates two or more strings into one string.","sidebar":"autoSidebar"},"sql-syntax/functions/text/concat-ws":{"id":"sql-syntax/functions/text/concat-ws","title":"CONCAT_WS","description":"The CONCAT_WS function in SQL concatenates two or more strings into one string with a separator.","sidebar":"autoSidebar"},"sql-syntax/functions/text/find-idx":{"id":"sql-syntax/functions/text/find-idx","title":"FIND_IDX","description":"The FIND_IDX function in SQL is used to return the position of the first occurrence of a substring in a string, optionally after a specified position.","sidebar":"autoSidebar"},"sql-syntax/functions/text/initcap":{"id":"sql-syntax/functions/text/initcap","title":"INITCAP","description":"The INITCAP function in SQL is used to capitalize the first letter of each word in a string and convert the rest of the characters to lowercase.","sidebar":"autoSidebar"},"sql-syntax/functions/text/left":{"id":"sql-syntax/functions/text/left","title":"LEFT","description":"The LEFT function in SQL returns the specified number of characters from the start (left side) of a given string.","sidebar":"autoSidebar"},"sql-syntax/functions/text/lower":{"id":"sql-syntax/functions/text/lower","title":"LOWER","description":"The LOWER function in SQL returns a string in which all alphabetic characters in a specified string are converted to lowercase.","sidebar":"autoSidebar"},"sql-syntax/functions/text/lpad":{"id":"sql-syntax/functions/text/lpad","title":"LPAD","description":"The LPAD function in SQL pads the left side of a string with a specific set of characters.","sidebar":"autoSidebar"},"sql-syntax/functions/text/ltrim":{"id":"sql-syntax/functions/text/ltrim","title":"LTRIM","description":"The LTRIM function in SQL removes characters from the left (leading side) of a string.","sidebar":"autoSidebar"},"sql-syntax/functions/text/position":{"id":"sql-syntax/functions/text/position","title":"POSITION","description":"The POSITION function in SQL is used to find the position of a substring in a string. The position of the first occurrence of the substring is returned. If the substring is not found, this function returns 0.","sidebar":"autoSidebar"},"sql-syntax/functions/text/repeat":{"id":"sql-syntax/functions/text/repeat","title":"REPEAT","description":"The REPEAT function in SQL is used to repeat a string for a specified number of times.","sidebar":"autoSidebar"},"sql-syntax/functions/text/reverse":{"id":"sql-syntax/functions/text/reverse","title":"REVERSE","description":"The REVERSE function in SQL is used to reverse a string.","sidebar":"autoSidebar"},"sql-syntax/functions/text/right":{"id":"sql-syntax/functions/text/right","title":"RIGHT","description":"The RIGHT function in SQL returns the specified number of characters from the end (right side) of a given string.","sidebar":"autoSidebar"},"sql-syntax/functions/text/rpad":{"id":"sql-syntax/functions/text/rpad","title":"RPAD","description":"The RPAD function in SQL pads the right side of a string with a specific set of characters.","sidebar":"autoSidebar"},"sql-syntax/functions/text/rtrim":{"id":"sql-syntax/functions/text/rtrim","title":"RTRIM","description":"The RTRIM function in SQL removes characters from the right (trailing side) of a string.","sidebar":"autoSidebar"},"sql-syntax/functions/text/substr":{"id":"sql-syntax/functions/text/substr","title":"SUBSTR","description":"The SUBSTR function in SQL is used to extract a substring from a string.","sidebar":"autoSidebar"},"sql-syntax/functions/text/trim":{"id":"sql-syntax/functions/text/trim","title":"TRIM","description":"The TRIM function in SQL is used to remove leading, trailing, or both leading and trailing unwanted characters (often whitespace) from a string.","sidebar":"autoSidebar"},"sql-syntax/functions/text/upper":{"id":"sql-syntax/functions/text/upper","title":"UPPER","description":"The UPPER function in SQL converts all lowercase alphabetic characters in a specified string to uppercase.","sidebar":"autoSidebar"},"sql-syntax/intro":{"id":"sql-syntax/intro","title":"Introduction","description":"Welcome to the Introduction page for the SQL Syntax category in GlueSQL! In this section, we\'ll provide a brief overview of the SQL syntax supported by GlueSQL. You can find more in-depth examples and details by browsing the other pages in this category.","sidebar":"autoSidebar"},"sql-syntax/statements/data-definition/alter-table":{"id":"sql-syntax/statements/data-definition/alter-table","title":"ALTER TABLE","description":"The ALTER TABLE statement is an SQL command used to modify the structure of an existing table in a database. This operation is useful when you need to add, remove, or modify columns or constraints in a table. In this document, we\'ll explain the syntax and usage of the ALTER TABLE statement, including the RENAME, ADD COLUMN, and DROP COLUMN clauses.","sidebar":"autoSidebar"},"sql-syntax/statements/data-definition/create-index":{"id":"sql-syntax/statements/data-definition/create-index","title":"CREATE INDEX","description":"CREATE INDEX statement is used to create an index on one or more columns of a table. Indexes can improve query performance by allowing the database to quickly locate rows with specific column values. They can also be used with the ORDER BY clause to improve sorting performance. An index can be thought of as a data structure that maps the values of a specific column or columns to the corresponding rows in a table. This mapping allows the database to perform lookups and sorting operations more efficiently, as it does not have to scan the entire table.","sidebar":"autoSidebar"},"sql-syntax/statements/data-definition/create-table":{"id":"sql-syntax/statements/data-definition/create-table","title":"CREATE TABLE","description":"The CREATE TABLE statement is a fundamental SQL command used to create a new table in a database. Tables are the primary structure in databases, as they hold the data organized in rows and columns. In this document, we\'ll explain the syntax and usage of the CREATE TABLE statement, including the IF NOT EXISTS clause.","sidebar":"autoSidebar"},"sql-syntax/statements/data-definition/drop-index":{"id":"sql-syntax/statements/data-definition/drop-index","title":"DROP INDEX","description":"DROP INDEX statement is used to remove an existing index from a table. This can be useful when an index is no longer needed, or if you want to free up storage space and reduce maintenance overhead associated with maintaining the index.","sidebar":"autoSidebar"},"sql-syntax/statements/data-definition/drop-table":{"id":"sql-syntax/statements/data-definition/drop-table","title":"DROP TABLE","description":"The DROP TABLE statement is an SQL command used to remove one or more tables from a database. This operation is useful when you no longer need a table or want to clear out old data structures. In this document, we\'ll explain the syntax and usage of the DROP TABLE statement, including the IF EXISTS clause and dropping multiple tables at once.","sidebar":"autoSidebar"},"sql-syntax/statements/data-manipulation/delete":{"id":"sql-syntax/statements/data-manipulation/delete","title":"DELETE","description":"The DELETE statement is used to remove records from a table. You can delete a single row, multiple rows, or all rows at once based on specific conditions.","sidebar":"autoSidebar"},"sql-syntax/statements/data-manipulation/insert":{"id":"sql-syntax/statements/data-manipulation/insert","title":"INSERT","description":"The INSERT statement is used to insert new records into a table. You can insert a single row or multiple rows at once, and you can also use the NULL, NOT NULL, and DEFAULT constraints to define how values are inserted.","sidebar":"autoSidebar"},"sql-syntax/statements/data-manipulation/update":{"id":"sql-syntax/statements/data-manipulation/update","title":"UPDATE","description":"The UPDATE statement is used to modify existing records in a table. You can update one or more columns with new values, or even use subqueries to update values based on other tables.","sidebar":"autoSidebar"},"sql-syntax/statements/metadata/data-dictionary":{"id":"sql-syntax/statements/metadata/data-dictionary","title":"Data Dictionary","description":"In GlueSQL, there are predefined tables, also known as Data Dictionary tables, which store metadata about the database objects like tables, columns, and indexes. These tables can be queried like any other table in the database, and they provide useful information about the database schema.","sidebar":"autoSidebar"},"sql-syntax/statements/metadata/show-tables":{"id":"sql-syntax/statements/metadata/show-tables","title":"SHOW TABLES","description":"The SHOW TABLES statement in GlueSQL is used to display a list of tables available in the database. This statement is useful when you want to inspect the current structure of your database or when you want to manage multiple tables.","sidebar":"autoSidebar"},"sql-syntax/statements/querying/aggregation":{"id":"sql-syntax/statements/querying/aggregation","title":"Aggregation","description":"GlueSQL supports several aggregate functions to perform calculations on a set of values. Below is a list of supported aggregate functions along with a brief explanation of each:","sidebar":"autoSidebar"},"sql-syntax/statements/querying/join":{"id":"sql-syntax/statements/querying/join","title":"JOIN","description":"GlueSQL supports two types of JOIN operations:","sidebar":"autoSidebar"},"sql-syntax/statements/querying/limit":{"id":"sql-syntax/statements/querying/limit","title":"LIMIT & OFFSET","description":"LIMIT and OFFSET are SQL clauses that allow you to control the number of rows returned by a SELECT statement. They are particularly useful when you need to paginate or retrieve a specific portion of the result set.","sidebar":"autoSidebar"},"sql-syntax/statements/querying/schemaless":{"id":"sql-syntax/statements/querying/schemaless","title":"Schemaless Data","description":"GlueSQL is an SQL database that provides a unique feature: it allows you to work with schemaless data, similar to NoSQL databases. Please note this point in the documentation.","sidebar":"autoSidebar"},"sql-syntax/statements/querying/where":{"id":"sql-syntax/statements/querying/where","title":"WHERE","description":"In GlueSQL, the WHERE clause is used to filter the results of a SELECT query based on specific conditions. The WHERE clause can be used with various operators and functions to create complex filtering conditions.","sidebar":"autoSidebar"},"sql-syntax/statements/transaction":{"id":"sql-syntax/statements/transaction","title":"Transaction","description":"Transactions in SQL are a series of queries that are executed as a single unit of work. In GlueSQL, transactions help to ensure the consistency and integrity of the database. They follow the ACID properties: Atomicity, Consistency, Isolation, and Durability.","sidebar":"autoSidebar"},"storages/developing-custom-storages/intro":{"id":"storages/developing-custom-storages/intro","title":"Introduction","description":"With GlueSQL, you can adapt SQL and the AST Builder to a wide variety of environments. This includes file systems, key-value databases, complex NoSQL databases, and even remote APIs. As long as a system supports reading, it can support SELECT queries. If it supports both reading and writing, it can support most SQL operations, including UPDATE and DELETE.","sidebar":"autoSidebar"},"storages/developing-custom-storages/store-traits/alter-table":{"id":"storages/developing-custom-storages/store-traits/alter-table","title":"AlterTable","description":"The AlterTable trait corresponds to the SQL ALTER TABLE statement and is used for modifying existing schemas. It is not necessary to implement the AlterTable trait. If you are dealing with data that is difficult to modify schema-wise or schemaless data, there is no need to implement the AlterTable trait. It is an optional trait that custom storage developers can choose to implement.","sidebar":"autoSidebar"},"storages/developing-custom-storages/store-traits/custom-function":{"id":"storages/developing-custom-storages/store-traits/custom-function","title":"CustomFunction","description":"The CustomFunction trait is an optional trait for supporting user-level custom functions. Through the CustomFunction trait, you can retrieve custom functions stored in the storage system. You can choose to implement the CustomFunction trait alone or together with the CustomFunctionMut trait.","sidebar":"autoSidebar"},"storages/developing-custom-storages/store-traits/custom-function-mut":{"id":"storages/developing-custom-storages/store-traits/custom-function-mut","title":"CustomFunctionMut","description":"By implementing both the CustomFunction and CustomFunctionMut traits, users can create, use, and delete user-level custom functions. Although GlueSQL plans to continuously add various functions, users may still find them insufficient. In such cases, users can create their own user-level custom functions to supplement the built-in functions. Additionally, if there are repetitive business logic codes, they can be stored as custom functions.","sidebar":"autoSidebar"},"storages/developing-custom-storages/store-traits/index-mut":{"id":"storages/developing-custom-storages/store-traits/index-mut","title":"IndexMut","description":"The IndexMut trait, when implemented along with the Index trait, allows custom storage developers to provide users with the ability to create, use, and delete non-clustered indexes. Implementing the IndexMut trait enhances the storage system\'s capabilities by providing support for dynamic index management.","sidebar":"autoSidebar"},"storages/developing-custom-storages/store-traits/index-trait":{"id":"storages/developing-custom-storages/store-traits/index-trait","title":"Index","description":"The Index trait is designed to support non-clustered indexes. If you only need to support pre-built non-clustered indexes, implementing the Index trait without the IndexMut trait is sufficient. Note that clustered indexes (PRIMARY KEY) are automatically supported by the Store & StoreMut implementations. The Index trait is specifically for non-clustered index support.","sidebar":"autoSidebar"},"storages/developing-custom-storages/store-traits/metadata":{"id":"storages/developing-custom-storages/store-traits/metadata","title":"Metadata","description":"The Metadata trait is an optional implementation for providing additional metadata support in GlueSQL. GlueSQL does not enforce any specific metadata implementation, allowing custom storage developers to decide which type of metadata, such as create time, modify time, etc., they want to provide.","sidebar":"autoSidebar"},"storages/developing-custom-storages/store-traits/store":{"id":"storages/developing-custom-storages/store-traits/store","title":"Store","description":"The Store trait is the most essential trait to implement for custom storage. Simply by implementing the Store trait, you can support SELECT queries in SQL. You may want to analyze and retrieve data from log files or external APIs using SQL. In this case, having only SELECT queries available is sufficient, and there might not be any need for data modification. In such scenarios, implementing GlueSQL\'s Store trait alone would be adequate.","sidebar":"autoSidebar"},"storages/developing-custom-storages/store-traits/store-mut":{"id":"storages/developing-custom-storages/store-traits/store-mut","title":"StoreMut","description":"While the Store trait is for supporting SELECT queries and reading data, the StoreMut trait is for modifying data. Implementing the StoreMut trait requires the implementation of the Store trait as well. By implementing both the Store and StoreMut traits, you can support most of the commonly used SQL statements. Additionally, you can use the Test Suite to utilize the integration test set provided by GlueSQL. Custom storage developers can verify their own Store & StoreMut implementations by checking if they pass all the tests provided in the Test Suite.","sidebar":"autoSidebar"},"storages/developing-custom-storages/store-traits/transaction":{"id":"storages/developing-custom-storages/store-traits/transaction","title":"Transaction","description":"While transactions are often considered an essential feature for databases, GlueSQL treats transactions as an optional trait. Custom storage developers can choose whether or not to support transactions in their storage implementation. Transactions can be quite heavy and expensive in terms of performance.","sidebar":"autoSidebar"},"storages/developing-custom-storages/using-test-suite":{"id":"storages/developing-custom-storages/using-test-suite","title":"Using the Test Suite","description":"The GlueSQL Test Suite is a valuable tool for validating your custom storage implementation. By using the provided test sets, you can ensure that your storage implementation adheres to the required specifications and works as expected with GlueSQL.","sidebar":"autoSidebar"},"storages/intro":{"id":"storages/intro","title":"Introduction","description":"GlueSQL is not only suitable for use as a conventional database, but one of its key features is the ability for anyone to easily adapt SQL and the AST Builder to their desired file or storage system. This adaptability is achieved through the following topics covered in this section:","sidebar":"autoSidebar"},"storages/supported-storages/composite-storage":{"id":"storages/supported-storages/composite-storage","title":"Composite Storage","description":"Introduction","sidebar":"autoSidebar"},"storages/supported-storages/idb-storage":{"id":"storages/supported-storages/idb-storage","title":"IndexedDB Storage","description":"Introduction","sidebar":"autoSidebar"},"storages/supported-storages/json-storage":{"id":"storages/supported-storages/json-storage","title":"JSON Storage","description":"Introduction","sidebar":"autoSidebar"},"storages/supported-storages/memory-storage":{"id":"storages/supported-storages/memory-storage","title":"Memory Storage","description":"MemoryStorage is a foundational storage option designed for in-memory, non-persistent data. Despite its simplicity, it is robust enough for use in production environments.","sidebar":"autoSidebar"},"storages/supported-storages/shared-memory-storage":{"id":"storages/supported-storages/shared-memory-storage","title":"Shared Memory Storage","description":"SharedMemoryStorage is a storage option designed to provide more comfortable usage of MemoryStorage in concurrent environments. Although it doesn\'t operate in parallel, it makes accessing the same data from multiple threads simultaneously more convenient.","sidebar":"autoSidebar"},"storages/supported-storages/sled-storage":{"id":"storages/supported-storages/sled-storage","title":"Sled Storage","description":"SledStorage is currently the representative persistent data storage for GlueSQL. As the name suggests, it\'s a storage option based on the Sled key-value embedded database built in Rust (Sled on Github).","sidebar":"autoSidebar"},"storages/supported-storages/web-storage":{"id":"storages/supported-storages/web-storage","title":"WebStorage (local & session)","description":"WebStorage - yes, the localStorage and sessionStorage you\'re familiar with. With GlueSQL, you can use SQL to interact with these storages!","sidebar":"autoSidebar"}}}')}}]); \ No newline at end of file diff --git a/docs/dev/assets/js/935f2afb.a58568b0.js b/docs/dev/assets/js/935f2afb.a58568b0.js new file mode 100644 index 00000000..be23b766 --- /dev/null +++ b/docs/dev/assets/js/935f2afb.a58568b0.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs=self.webpackChunkdocs||[]).push([[53],{1109:t=>{t.exports=JSON.parse('{"pluginId":"default","version":"current","label":"Next","banner":null,"badge":false,"noIndex":false,"className":"docs-version-current","isLast":true,"docsSidebars":{"autoSidebar":[{"type":"link","label":"Introduction","href":"/docs/dev/","docId":"index"},{"type":"category","label":"Getting Started","collapsible":true,"collapsed":false,"items":[{"type":"link","label":"Rust","href":"/docs/dev/getting-started/rust","docId":"getting-started/rust"},{"type":"link","label":"JavaScript (Web Browser)","href":"/docs/dev/getting-started/javascript-web","docId":"getting-started/javascript-web"},{"type":"link","label":"Node.js","href":"/docs/dev/getting-started/nodejs","docId":"getting-started/nodejs"},{"type":"link","label":"Command-Line Interface","href":"/docs/dev/getting-started/cli","docId":"getting-started/cli"}]},{"type":"category","label":"SQL Syntax","collapsible":true,"collapsed":false,"items":[{"type":"link","label":"Introduction","href":"/docs/dev/sql-syntax/intro","docId":"sql-syntax/intro"},{"type":"category","label":"Statements","collapsible":true,"collapsed":true,"items":[{"type":"category","label":"Querying","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"WHERE","href":"/docs/dev/sql-syntax/statements/querying/where","docId":"sql-syntax/statements/querying/where"},{"type":"link","label":"JOIN","href":"/docs/dev/sql-syntax/statements/querying/join","docId":"sql-syntax/statements/querying/join"},{"type":"link","label":"LIMIT & OFFSET","href":"/docs/dev/sql-syntax/statements/querying/limit","docId":"sql-syntax/statements/querying/limit"},{"type":"link","label":"Aggregation","href":"/docs/dev/sql-syntax/statements/querying/aggregation","docId":"sql-syntax/statements/querying/aggregation"},{"type":"link","label":"Schemaless Data","href":"/docs/dev/sql-syntax/statements/querying/schemaless","docId":"sql-syntax/statements/querying/schemaless"}]},{"type":"category","label":"Data definition","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"CREATE TABLE","href":"/docs/dev/sql-syntax/statements/data-definition/create-table","docId":"sql-syntax/statements/data-definition/create-table"},{"type":"link","label":"DROP TABLE","href":"/docs/dev/sql-syntax/statements/data-definition/drop-table","docId":"sql-syntax/statements/data-definition/drop-table"},{"type":"link","label":"CREATE INDEX","href":"/docs/dev/sql-syntax/statements/data-definition/create-index","docId":"sql-syntax/statements/data-definition/create-index"},{"type":"link","label":"DROP INDEX","href":"/docs/dev/sql-syntax/statements/data-definition/drop-index","docId":"sql-syntax/statements/data-definition/drop-index"},{"type":"link","label":"ALTER TABLE","href":"/docs/dev/sql-syntax/statements/data-definition/alter-table","docId":"sql-syntax/statements/data-definition/alter-table"}]},{"type":"category","label":"Data manipulation","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"INSERT","href":"/docs/dev/sql-syntax/statements/data-manipulation/insert","docId":"sql-syntax/statements/data-manipulation/insert"},{"type":"link","label":"UPDATE","href":"/docs/dev/sql-syntax/statements/data-manipulation/update","docId":"sql-syntax/statements/data-manipulation/update"},{"type":"link","label":"DELETE","href":"/docs/dev/sql-syntax/statements/data-manipulation/delete","docId":"sql-syntax/statements/data-manipulation/delete"}]},{"type":"link","label":"Transaction","href":"/docs/dev/sql-syntax/statements/transaction","docId":"sql-syntax/statements/transaction"},{"type":"category","label":"Metadata","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"SHOW TABLES","href":"/docs/dev/sql-syntax/statements/metadata/show-tables","docId":"sql-syntax/statements/metadata/show-tables"},{"type":"link","label":"Data Dictionary","href":"/docs/dev/sql-syntax/statements/metadata/data-dictionary","docId":"sql-syntax/statements/metadata/data-dictionary"}]}]},{"type":"category","label":"Data types","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"BOOLEAN","href":"/docs/dev/sql-syntax/data-types/boolean","docId":"sql-syntax/data-types/boolean"},{"type":"link","label":"Integer Types","href":"/docs/dev/sql-syntax/data-types/integers","docId":"sql-syntax/data-types/integers"},{"type":"link","label":"FLOAT","href":"/docs/dev/sql-syntax/data-types/float","docId":"sql-syntax/data-types/float"},{"type":"link","label":"TEXT","href":"/docs/dev/sql-syntax/data-types/text","docId":"sql-syntax/data-types/text"},{"type":"link","label":"DECIMAL","href":"/docs/dev/sql-syntax/data-types/decimal","docId":"sql-syntax/data-types/decimal"},{"type":"link","label":"DATE","href":"/docs/dev/sql-syntax/data-types/date","docId":"sql-syntax/data-types/date"},{"type":"link","label":"TIMESTAMP","href":"/docs/dev/sql-syntax/data-types/timestamp","docId":"sql-syntax/data-types/timestamp"},{"type":"link","label":"TIME","href":"/docs/dev/sql-syntax/data-types/time","docId":"sql-syntax/data-types/time"},{"type":"link","label":"INTERVAL","href":"/docs/dev/sql-syntax/data-types/interval","docId":"sql-syntax/data-types/interval"},{"type":"link","label":"LIST","href":"/docs/dev/sql-syntax/data-types/list","docId":"sql-syntax/data-types/list"},{"type":"link","label":"MAP","href":"/docs/dev/sql-syntax/data-types/map","docId":"sql-syntax/data-types/map"},{"type":"link","label":"BYTEA","href":"/docs/dev/sql-syntax/data-types/bytea","docId":"sql-syntax/data-types/bytea"},{"type":"link","label":"INET","href":"/docs/dev/sql-syntax/data-types/inet","docId":"sql-syntax/data-types/inet"},{"type":"link","label":"UUID","href":"/docs/dev/sql-syntax/data-types/uuid","docId":"sql-syntax/data-types/uuid"}]},{"type":"category","label":"Functions","collapsible":true,"collapsed":true,"items":[{"type":"category","label":"Text","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"ASCII","href":"/docs/dev/sql-syntax/functions/text/ascii","docId":"sql-syntax/functions/text/ascii"},{"type":"link","label":"CHR","href":"/docs/dev/sql-syntax/functions/text/chr","docId":"sql-syntax/functions/text/chr"},{"type":"link","label":"CONCAT_WS","href":"/docs/dev/sql-syntax/functions/text/concat-ws","docId":"sql-syntax/functions/text/concat-ws"},{"type":"link","label":"CONCAT","href":"/docs/dev/sql-syntax/functions/text/concat","docId":"sql-syntax/functions/text/concat"},{"type":"link","label":"FIND_IDX","href":"/docs/dev/sql-syntax/functions/text/find-idx","docId":"sql-syntax/functions/text/find-idx"},{"type":"link","label":"INITCAP","href":"/docs/dev/sql-syntax/functions/text/initcap","docId":"sql-syntax/functions/text/initcap"},{"type":"link","label":"LEFT","href":"/docs/dev/sql-syntax/functions/text/left","docId":"sql-syntax/functions/text/left"},{"type":"link","label":"LOWER","href":"/docs/dev/sql-syntax/functions/text/lower","docId":"sql-syntax/functions/text/lower"},{"type":"link","label":"LPAD","href":"/docs/dev/sql-syntax/functions/text/lpad","docId":"sql-syntax/functions/text/lpad"},{"type":"link","label":"LTRIM","href":"/docs/dev/sql-syntax/functions/text/ltrim","docId":"sql-syntax/functions/text/ltrim"},{"type":"link","label":"POSITION","href":"/docs/dev/sql-syntax/functions/text/position","docId":"sql-syntax/functions/text/position"},{"type":"link","label":"REPEAT","href":"/docs/dev/sql-syntax/functions/text/repeat","docId":"sql-syntax/functions/text/repeat"},{"type":"link","label":"REVERSE","href":"/docs/dev/sql-syntax/functions/text/reverse","docId":"sql-syntax/functions/text/reverse"},{"type":"link","label":"RIGHT","href":"/docs/dev/sql-syntax/functions/text/right","docId":"sql-syntax/functions/text/right"},{"type":"link","label":"RPAD","href":"/docs/dev/sql-syntax/functions/text/rpad","docId":"sql-syntax/functions/text/rpad"},{"type":"link","label":"RTRIM","href":"/docs/dev/sql-syntax/functions/text/rtrim","docId":"sql-syntax/functions/text/rtrim"},{"type":"link","label":"SUBSTR","href":"/docs/dev/sql-syntax/functions/text/substr","docId":"sql-syntax/functions/text/substr"},{"type":"link","label":"TRIM","href":"/docs/dev/sql-syntax/functions/text/trim","docId":"sql-syntax/functions/text/trim"},{"type":"link","label":"UPPER","href":"/docs/dev/sql-syntax/functions/text/upper","docId":"sql-syntax/functions/text/upper"}]},{"type":"category","label":"Math","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"ABS","href":"/docs/dev/sql-syntax/functions/math/abs","docId":"sql-syntax/functions/math/abs"},{"type":"link","label":"ACOS","href":"/docs/dev/sql-syntax/functions/math/acos","docId":"sql-syntax/functions/math/acos"},{"type":"link","label":"ASIN","href":"/docs/dev/sql-syntax/functions/math/asin","docId":"sql-syntax/functions/math/asin"},{"type":"link","label":"ATAN","href":"/docs/dev/sql-syntax/functions/math/atan","docId":"sql-syntax/functions/math/atan"},{"type":"link","label":"CEIL","href":"/docs/dev/sql-syntax/functions/math/ceil","docId":"sql-syntax/functions/math/ceil"},{"type":"link","label":"COS","href":"/docs/dev/sql-syntax/functions/math/cos","docId":"sql-syntax/functions/math/cos"},{"type":"link","label":"DEGREES","href":"/docs/dev/sql-syntax/functions/math/degrees","docId":"sql-syntax/functions/math/degrees"},{"type":"link","label":"DIV","href":"/docs/dev/sql-syntax/functions/math/div","docId":"sql-syntax/functions/math/div"},{"type":"link","label":"EXP","href":"/docs/dev/sql-syntax/functions/math/exp","docId":"sql-syntax/functions/math/exp"},{"type":"link","label":"FLOOR","href":"/docs/dev/sql-syntax/functions/math/floor","docId":"sql-syntax/functions/math/floor"},{"type":"link","label":"GCD","href":"/docs/dev/sql-syntax/functions/math/gcd","docId":"sql-syntax/functions/math/gcd"},{"type":"link","label":"LCM","href":"/docs/dev/sql-syntax/functions/math/lcm","docId":"sql-syntax/functions/math/lcm"},{"type":"link","label":"LN","href":"/docs/dev/sql-syntax/functions/math/ln","docId":"sql-syntax/functions/math/ln"},{"type":"link","label":"LOG","href":"/docs/dev/sql-syntax/functions/math/log","docId":"sql-syntax/functions/math/log"},{"type":"link","label":"LOG10","href":"/docs/dev/sql-syntax/functions/math/log10","docId":"sql-syntax/functions/math/log10"},{"type":"link","label":"LOG2","href":"/docs/dev/sql-syntax/functions/math/log2","docId":"sql-syntax/functions/math/log2"},{"type":"link","label":"MOD","href":"/docs/dev/sql-syntax/functions/math/mod","docId":"sql-syntax/functions/math/mod"},{"type":"link","label":"PI","href":"/docs/dev/sql-syntax/functions/math/pi","docId":"sql-syntax/functions/math/pi"},{"type":"link","label":"POWER","href":"/docs/dev/sql-syntax/functions/math/power","docId":"sql-syntax/functions/math/power"},{"type":"link","label":"RADIANS","href":"/docs/dev/sql-syntax/functions/math/radians","docId":"sql-syntax/functions/math/radians"},{"type":"link","label":"RAND","href":"/docs/dev/sql-syntax/functions/math/rand","docId":"sql-syntax/functions/math/rand"},{"type":"link","label":"ROUND","href":"/docs/dev/sql-syntax/functions/math/round","docId":"sql-syntax/functions/math/round"},{"type":"link","label":"SIGN","href":"/docs/dev/sql-syntax/functions/math/sign","docId":"sql-syntax/functions/math/sign"},{"type":"link","label":"SIN","href":"/docs/dev/sql-syntax/functions/math/sin","docId":"sql-syntax/functions/math/sin"},{"type":"link","label":"SQRT","href":"/docs/dev/sql-syntax/functions/math/sqrt","docId":"sql-syntax/functions/math/sqrt"},{"type":"link","label":"TAN","href":"/docs/dev/sql-syntax/functions/math/tan","docId":"sql-syntax/functions/math/tan"}]},{"type":"category","label":"Date & Time","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"EXTRACT","href":"/docs/dev/sql-syntax/functions/datetime/extract","docId":"sql-syntax/functions/datetime/extract"},{"type":"link","label":"FORMAT","href":"/docs/dev/sql-syntax/functions/datetime/format","docId":"sql-syntax/functions/datetime/format"},{"type":"link","label":"NOW","href":"/docs/dev/sql-syntax/functions/datetime/now","docId":"sql-syntax/functions/datetime/now"},{"type":"link","label":"TO_DATE","href":"/docs/dev/sql-syntax/functions/datetime/to-date","docId":"sql-syntax/functions/datetime/to-date"},{"type":"link","label":"TO_TIME","href":"/docs/dev/sql-syntax/functions/datetime/to-time","docId":"sql-syntax/functions/datetime/to-time"},{"type":"link","label":"TO_TIMESTAMP","href":"/docs/dev/sql-syntax/functions/datetime/to-timestamp","docId":"sql-syntax/functions/datetime/to-timestamp"}]},{"type":"category","label":"List & Map","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"APPEND","href":"/docs/dev/sql-syntax/functions/list-map/append","docId":"sql-syntax/functions/list-map/append"},{"type":"link","label":"CONCAT","href":"/docs/dev/sql-syntax/functions/list-map/concat","docId":"sql-syntax/functions/list-map/concat"},{"type":"link","label":"PREPEND","href":"/docs/dev/sql-syntax/functions/list-map/prepend","docId":"sql-syntax/functions/list-map/prepend"},{"type":"link","label":"SQL Function - \\"SPLICE\\"","href":"/docs/dev/sql-syntax/functions/list-map/splice","docId":"sql-syntax/functions/list-map/splice"}]},{"type":"category","label":"Geometry","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"CALC_DISTANCE","href":"/docs/dev/sql-syntax/functions/geometry/calc-distance","docId":"sql-syntax/functions/geometry/calc-distance"},{"type":"link","label":"GET_X","href":"/docs/dev/sql-syntax/functions/geometry/get-x","docId":"sql-syntax/functions/geometry/get-x"},{"type":"link","label":"GET_Y","href":"/docs/dev/sql-syntax/functions/geometry/get-y","docId":"sql-syntax/functions/geometry/get-y"},{"type":"link","label":"POINT","href":"/docs/dev/sql-syntax/functions/geometry/point","docId":"sql-syntax/functions/geometry/point"}]},{"type":"category","label":"Others","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"CAST","href":"/docs/dev/sql-syntax/functions/others/cast","docId":"sql-syntax/functions/others/cast"},{"type":"link","label":"GENERATE_UUID","href":"/docs/dev/sql-syntax/functions/others/generate-uuid","docId":"sql-syntax/functions/others/generate-uuid"},{"type":"link","label":"IFNULL","href":"/docs/dev/sql-syntax/functions/others/ifnull","docId":"sql-syntax/functions/others/ifnull"}]}]}]},{"type":"category","label":"AST Builder","collapsible":true,"collapsed":false,"items":[{"type":"link","label":"Introduction","href":"/docs/dev/ast-builder/intro","docId":"ast-builder/intro"},{"type":"category","label":"Statements","collapsible":true,"collapsed":true,"items":[{"type":"category","label":"Querying","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"Fetching Data from Storage","href":"/docs/dev/ast-builder/statements/querying/fetching-data-from-storage","docId":"ast-builder/statements/querying/fetching-data-from-storage"},{"type":"link","label":"Using Preloaded Data","href":"/docs/dev/ast-builder/statements/querying/using-preloaded-data","docId":"ast-builder/statements/querying/using-preloaded-data"},{"type":"link","label":"Creating Derived Subqueries","href":"/docs/dev/ast-builder/statements/querying/creating-derived-subqueries","docId":"ast-builder/statements/querying/creating-derived-subqueries"},{"type":"link","label":"Data Aggregation","href":"/docs/dev/ast-builder/statements/querying/data-aggregation","docId":"ast-builder/statements/querying/data-aggregation"},{"type":"link","label":"Data Injection","href":"/docs/dev/ast-builder/statements/querying/data-injection","docId":"ast-builder/statements/querying/data-injection"},{"type":"link","label":"Data Joining","href":"/docs/dev/ast-builder/statements/querying/data-joining","docId":"ast-builder/statements/querying/data-joining"},{"type":"link","label":"Data Selection and Projection","href":"/docs/dev/ast-builder/statements/querying/data-selection-and-projection","docId":"ast-builder/statements/querying/data-selection-and-projection"},{"type":"link","label":"Data Sorting and Limiting","href":"/docs/dev/ast-builder/statements/querying/data-sorting-and-limiting","docId":"ast-builder/statements/querying/data-sorting-and-limiting"}]},{"type":"category","label":"Data Manipulation","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"Inserting Data","href":"/docs/dev/ast-builder/statements/data-manipulation/inserting-data","docId":"ast-builder/statements/data-manipulation/inserting-data"},{"type":"link","label":"Updating Data","href":"/docs/dev/ast-builder/statements/data-manipulation/updating-data","docId":"ast-builder/statements/data-manipulation/updating-data"},{"type":"link","label":"Deleting Data","href":"/docs/dev/ast-builder/statements/data-manipulation/deleting-data","docId":"ast-builder/statements/data-manipulation/deleting-data"}]}]},{"type":"category","label":"Expressions","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"Conditional","href":"/docs/dev/ast-builder/expressions/conditional","docId":"ast-builder/expressions/conditional"},{"type":"link","label":"Nested","href":"/docs/dev/ast-builder/expressions/nested","docId":"ast-builder/expressions/nested"},{"type":"link","label":"Operator Based","href":"/docs/dev/ast-builder/expressions/operator-based","docId":"ast-builder/expressions/operator-based"},{"type":"link","label":"Pattern Matching","href":"/docs/dev/ast-builder/expressions/pattern-matching","docId":"ast-builder/expressions/pattern-matching"},{"type":"link","label":"Value Checking","href":"/docs/dev/ast-builder/expressions/value-checking","docId":"ast-builder/expressions/value-checking"}]},{"type":"category","label":"Functions","collapsible":true,"collapsed":true,"items":[{"type":"category","label":"Text","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"Case Conversion","href":"/docs/dev/ast-builder/functions/text/case-conversion","docId":"ast-builder/functions/text/case-conversion"},{"type":"link","label":"Character Conversion","href":"/docs/dev/ast-builder/functions/text/character-conversion","docId":"ast-builder/functions/text/character-conversion"},{"type":"link","label":"Padding","href":"/docs/dev/ast-builder/functions/text/padding","docId":"ast-builder/functions/text/padding"},{"type":"link","label":"Position and Indexing","href":"/docs/dev/ast-builder/functions/text/position-and-indexing","docId":"ast-builder/functions/text/position-and-indexing"},{"type":"link","label":"Text Manipulation","href":"/docs/dev/ast-builder/functions/text/text-manipulation","docId":"ast-builder/functions/text/text-manipulation"},{"type":"link","label":"Trimming","href":"/docs/dev/ast-builder/functions/text/trimming","docId":"ast-builder/functions/text/trimming"}]},{"type":"category","label":"Math","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"Basic Arithmetic","href":"/docs/dev/ast-builder/functions/math/basic-arithmetic","docId":"ast-builder/functions/math/basic-arithmetic"},{"type":"link","label":"Conversion","href":"/docs/dev/ast-builder/functions/math/conversion","docId":"ast-builder/functions/math/conversion"},{"type":"link","label":"Logarithmic and Exponential","href":"/docs/dev/ast-builder/functions/math/logarithmic-and-exponential","docId":"ast-builder/functions/math/logarithmic-and-exponential"},{"type":"link","label":"Rounding","href":"/docs/dev/ast-builder/functions/math/rounding","docId":"ast-builder/functions/math/rounding"},{"type":"link","label":"Special Mathematical","href":"/docs/dev/ast-builder/functions/math/special-mathematical","docId":"ast-builder/functions/math/special-mathematical"},{"type":"link","label":"Trigonometric","href":"/docs/dev/ast-builder/functions/math/trigonometric","docId":"ast-builder/functions/math/trigonometric"}]},{"type":"category","label":"Date & Time","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"Conversion","href":"/docs/dev/ast-builder/functions/date-&-time/conversion","docId":"ast-builder/functions/date-&-time/conversion"},{"type":"link","label":"Current Date and Time","href":"/docs/dev/ast-builder/functions/date-&-time/current-date-and-time","docId":"ast-builder/functions/date-&-time/current-date-and-time"},{"type":"link","label":"Date and Time Extraction","href":"/docs/dev/ast-builder/functions/date-&-time/date-and-time-extraction","docId":"ast-builder/functions/date-&-time/date-and-time-extraction"},{"type":"link","label":"Formatting","href":"/docs/dev/ast-builder/functions/date-&-time/formatting","docId":"ast-builder/functions/date-&-time/formatting"}]},{"type":"category","label":"List & Map","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"List and Map Concatenation","href":"/docs/dev/ast-builder/functions/list-&-map/list-and-map-concatenation","docId":"ast-builder/functions/list-&-map/list-and-map-concatenation"},{"type":"link","label":"List Manipulation","href":"/docs/dev/ast-builder/functions/list-&-map/list-manipulation","docId":"ast-builder/functions/list-&-map/list-manipulation"}]},{"type":"category","label":"Geometry","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"Coordinate Extraction","href":"/docs/dev/ast-builder/functions/geometry/coordinate-extraction","docId":"ast-builder/functions/geometry/coordinate-extraction"},{"type":"link","label":"Distance Calculation","href":"/docs/dev/ast-builder/functions/geometry/distance-calculation","docId":"ast-builder/functions/geometry/distance-calculation"},{"type":"link","label":"Point Creation","href":"/docs/dev/ast-builder/functions/geometry/point-creation","docId":"ast-builder/functions/geometry/point-creation"}]},{"type":"category","label":"Others","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"Null Handling","href":"/docs/dev/ast-builder/functions/others/null-handling","docId":"ast-builder/functions/others/null-handling"},{"type":"link","label":"Type Conversion","href":"/docs/dev/ast-builder/functions/others/type-conversion","docId":"ast-builder/functions/others/type-conversion"},{"type":"link","label":"Unique Identifier","href":"/docs/dev/ast-builder/functions/others/unique-identifier","docId":"ast-builder/functions/others/unique-identifier"}]}]}]},{"type":"category","label":"Storages","collapsible":true,"collapsed":false,"items":[{"type":"link","label":"Introduction","href":"/docs/dev/storages/intro","docId":"storages/intro"},{"type":"category","label":"Supported Storages","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"Memory Storage","href":"/docs/dev/storages/supported-storages/memory-storage","docId":"storages/supported-storages/memory-storage"},{"type":"link","label":"Shared Memory Storage","href":"/docs/dev/storages/supported-storages/shared-memory-storage","docId":"storages/supported-storages/shared-memory-storage"},{"type":"link","label":"Sled Storage","href":"/docs/dev/storages/supported-storages/sled-storage","docId":"storages/supported-storages/sled-storage"},{"type":"link","label":"JSON Storage","href":"/docs/dev/storages/supported-storages/json-storage","docId":"storages/supported-storages/json-storage"},{"type":"link","label":"WebStorage (local & session)","href":"/docs/dev/storages/supported-storages/web-storage","docId":"storages/supported-storages/web-storage"},{"type":"link","label":"IndexedDB Storage","href":"/docs/dev/storages/supported-storages/idb-storage","docId":"storages/supported-storages/idb-storage"},{"type":"link","label":"Composite Storage","href":"/docs/dev/storages/supported-storages/composite-storage","docId":"storages/supported-storages/composite-storage"}]},{"type":"category","label":"Developing Custom Storages","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"Introduction","href":"/docs/dev/storages/developing-custom-storages/intro","docId":"storages/developing-custom-storages/intro"},{"type":"category","label":"Understanding Store traits","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"Store","href":"/docs/dev/storages/developing-custom-storages/store-traits/store","docId":"storages/developing-custom-storages/store-traits/store"},{"type":"link","label":"StoreMut","href":"/docs/dev/storages/developing-custom-storages/store-traits/store-mut","docId":"storages/developing-custom-storages/store-traits/store-mut"},{"type":"link","label":"AlterTable","href":"/docs/dev/storages/developing-custom-storages/store-traits/alter-table","docId":"storages/developing-custom-storages/store-traits/alter-table"},{"type":"link","label":"Transaction","href":"/docs/dev/storages/developing-custom-storages/store-traits/transaction","docId":"storages/developing-custom-storages/store-traits/transaction"},{"type":"link","label":"CustomFunction","href":"/docs/dev/storages/developing-custom-storages/store-traits/custom-function","docId":"storages/developing-custom-storages/store-traits/custom-function"},{"type":"link","label":"CustomFunctionMut","href":"/docs/dev/storages/developing-custom-storages/store-traits/custom-function-mut","docId":"storages/developing-custom-storages/store-traits/custom-function-mut"},{"type":"link","label":"Index","href":"/docs/dev/storages/developing-custom-storages/store-traits/index-trait","docId":"storages/developing-custom-storages/store-traits/index-trait"},{"type":"link","label":"IndexMut","href":"/docs/dev/storages/developing-custom-storages/store-traits/index-mut","docId":"storages/developing-custom-storages/store-traits/index-mut"},{"type":"link","label":"Metadata","href":"/docs/dev/storages/developing-custom-storages/store-traits/metadata","docId":"storages/developing-custom-storages/store-traits/metadata"}]},{"type":"link","label":"Using the Test Suite","href":"/docs/dev/storages/developing-custom-storages/using-test-suite","docId":"storages/developing-custom-storages/using-test-suite"}]}]}]},"docs":{"ast-builder/expressions/conditional":{"id":"ast-builder/expressions/conditional","title":"Conditional","description":"Todo","sidebar":"autoSidebar"},"ast-builder/expressions/nested":{"id":"ast-builder/expressions/nested","title":"Nested","description":"Todo","sidebar":"autoSidebar"},"ast-builder/expressions/operator-based":{"id":"ast-builder/expressions/operator-based","title":"Operator Based","description":"Todo","sidebar":"autoSidebar"},"ast-builder/expressions/pattern-matching":{"id":"ast-builder/expressions/pattern-matching","title":"Pattern Matching","description":"Pattern matching is a crucial feature in SQL that allows you to match rows based on specific patterns in a column. GlueSQL provides 4 pattern matching operators: like, ilike, notlike, and notilike.","sidebar":"autoSidebar"},"ast-builder/expressions/value-checking":{"id":"ast-builder/expressions/value-checking","title":"Value Checking","description":"Todo","sidebar":"autoSidebar"},"ast-builder/functions/date-&-time/conversion":{"id":"ast-builder/functions/date-&-time/conversion","title":"Conversion","description":"GlueSQL provides date and time conversion functions that allow you to convert text data to datetime data types such as Date, Time, and Timestamp. These functions are todate, totime, and to_timestamp.","sidebar":"autoSidebar"},"ast-builder/functions/date-&-time/current-date-and-time":{"id":"ast-builder/functions/date-&-time/current-date-and-time","title":"Current Date and Time","description":"GlueSQL provides a function to get the current date and time: now.","sidebar":"autoSidebar"},"ast-builder/functions/date-&-time/date-and-time-extraction":{"id":"ast-builder/functions/date-&-time/date-and-time-extraction","title":"Date and Time Extraction","description":"Todo","sidebar":"autoSidebar"},"ast-builder/functions/date-&-time/formatting":{"id":"ast-builder/functions/date-&-time/formatting","title":"Formatting","description":"In GlueSQL, you can format date, time, and timestamp values to a specific format using the format function.","sidebar":"autoSidebar"},"ast-builder/functions/geometry/coordinate-extraction":{"id":"ast-builder/functions/geometry/coordinate-extraction","title":"Coordinate Extraction","description":"Todo","sidebar":"autoSidebar"},"ast-builder/functions/geometry/distance-calculation":{"id":"ast-builder/functions/geometry/distance-calculation","title":"Distance Calculation","description":"Todo","sidebar":"autoSidebar"},"ast-builder/functions/geometry/point-creation":{"id":"ast-builder/functions/geometry/point-creation","title":"Point Creation","description":"Todo","sidebar":"autoSidebar"},"ast-builder/functions/list-&-map/list-and-map-concatenation":{"id":"ast-builder/functions/list-&-map/list-and-map-concatenation","title":"List and Map Concatenation","description":"Todo","sidebar":"autoSidebar"},"ast-builder/functions/list-&-map/list-manipulation":{"id":"ast-builder/functions/list-&-map/list-manipulation","title":"List Manipulation","description":"Todo","sidebar":"autoSidebar"},"ast-builder/functions/math/basic-arithmetic":{"id":"ast-builder/functions/math/basic-arithmetic","title":"Basic Arithmetic","description":"GlueSQL provides a number of basic arithmetic operations such as absolute value (abs), division (divide), modulo (modulo), greatest common divisor (gcd), and least common multiple (lcm).","sidebar":"autoSidebar"},"ast-builder/functions/math/conversion":{"id":"ast-builder/functions/math/conversion","title":"Conversion","description":"The AST (Abstract Syntax Tree) Builder in GlueSQL provides mathematical conversion functions like degrees and radians. These functions convert angles expressed in radians to degrees and vice versa.","sidebar":"autoSidebar"},"ast-builder/functions/math/logarithmic-and-exponential":{"id":"ast-builder/functions/math/logarithmic-and-exponential","title":"Logarithmic and Exponential","description":"Todo","sidebar":"autoSidebar"},"ast-builder/functions/math/rounding":{"id":"ast-builder/functions/math/rounding","title":"Rounding","description":"The AST (Abstract Syntax Tree) Builder in GlueSQL provides several mathematical functions, including round, ceil, and floor. These functions are used to perform rounding operations on floating-point numbers.","sidebar":"autoSidebar"},"ast-builder/functions/math/special-mathematical":{"id":"ast-builder/functions/math/special-mathematical","title":"Special Mathematical","description":"Todo","sidebar":"autoSidebar"},"ast-builder/functions/math/trigonometric":{"id":"ast-builder/functions/math/trigonometric","title":"Trigonometric","description":"Todo","sidebar":"autoSidebar"},"ast-builder/functions/others/null-handling":{"id":"ast-builder/functions/others/null-handling","title":"Null Handling","description":"In some cases, you may need to handle NULL values in your database. GlueSQL provides a function called ifnull to handle these cases.","sidebar":"autoSidebar"},"ast-builder/functions/others/type-conversion":{"id":"ast-builder/functions/others/type-conversion","title":"Type Conversion","description":"Todo","sidebar":"autoSidebar"},"ast-builder/functions/others/unique-identifier":{"id":"ast-builder/functions/others/unique-identifier","title":"Unique Identifier","description":"Todo","sidebar":"autoSidebar"},"ast-builder/functions/text/case-conversion":{"id":"ast-builder/functions/text/case-conversion","title":"Case Conversion","description":"GlueSQL provides several text case conversion functions that allow you to convert text data to upper case, lower case or capitalize each word in a string.","sidebar":"autoSidebar"},"ast-builder/functions/text/character-conversion":{"id":"ast-builder/functions/text/character-conversion","title":"Character Conversion","description":"Todo","sidebar":"autoSidebar"},"ast-builder/functions/text/padding":{"id":"ast-builder/functions/text/padding","title":"Padding","description":"Todo","sidebar":"autoSidebar"},"ast-builder/functions/text/position-and-indexing":{"id":"ast-builder/functions/text/position-and-indexing","title":"Position and Indexing","description":"GlueSQL provides several functions for text manipulation, including finding the index of a substring (find_idx), finding the position of a substring (position), and getting the leftmost or rightmost characters (left and right).","sidebar":"autoSidebar"},"ast-builder/functions/text/text-manipulation":{"id":"ast-builder/functions/text/text-manipulation","title":"Text Manipulation","description":"Todo","sidebar":"autoSidebar"},"ast-builder/functions/text/trimming":{"id":"ast-builder/functions/text/trimming","title":"Trimming","description":"GlueSQL provides several text trimming functions that allow you to remove leading or trailing characters from a text string.","sidebar":"autoSidebar"},"ast-builder/intro":{"id":"ast-builder/intro","title":"Introduction","description":"GlueSQL offers two ways to create and execute queries: using SQL statements or using the AST Builder. In this introductory page, we will focus on the AST Builder.","sidebar":"autoSidebar"},"ast-builder/statements/data-manipulation/deleting-data":{"id":"ast-builder/statements/data-manipulation/deleting-data","title":"Deleting Data","description":"In this section, we will discuss how to delete data from a table using GlueSQL.","sidebar":"autoSidebar"},"ast-builder/statements/data-manipulation/inserting-data":{"id":"ast-builder/statements/data-manipulation/inserting-data","title":"Inserting Data","description":"In this section, we will discuss how to insert data into a table using GlueSQL.","sidebar":"autoSidebar"},"ast-builder/statements/data-manipulation/updating-data":{"id":"ast-builder/statements/data-manipulation/updating-data","title":"Updating Data","description":"In this section, we will discuss how to update data in a table using GlueSQL.","sidebar":"autoSidebar"},"ast-builder/statements/querying/creating-derived-subqueries":{"id":"ast-builder/statements/querying/creating-derived-subqueries","title":"Creating Derived Subqueries","description":"This document covers the aliasas functionality of the AST Builder in the GlueSQL project. The aliasas method allows you to create a derived subquery, which is similar to subqueries in SQL. It gives you the ability to use the output of a query as a table to perform further queries.","sidebar":"autoSidebar"},"ast-builder/statements/querying/data-aggregation":{"id":"ast-builder/statements/querying/data-aggregation","title":"Data Aggregation","description":"The AST Builder API in GlueSQL allows you to construct SQL queries programmatically. This page provides an introduction to data aggregation using the AST Builder API.","sidebar":"autoSidebar"},"ast-builder/statements/querying/data-injection":{"id":"ast-builder/statements/querying/data-injection","title":"Data Injection","description":"Todo","sidebar":"autoSidebar"},"ast-builder/statements/querying/data-joining":{"id":"ast-builder/statements/querying/data-joining","title":"Data Joining","description":"Todo","sidebar":"autoSidebar"},"ast-builder/statements/querying/data-selection-and-projection":{"id":"ast-builder/statements/querying/data-selection-and-projection","title":"Data Selection and Projection","description":"Todo","sidebar":"autoSidebar"},"ast-builder/statements/querying/data-sorting-and-limiting":{"id":"ast-builder/statements/querying/data-sorting-and-limiting","title":"Data Sorting and Limiting","description":"Todo","sidebar":"autoSidebar"},"ast-builder/statements/querying/fetching-data-from-storage":{"id":"ast-builder/statements/querying/fetching-data-from-storage","title":"Fetching Data from Storage","description":"The AST Builder provides a powerful and flexible way to query data from your tables, similar to SQL\'s SELECT statement. This guide will show you how to use the AST Builder\'s table(\\"foo\\").select() method to perform various query types, including filtering, joining, grouping, ordering, and pagination.","sidebar":"autoSidebar"},"ast-builder/statements/querying/using-preloaded-data":{"id":"ast-builder/statements/querying/using-preloaded-data","title":"Using Preloaded Data","description":"This guide will show you how to use AST Builder to query data that has already been loaded into memory, as opposed to querying data from storage. This is similar to SQL\'s VALUES functionality.","sidebar":"autoSidebar"},"getting-started/cli":{"id":"getting-started/cli","title":"Command-Line Interface","description":"Introduction","sidebar":"autoSidebar"},"getting-started/javascript-web":{"id":"getting-started/javascript-web","title":"JavaScript (Web Browser)","description":"GlueSQL is a SQL database engine written in Rust, compiled to WebAssembly, and can be used in JavaScript. This guide will walk you through the process of installing and using the GlueSQL package.","sidebar":"autoSidebar"},"getting-started/nodejs":{"id":"getting-started/nodejs","title":"Node.js","description":"This guide will help you get started with GlueSQL in a Node.js project. First, install the gluesql package using npm by running the following command in your terminal:","sidebar":"autoSidebar"},"getting-started/rust":{"id":"getting-started/rust","title":"Rust","description":"To install and use GlueSQL in your Rust project, you\'ll first need to add it as a dependency from crates.io. You can do this by adding the following lines to your Cargo.toml file:","sidebar":"autoSidebar"},"index":{"id":"index","title":"Introduction","description":"crates.io","sidebar":"autoSidebar"},"sql-syntax/data-types/boolean":{"id":"sql-syntax/data-types/boolean","title":"BOOLEAN","description":"The BOOLEAN data type in SQL is used to store boolean values, which can be either TRUE or FALSE. This data type is useful for representing binary states or conditions in your data.","sidebar":"autoSidebar"},"sql-syntax/data-types/bytea":{"id":"sql-syntax/data-types/bytea","title":"BYTEA","description":"The BYTEA data type in SQL is used to store binary data, such as images, audio files, or any other type of data that needs to be stored in its raw form. In GlueSQL, the BYTEA data type is represented as a sequence of bytes.","sidebar":"autoSidebar"},"sql-syntax/data-types/date":{"id":"sql-syntax/data-types/date","title":"DATE","description":"In GlueSQL, the DATE data type is used to store date values in the format \'YYYY-MM-DD\'. Note that GlueSQL currently does not support timezones.","sidebar":"autoSidebar"},"sql-syntax/data-types/decimal":{"id":"sql-syntax/data-types/decimal","title":"DECIMAL","description":"The DECIMAL data type in SQL is used to store exact numeric values, making it suitable for financial calculations and other operations requiring a high level of precision without round-off errors. In GlueSQL, the DECIMAL data type is implemented using a pure Rust library, providing a 96-bit integer number, a scaling factor for specifying the decimal fraction, and a 1-bit sign.","sidebar":"autoSidebar"},"sql-syntax/data-types/float":{"id":"sql-syntax/data-types/float","title":"FLOAT","description":"The FLOAT data type in SQL is used to store floating-point numbers. In GlueSQL, the FLOAT data type represents a 64-bit floating-point number, providing the ability to store numbers with decimal values and a wide range of magnitude.","sidebar":"autoSidebar"},"sql-syntax/data-types/inet":{"id":"sql-syntax/data-types/inet","title":"INET","description":"The INET data type in SQL is used to store IPv4 and IPv6 addresses. These addresses can be compared, filtered, and sorted using standard SQL operations.","sidebar":"autoSidebar"},"sql-syntax/data-types/integers":{"id":"sql-syntax/data-types/integers","title":"Integer Types","description":"GlueSQL supports the following integer data types:","sidebar":"autoSidebar"},"sql-syntax/data-types/interval":{"id":"sql-syntax/data-types/interval","title":"INTERVAL","description":"The INTERVAL data type in GlueSQL is used to represent a period of time. In accordance with the ANSI SQL standard, several subtypes of INTERVAL can be used to represent different units of time, such as years, months, days, hours, minutes, and seconds. These subtypes are:","sidebar":"autoSidebar"},"sql-syntax/data-types/list":{"id":"sql-syntax/data-types/list","title":"LIST","description":"The LIST data type in GlueSQL is used to store ordered collections of elements, similar to JSON arrays. The elements can be any valid data supported by GlueSQL, such as numbers, strings, booleans, null, MAP, or even other nested LIST values. Although the input is provided in a JSON array format for convenience, it can store more than just JSON data.","sidebar":"autoSidebar"},"sql-syntax/data-types/map":{"id":"sql-syntax/data-types/map","title":"MAP","description":"The MAP data type in GlueSQL is used to store nested key-value pairs, similar to JSON objects. The object keys must be strings, and the values can be any valid data supported by GlueSQL, such as numbers, strings, booleans, null, or even other nested MAP values. Although the input is provided in a JSON object format for convenience, it can store more than just JSON data.","sidebar":"autoSidebar"},"sql-syntax/data-types/text":{"id":"sql-syntax/data-types/text","title":"TEXT","description":"The TEXT data type in SQL is used to store variable-length character strings. In GlueSQL, the TEXT data type is the only supported string data type, providing the ability to store and manage strings of varying lengths.","sidebar":"autoSidebar"},"sql-syntax/data-types/time":{"id":"sql-syntax/data-types/time","title":"TIME","description":"In GlueSQL, the TIME data type is used to store time values in the format \'HHSS.SSS\'. The code snippet provided demonstrates how to create a table with TIME columns, insert data into it, and perform various queries and operations on the data.","sidebar":"autoSidebar"},"sql-syntax/data-types/timestamp":{"id":"sql-syntax/data-types/timestamp","title":"TIMESTAMP","description":"In GlueSQL, the TIMESTAMP data type is used to store date and time values in the format \'YYYY-MM-DD HHSS.SSSS\'. Although timezone information can be included in the input string, GlueSQL stores all TIMESTAMP values in UTC, discarding the timezone information.","sidebar":"autoSidebar"},"sql-syntax/data-types/uuid":{"id":"sql-syntax/data-types/uuid","title":"UUID","description":"The UUID data type in SQL is used to store universally unique identifiers (UUIDs). These identifiers can be compared, filtered, and sorted using standard SQL operations.","sidebar":"autoSidebar"},"sql-syntax/functions/datetime/extract":{"id":"sql-syntax/functions/datetime/extract","title":"EXTRACT","description":"The EXTRACT function in SQL is used to retrieve a specific datetime field from a date, time, or interval.","sidebar":"autoSidebar"},"sql-syntax/functions/datetime/format":{"id":"sql-syntax/functions/datetime/format","title":"FORMAT","description":"The FORMAT function in SQL is used to format date, time, and timestamp values into a specified format.","sidebar":"autoSidebar"},"sql-syntax/functions/datetime/now":{"id":"sql-syntax/functions/datetime/now","title":"NOW","description":"The NOW() function in SQL returns the current date and time in UTC. You can use it to retrieve the current UTC timestamp, or as a default value for a TIMESTAMP column in a table.","sidebar":"autoSidebar"},"sql-syntax/functions/datetime/to-date":{"id":"sql-syntax/functions/datetime/to-date","title":"TO_DATE","description":"The TO_DATE function in SQL is used to convert a string into a DATE. This function takes two arguments, the string to be converted and a format string that specifies the format of the input string.","sidebar":"autoSidebar"},"sql-syntax/functions/datetime/to-time":{"id":"sql-syntax/functions/datetime/to-time","title":"TO_TIME","description":"The TO_TIME function in SQL is used to convert a string into a TIME. This function takes two arguments, the string to be converted and a format string that specifies the format of the input string.","sidebar":"autoSidebar"},"sql-syntax/functions/datetime/to-timestamp":{"id":"sql-syntax/functions/datetime/to-timestamp","title":"TO_TIMESTAMP","description":"The TO_TIMESTAMP function in SQL is used to convert a string into a TIMESTAMP. This function takes two arguments, the string to be converted and a format string that specifies the format of the input string.","sidebar":"autoSidebar"},"sql-syntax/functions/geometry/calc-distance":{"id":"sql-syntax/functions/geometry/calc-distance","title":"CALC_DISTANCE","description":"The CALC_DISTANCE function is used to calculate the Euclidean distance between two Point type geographical coordinates.","sidebar":"autoSidebar"},"sql-syntax/functions/geometry/get-x":{"id":"sql-syntax/functions/geometry/get-x","title":"GET_X","description":"The GET_X function returns the x-coordinate of a given POINT data type. It takes one POINT data type argument and returns a FLOAT value representing the x-coordinate.","sidebar":"autoSidebar"},"sql-syntax/functions/geometry/get-y":{"id":"sql-syntax/functions/geometry/get-y","title":"GET_Y","description":"The GET_Y function returns the y-coordinate of a given POINT data type. It takes one POINT data type argument and returns a FLOAT value representing the y-coordinate.","sidebar":"autoSidebar"},"sql-syntax/functions/geometry/point":{"id":"sql-syntax/functions/geometry/point","title":"POINT","description":"The POINT function creates a point value using the provided x and y coordinates. A point value represents a two-dimensional geometric point with a pair of floating-point numbers, often used for storing spatial data.","sidebar":"autoSidebar"},"sql-syntax/functions/list-map/append":{"id":"sql-syntax/functions/list-map/append","title":"APPEND","description":"The APPEND function in SQL is used to append an element to a list.","sidebar":"autoSidebar"},"sql-syntax/functions/list-map/concat":{"id":"sql-syntax/functions/list-map/concat","title":"CONCAT","description":"The CONCAT function is used to concatenate two or more list values together.","sidebar":"autoSidebar"},"sql-syntax/functions/list-map/prepend":{"id":"sql-syntax/functions/list-map/prepend","title":"PREPEND","description":"The PREPEND function in SQL is used to prepend an element to a list.","sidebar":"autoSidebar"},"sql-syntax/functions/list-map/splice":{"id":"sql-syntax/functions/list-map/splice","title":"SQL Function - \\"SPLICE\\"","description":"The \\"SPLICE\\" function in GlueSQL is used to modify elements in a list. It allows you to remove or replace elements in a list. The syntax for the \\"SPLICE\\" function is as follows:","sidebar":"autoSidebar"},"sql-syntax/functions/math/abs":{"id":"sql-syntax/functions/math/abs","title":"ABS","description":"The ABS function is used to calculate the absolute value of a number. It takes a single numeric argument and returns the absolute value of that number. The argument can be an integer, decimal, or float value.","sidebar":"autoSidebar"},"sql-syntax/functions/math/acos":{"id":"sql-syntax/functions/math/acos","title":"ACOS","description":"The ACOS function is used to calculate the arccosine (inverse cosine) of a number. It takes a single numeric argument, which should be a float value in the range of -1 to 1, and returns the arccosine of that number in radians.","sidebar":"autoSidebar"},"sql-syntax/functions/math/asin":{"id":"sql-syntax/functions/math/asin","title":"ASIN","description":"The ASIN function is used to calculate the arcsine (inverse sine) of a number. It takes a single numeric argument, which should be a float value in the range of -1 to 1, and returns the arcsine of that number in radians.","sidebar":"autoSidebar"},"sql-syntax/functions/math/atan":{"id":"sql-syntax/functions/math/atan","title":"ATAN","description":"The ATAN function is used to calculate the arctangent (inverse tangent) of a number. It takes a single numeric argument, and returns the arctangent of that number in radians.","sidebar":"autoSidebar"},"sql-syntax/functions/math/ceil":{"id":"sql-syntax/functions/math/ceil","title":"CEIL","description":"The CEIL function is used to round a number up to the nearest integer value. It takes a single floating-point or integer value as its argument and returns a floating-point value.","sidebar":"autoSidebar"},"sql-syntax/functions/math/cos":{"id":"sql-syntax/functions/math/cos","title":"COS","description":"The COS function is used to calculate the cosine of a number. It takes a single numeric argument (angle in radians) and returns the cosine of that angle.","sidebar":"autoSidebar"},"sql-syntax/functions/math/degrees":{"id":"sql-syntax/functions/math/degrees","title":"DEGREES","description":"The DEGREES function is used to convert a given angle value from radians to degrees. It takes a single numeric argument (angle in radians) and returns the angle in degrees.","sidebar":"autoSidebar"},"sql-syntax/functions/math/div":{"id":"sql-syntax/functions/math/div","title":"DIV","description":"The DIV function is used to perform integer division. It takes two arguments (a dividend and a divisor) and returns the integer quotient of the division operation. Both dividend and divisor can be FLOAT or INTEGER type. The return type of the function is INTEGER.","sidebar":"autoSidebar"},"sql-syntax/functions/math/exp":{"id":"sql-syntax/functions/math/exp","title":"EXP","description":"The EXP function is used to calculate the exponential value of a number. It takes a single FLOAT or INTEGER argument and returns a FLOAT value representing the exponential value of the given number.","sidebar":"autoSidebar"},"sql-syntax/functions/math/floor":{"id":"sql-syntax/functions/math/floor","title":"FLOOR","description":"The FLOOR function is used to round a number down to the nearest integer value. It takes a single floating-point or integer value as its argument and returns a floating-point value.","sidebar":"autoSidebar"},"sql-syntax/functions/math/gcd":{"id":"sql-syntax/functions/math/gcd","title":"GCD","description":"The GCD function is used to find the greatest common divisor (GCD) of two integers. It takes two INTEGER arguments and returns an INTEGER value representing the greatest common divisor of the given integers.","sidebar":"autoSidebar"},"sql-syntax/functions/math/lcm":{"id":"sql-syntax/functions/math/lcm","title":"LCM","description":"The LCM function is used to find the least common multiple (LCM) of two integers. It takes two INTEGER arguments and returns an INTEGER value representing the least common multiple of the given integers.","sidebar":"autoSidebar"},"sql-syntax/functions/math/ln":{"id":"sql-syntax/functions/math/ln","title":"LN","description":"The LN function is used to calculate the natural logarithm (base e) of a number. It takes a single FLOAT or INTEGER argument and returns a FLOAT value representing the natural logarithm of the given number.","sidebar":"autoSidebar"},"sql-syntax/functions/math/log":{"id":"sql-syntax/functions/math/log","title":"LOG","description":"The LOG function calculates the logarithm of a number with a specified base. It takes two FLOAT or INTEGER arguments and returns a FLOAT value representing the logarithm of the first argument with the base specified by the second argument.","sidebar":"autoSidebar"},"sql-syntax/functions/math/log10":{"id":"sql-syntax/functions/math/log10","title":"LOG10","description":"The LOG10 function is used to calculate the base-10 logarithm of a number. It takes a single FLOAT or INTEGER argument and returns a FLOAT value representing the base-10 logarithm of the given number.","sidebar":"autoSidebar"},"sql-syntax/functions/math/log2":{"id":"sql-syntax/functions/math/log2","title":"LOG2","description":"The LOG2 function is used to calculate the base-2 logarithm of a number. It takes a single FLOAT or INTEGER argument and returns a FLOAT value representing the base-2 logarithm of the given number.","sidebar":"autoSidebar"},"sql-syntax/functions/math/mod":{"id":"sql-syntax/functions/math/mod","title":"MOD","description":"The MOD function is used to calculate the remainder of a division operation. It takes two arguments (a dividend and a divisor) and returns the remainder of the division operation. Both dividend and divisor can be FLOAT or INTEGER type. The return type of the function is FLOAT.","sidebar":"autoSidebar"},"sql-syntax/functions/math/pi":{"id":"sql-syntax/functions/math/pi","title":"PI","description":"The PI function is used to retrieve the mathematical constant \u03c0 (pi), which is approximately 3.141592653589793. The function takes no arguments.","sidebar":"autoSidebar"},"sql-syntax/functions/math/power":{"id":"sql-syntax/functions/math/power","title":"POWER","description":"The POWER function is used to raise a number to the power of another number. It takes two arguments, the base and the exponent, both of which must be of the FLOAT type. The result will also be of the FLOAT type.","sidebar":"autoSidebar"},"sql-syntax/functions/math/radians":{"id":"sql-syntax/functions/math/radians","title":"RADIANS","description":"The RADIANS function is used to convert a given angle value from degrees to radians. It takes a single numeric argument (angle in degrees) and returns the angle in radians.","sidebar":"autoSidebar"},"sql-syntax/functions/math/rand":{"id":"sql-syntax/functions/math/rand","title":"RAND","description":"The RAND function is used to generate a random float value between 0 (inclusive) and 1 (exclusive). The function takes an optional seed value, which must be of the FLOAT type. If a seed value is provided, the random number generator will be initialized with that seed, producing a deterministic sequence of random numbers.","sidebar":"autoSidebar"},"sql-syntax/functions/math/round":{"id":"sql-syntax/functions/math/round","title":"ROUND","description":"The ROUND function is used to round a number to the nearest integer value. It takes a single floating-point or integer value as its argument and returns a floating-point value.","sidebar":"autoSidebar"},"sql-syntax/functions/math/sign":{"id":"sql-syntax/functions/math/sign","title":"SIGN","description":"The SIGN function is used to determine the sign of a number. It takes one argument, which must be of the FLOAT type. The result will be of the INTEGER type and can be -1, 0, or 1.","sidebar":"autoSidebar"},"sql-syntax/functions/math/sin":{"id":"sql-syntax/functions/math/sin","title":"SIN","description":"The SIN function is used to calculate the sine of a number. It takes a single numeric argument (angle in radians) and returns the sine of that angle.","sidebar":"autoSidebar"},"sql-syntax/functions/math/sqrt":{"id":"sql-syntax/functions/math/sqrt","title":"SQRT","description":"The SQRT function is used to calculate the square root of a number. It takes one argument, which must be of the FLOAT type. The result will also be of the FLOAT type.","sidebar":"autoSidebar"},"sql-syntax/functions/math/tan":{"id":"sql-syntax/functions/math/tan","title":"TAN","description":"The TAN function is used to calculate the tangent of a number. It takes a single numeric argument (angle in radians) and returns the tangent of that angle.","sidebar":"autoSidebar"},"sql-syntax/functions/others/cast":{"id":"sql-syntax/functions/others/cast","title":"CAST","description":"The CAST function is used to convert a value from one data type to another. It is commonly used when you need to change the data type of a value or a column to perform a specific operation, such as arithmetic or string concatenation.","sidebar":"autoSidebar"},"sql-syntax/functions/others/generate-uuid":{"id":"sql-syntax/functions/others/generate-uuid","title":"GENERATE_UUID","description":"The GENERATE_UUID function is an SQL function provided by GlueSQL that generates a new UUID (Universally Unique Identifier) using the version 4 UUID algorithm. A UUID is a 128-bit value used to uniquely identify items in various computing systems. Version 4 UUIDs are randomly generated and have 122 bits of randomness, which ensures a very low probability of collisions.","sidebar":"autoSidebar"},"sql-syntax/functions/others/ifnull":{"id":"sql-syntax/functions/others/ifnull","title":"IFNULL","description":"The IFNULL function is used to return the first non-null value among the provided expressions. It takes two arguments and checks if the first argument is NULL. If the first argument is NULL, it returns the second argument; otherwise, it returns the first argument.","sidebar":"autoSidebar"},"sql-syntax/functions/text/ascii":{"id":"sql-syntax/functions/text/ascii","title":"ASCII","description":"The ASCII function in SQL returns the ASCII value for the first character of the specified string.","sidebar":"autoSidebar"},"sql-syntax/functions/text/chr":{"id":"sql-syntax/functions/text/chr","title":"CHR","description":"The CHR function in SQL returns the character represented by the specified ASCII value.","sidebar":"autoSidebar"},"sql-syntax/functions/text/concat":{"id":"sql-syntax/functions/text/concat","title":"CONCAT","description":"The CONCAT function in SQL concatenates two or more strings into one string.","sidebar":"autoSidebar"},"sql-syntax/functions/text/concat-ws":{"id":"sql-syntax/functions/text/concat-ws","title":"CONCAT_WS","description":"The CONCAT_WS function in SQL concatenates two or more strings into one string with a separator.","sidebar":"autoSidebar"},"sql-syntax/functions/text/find-idx":{"id":"sql-syntax/functions/text/find-idx","title":"FIND_IDX","description":"The FIND_IDX function in SQL is used to return the position of the first occurrence of a substring in a string, optionally after a specified position.","sidebar":"autoSidebar"},"sql-syntax/functions/text/initcap":{"id":"sql-syntax/functions/text/initcap","title":"INITCAP","description":"The INITCAP function in SQL is used to capitalize the first letter of each word in a string and convert the rest of the characters to lowercase.","sidebar":"autoSidebar"},"sql-syntax/functions/text/left":{"id":"sql-syntax/functions/text/left","title":"LEFT","description":"The LEFT function in SQL returns the specified number of characters from the start (left side) of a given string.","sidebar":"autoSidebar"},"sql-syntax/functions/text/lower":{"id":"sql-syntax/functions/text/lower","title":"LOWER","description":"The LOWER function in SQL returns a string in which all alphabetic characters in a specified string are converted to lowercase.","sidebar":"autoSidebar"},"sql-syntax/functions/text/lpad":{"id":"sql-syntax/functions/text/lpad","title":"LPAD","description":"The LPAD function in SQL pads the left side of a string with a specific set of characters.","sidebar":"autoSidebar"},"sql-syntax/functions/text/ltrim":{"id":"sql-syntax/functions/text/ltrim","title":"LTRIM","description":"The LTRIM function in SQL removes characters from the left (leading side) of a string.","sidebar":"autoSidebar"},"sql-syntax/functions/text/position":{"id":"sql-syntax/functions/text/position","title":"POSITION","description":"The POSITION function in SQL is used to find the position of a substring in a string. The position of the first occurrence of the substring is returned. If the substring is not found, this function returns 0.","sidebar":"autoSidebar"},"sql-syntax/functions/text/repeat":{"id":"sql-syntax/functions/text/repeat","title":"REPEAT","description":"The REPEAT function in SQL is used to repeat a string for a specified number of times.","sidebar":"autoSidebar"},"sql-syntax/functions/text/reverse":{"id":"sql-syntax/functions/text/reverse","title":"REVERSE","description":"The REVERSE function in SQL is used to reverse a string.","sidebar":"autoSidebar"},"sql-syntax/functions/text/right":{"id":"sql-syntax/functions/text/right","title":"RIGHT","description":"The RIGHT function in SQL returns the specified number of characters from the end (right side) of a given string.","sidebar":"autoSidebar"},"sql-syntax/functions/text/rpad":{"id":"sql-syntax/functions/text/rpad","title":"RPAD","description":"The RPAD function in SQL pads the right side of a string with a specific set of characters.","sidebar":"autoSidebar"},"sql-syntax/functions/text/rtrim":{"id":"sql-syntax/functions/text/rtrim","title":"RTRIM","description":"The RTRIM function in SQL removes characters from the right (trailing side) of a string.","sidebar":"autoSidebar"},"sql-syntax/functions/text/substr":{"id":"sql-syntax/functions/text/substr","title":"SUBSTR","description":"The SUBSTR function in SQL is used to extract a substring from a string.","sidebar":"autoSidebar"},"sql-syntax/functions/text/trim":{"id":"sql-syntax/functions/text/trim","title":"TRIM","description":"The TRIM function in SQL is used to remove leading, trailing, or both leading and trailing unwanted characters (often whitespace) from a string.","sidebar":"autoSidebar"},"sql-syntax/functions/text/upper":{"id":"sql-syntax/functions/text/upper","title":"UPPER","description":"The UPPER function in SQL converts all lowercase alphabetic characters in a specified string to uppercase.","sidebar":"autoSidebar"},"sql-syntax/intro":{"id":"sql-syntax/intro","title":"Introduction","description":"Welcome to the Introduction page for the SQL Syntax category in GlueSQL! In this section, we\'ll provide a brief overview of the SQL syntax supported by GlueSQL. You can find more in-depth examples and details by browsing the other pages in this category.","sidebar":"autoSidebar"},"sql-syntax/statements/data-definition/alter-table":{"id":"sql-syntax/statements/data-definition/alter-table","title":"ALTER TABLE","description":"The ALTER TABLE statement is an SQL command used to modify the structure of an existing table in a database. This operation is useful when you need to add, remove, or modify columns or constraints in a table. In this document, we\'ll explain the syntax and usage of the ALTER TABLE statement, including the RENAME, ADD COLUMN, and DROP COLUMN clauses.","sidebar":"autoSidebar"},"sql-syntax/statements/data-definition/create-index":{"id":"sql-syntax/statements/data-definition/create-index","title":"CREATE INDEX","description":"CREATE INDEX statement is used to create an index on one or more columns of a table. Indexes can improve query performance by allowing the database to quickly locate rows with specific column values. They can also be used with the ORDER BY clause to improve sorting performance. An index can be thought of as a data structure that maps the values of a specific column or columns to the corresponding rows in a table. This mapping allows the database to perform lookups and sorting operations more efficiently, as it does not have to scan the entire table.","sidebar":"autoSidebar"},"sql-syntax/statements/data-definition/create-table":{"id":"sql-syntax/statements/data-definition/create-table","title":"CREATE TABLE","description":"The CREATE TABLE statement is a fundamental SQL command used to create a new table in a database. Tables are the primary structure in databases, as they hold the data organized in rows and columns. In this document, we\'ll explain the syntax and usage of the CREATE TABLE statement, including the IF NOT EXISTS clause.","sidebar":"autoSidebar"},"sql-syntax/statements/data-definition/drop-index":{"id":"sql-syntax/statements/data-definition/drop-index","title":"DROP INDEX","description":"DROP INDEX statement is used to remove an existing index from a table. This can be useful when an index is no longer needed, or if you want to free up storage space and reduce maintenance overhead associated with maintaining the index.","sidebar":"autoSidebar"},"sql-syntax/statements/data-definition/drop-table":{"id":"sql-syntax/statements/data-definition/drop-table","title":"DROP TABLE","description":"The DROP TABLE statement is an SQL command used to remove one or more tables from a database. This operation is useful when you no longer need a table or want to clear out old data structures. In this document, we\'ll explain the syntax and usage of the DROP TABLE statement, including the IF EXISTS clause and dropping multiple tables at once.","sidebar":"autoSidebar"},"sql-syntax/statements/data-manipulation/delete":{"id":"sql-syntax/statements/data-manipulation/delete","title":"DELETE","description":"The DELETE statement is used to remove records from a table. You can delete a single row, multiple rows, or all rows at once based on specific conditions.","sidebar":"autoSidebar"},"sql-syntax/statements/data-manipulation/insert":{"id":"sql-syntax/statements/data-manipulation/insert","title":"INSERT","description":"The INSERT statement is used to insert new records into a table. You can insert a single row or multiple rows at once, and you can also use the NULL, NOT NULL, and DEFAULT constraints to define how values are inserted.","sidebar":"autoSidebar"},"sql-syntax/statements/data-manipulation/update":{"id":"sql-syntax/statements/data-manipulation/update","title":"UPDATE","description":"The UPDATE statement is used to modify existing records in a table. You can update one or more columns with new values, or even use subqueries to update values based on other tables.","sidebar":"autoSidebar"},"sql-syntax/statements/metadata/data-dictionary":{"id":"sql-syntax/statements/metadata/data-dictionary","title":"Data Dictionary","description":"In GlueSQL, there are predefined tables, also known as Data Dictionary tables, which store metadata about the database objects like tables, columns, and indexes. These tables can be queried like any other table in the database, and they provide useful information about the database schema.","sidebar":"autoSidebar"},"sql-syntax/statements/metadata/show-tables":{"id":"sql-syntax/statements/metadata/show-tables","title":"SHOW TABLES","description":"The SHOW TABLES statement in GlueSQL is used to display a list of tables available in the database. This statement is useful when you want to inspect the current structure of your database or when you want to manage multiple tables.","sidebar":"autoSidebar"},"sql-syntax/statements/querying/aggregation":{"id":"sql-syntax/statements/querying/aggregation","title":"Aggregation","description":"GlueSQL supports several aggregate functions to perform calculations on a set of values. Below is a list of supported aggregate functions along with a brief explanation of each:","sidebar":"autoSidebar"},"sql-syntax/statements/querying/join":{"id":"sql-syntax/statements/querying/join","title":"JOIN","description":"GlueSQL supports two types of JOIN operations:","sidebar":"autoSidebar"},"sql-syntax/statements/querying/limit":{"id":"sql-syntax/statements/querying/limit","title":"LIMIT & OFFSET","description":"LIMIT and OFFSET are SQL clauses that allow you to control the number of rows returned by a SELECT statement. They are particularly useful when you need to paginate or retrieve a specific portion of the result set.","sidebar":"autoSidebar"},"sql-syntax/statements/querying/schemaless":{"id":"sql-syntax/statements/querying/schemaless","title":"Schemaless Data","description":"GlueSQL is an SQL database that provides a unique feature: it allows you to work with schemaless data, similar to NoSQL databases. Please note this point in the documentation.","sidebar":"autoSidebar"},"sql-syntax/statements/querying/where":{"id":"sql-syntax/statements/querying/where","title":"WHERE","description":"In GlueSQL, the WHERE clause is used to filter the results of a SELECT query based on specific conditions. The WHERE clause can be used with various operators and functions to create complex filtering conditions.","sidebar":"autoSidebar"},"sql-syntax/statements/transaction":{"id":"sql-syntax/statements/transaction","title":"Transaction","description":"Transactions in SQL are a series of queries that are executed as a single unit of work. In GlueSQL, transactions help to ensure the consistency and integrity of the database. They follow the ACID properties: Atomicity, Consistency, Isolation, and Durability.","sidebar":"autoSidebar"},"storages/developing-custom-storages/intro":{"id":"storages/developing-custom-storages/intro","title":"Introduction","description":"With GlueSQL, you can adapt SQL and the AST Builder to a wide variety of environments. This includes file systems, key-value databases, complex NoSQL databases, and even remote APIs. As long as a system supports reading, it can support SELECT queries. If it supports both reading and writing, it can support most SQL operations, including UPDATE and DELETE.","sidebar":"autoSidebar"},"storages/developing-custom-storages/store-traits/alter-table":{"id":"storages/developing-custom-storages/store-traits/alter-table","title":"AlterTable","description":"The AlterTable trait corresponds to the SQL ALTER TABLE statement and is used for modifying existing schemas. It is not necessary to implement the AlterTable trait. If you are dealing with data that is difficult to modify schema-wise or schemaless data, there is no need to implement the AlterTable trait. It is an optional trait that custom storage developers can choose to implement.","sidebar":"autoSidebar"},"storages/developing-custom-storages/store-traits/custom-function":{"id":"storages/developing-custom-storages/store-traits/custom-function","title":"CustomFunction","description":"The CustomFunction trait is an optional trait for supporting user-level custom functions. Through the CustomFunction trait, you can retrieve custom functions stored in the storage system. You can choose to implement the CustomFunction trait alone or together with the CustomFunctionMut trait.","sidebar":"autoSidebar"},"storages/developing-custom-storages/store-traits/custom-function-mut":{"id":"storages/developing-custom-storages/store-traits/custom-function-mut","title":"CustomFunctionMut","description":"By implementing both the CustomFunction and CustomFunctionMut traits, users can create, use, and delete user-level custom functions. Although GlueSQL plans to continuously add various functions, users may still find them insufficient. In such cases, users can create their own user-level custom functions to supplement the built-in functions. Additionally, if there are repetitive business logic codes, they can be stored as custom functions.","sidebar":"autoSidebar"},"storages/developing-custom-storages/store-traits/index-mut":{"id":"storages/developing-custom-storages/store-traits/index-mut","title":"IndexMut","description":"The IndexMut trait, when implemented along with the Index trait, allows custom storage developers to provide users with the ability to create, use, and delete non-clustered indexes. Implementing the IndexMut trait enhances the storage system\'s capabilities by providing support for dynamic index management.","sidebar":"autoSidebar"},"storages/developing-custom-storages/store-traits/index-trait":{"id":"storages/developing-custom-storages/store-traits/index-trait","title":"Index","description":"The Index trait is designed to support non-clustered indexes. If you only need to support pre-built non-clustered indexes, implementing the Index trait without the IndexMut trait is sufficient. Note that clustered indexes (PRIMARY KEY) are automatically supported by the Store & StoreMut implementations. The Index trait is specifically for non-clustered index support.","sidebar":"autoSidebar"},"storages/developing-custom-storages/store-traits/metadata":{"id":"storages/developing-custom-storages/store-traits/metadata","title":"Metadata","description":"The Metadata trait is an optional implementation for providing additional metadata support in GlueSQL. GlueSQL does not enforce any specific metadata implementation, allowing custom storage developers to decide which type of metadata, such as create time, modify time, etc., they want to provide.","sidebar":"autoSidebar"},"storages/developing-custom-storages/store-traits/store":{"id":"storages/developing-custom-storages/store-traits/store","title":"Store","description":"The Store trait is the most essential trait to implement for custom storage. Simply by implementing the Store trait, you can support SELECT queries in SQL. You may want to analyze and retrieve data from log files or external APIs using SQL. In this case, having only SELECT queries available is sufficient, and there might not be any need for data modification. In such scenarios, implementing GlueSQL\'s Store trait alone would be adequate.","sidebar":"autoSidebar"},"storages/developing-custom-storages/store-traits/store-mut":{"id":"storages/developing-custom-storages/store-traits/store-mut","title":"StoreMut","description":"While the Store trait is for supporting SELECT queries and reading data, the StoreMut trait is for modifying data. Implementing the StoreMut trait requires the implementation of the Store trait as well. By implementing both the Store and StoreMut traits, you can support most of the commonly used SQL statements. Additionally, you can use the Test Suite to utilize the integration test set provided by GlueSQL. Custom storage developers can verify their own Store & StoreMut implementations by checking if they pass all the tests provided in the Test Suite.","sidebar":"autoSidebar"},"storages/developing-custom-storages/store-traits/transaction":{"id":"storages/developing-custom-storages/store-traits/transaction","title":"Transaction","description":"While transactions are often considered an essential feature for databases, GlueSQL treats transactions as an optional trait. Custom storage developers can choose whether or not to support transactions in their storage implementation. Transactions can be quite heavy and expensive in terms of performance.","sidebar":"autoSidebar"},"storages/developing-custom-storages/using-test-suite":{"id":"storages/developing-custom-storages/using-test-suite","title":"Using the Test Suite","description":"The GlueSQL Test Suite is a valuable tool for validating your custom storage implementation. By using the provided test sets, you can ensure that your storage implementation adheres to the required specifications and works as expected with GlueSQL.","sidebar":"autoSidebar"},"storages/intro":{"id":"storages/intro","title":"Introduction","description":"GlueSQL is not only suitable for use as a conventional database, but one of its key features is the ability for anyone to easily adapt SQL and the AST Builder to their desired file or storage system. This adaptability is achieved through the following topics covered in this section:","sidebar":"autoSidebar"},"storages/supported-storages/composite-storage":{"id":"storages/supported-storages/composite-storage","title":"Composite Storage","description":"Introduction","sidebar":"autoSidebar"},"storages/supported-storages/idb-storage":{"id":"storages/supported-storages/idb-storage","title":"IndexedDB Storage","description":"Introduction","sidebar":"autoSidebar"},"storages/supported-storages/json-storage":{"id":"storages/supported-storages/json-storage","title":"JSON Storage","description":"Introduction","sidebar":"autoSidebar"},"storages/supported-storages/memory-storage":{"id":"storages/supported-storages/memory-storage","title":"Memory Storage","description":"MemoryStorage is a foundational storage option designed for in-memory, non-persistent data. Despite its simplicity, it is robust enough for use in production environments.","sidebar":"autoSidebar"},"storages/supported-storages/shared-memory-storage":{"id":"storages/supported-storages/shared-memory-storage","title":"Shared Memory Storage","description":"SharedMemoryStorage is a storage option designed to provide more comfortable usage of MemoryStorage in concurrent environments. Although it doesn\'t operate in parallel, it makes accessing the same data from multiple threads simultaneously more convenient.","sidebar":"autoSidebar"},"storages/supported-storages/sled-storage":{"id":"storages/supported-storages/sled-storage","title":"Sled Storage","description":"SledStorage is currently the representative persistent data storage for GlueSQL. As the name suggests, it\'s a storage option based on the Sled key-value embedded database built in Rust (Sled on Github).","sidebar":"autoSidebar"},"storages/supported-storages/web-storage":{"id":"storages/supported-storages/web-storage","title":"WebStorage (local & session)","description":"WebStorage - yes, the localStorage and sessionStorage you\'re familiar with. With GlueSQL, you can use SQL to interact with these storages!","sidebar":"autoSidebar"}}}')}}]); \ No newline at end of file diff --git a/docs/dev/assets/js/9785.0386875e.js b/docs/dev/assets/js/9785.ee036d0a.js similarity index 70% rename from docs/dev/assets/js/9785.0386875e.js rename to docs/dev/assets/js/9785.ee036d0a.js index d87616f1..cb355c23 100644 --- a/docs/dev/assets/js/9785.0386875e.js +++ b/docs/dev/assets/js/9785.ee036d0a.js @@ -1 +1 @@ -(self.webpackChunkdocs=self.webpackChunkdocs||[]).push([[9785],{3905:(e,t,n)=>{"use strict";n.d(t,{Zo:()=>u,kt:()=>f});var o=n(7294);function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function r(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);t&&(o=o.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,o)}return n}function c(e){for(var t=1;t=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(o=0;o=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var i=o.createContext({}),s=function(e){var t=o.useContext(i),n=t;return e&&(n="function"==typeof e?e(t):c(c({},t),e)),n},u=function(e){var t=s(e.components);return o.createElement(i.Provider,{value:t},e.children)},m="mdxType",d={inlineCode:"code",wrapper:function(e){var t=e.children;return o.createElement(o.Fragment,{},t)}},p=o.forwardRef((function(e,t){var n=e.components,a=e.mdxType,r=e.originalType,i=e.parentName,u=l(e,["components","mdxType","originalType","parentName"]),m=s(n),p=a,f=m["".concat(i,".").concat(p)]||m[p]||d[p]||r;return n?o.createElement(f,c(c({ref:t},u),{},{components:n})):o.createElement(f,c({ref:t},u))}));function f(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var r=n.length,c=new Array(r);c[0]=p;var l={};for(var i in t)hasOwnProperty.call(t,i)&&(l[i]=t[i]);l.originalType=e,l[m]="string"==typeof e?e:a,c[1]=l;for(var s=2;s{"use strict";n.d(t,{Z:()=>u});var o=n(7294),a=n(5999),r=n(5281),c=n(7462),l=n(6010);const i={iconEdit:"iconEdit_Z9Sw"};function s(e){let{className:t,...n}=e;return o.createElement("svg",(0,c.Z)({fill:"currentColor",height:"20",width:"20",viewBox:"0 0 40 40",className:(0,l.Z)(i.iconEdit,t),"aria-hidden":"true"},n),o.createElement("g",null,o.createElement("path",{d:"m34.5 11.7l-3 3.1-6.3-6.3 3.1-3q0.5-0.5 1.2-0.5t1.1 0.5l3.9 3.9q0.5 0.4 0.5 1.1t-0.5 1.2z m-29.5 17.1l18.4-18.5 6.3 6.3-18.4 18.4h-6.3v-6.2z"})))}function u(e){let{editUrl:t}=e;return o.createElement("a",{href:t,target:"_blank",rel:"noreferrer noopener",className:r.k.common.editThisPage},o.createElement(s,null),o.createElement(a.Z,{id:"theme.common.editThisPage",description:"The link label to edit the current page"},"Edit this page"))}},2503:(e,t,n)=>{"use strict";n.d(t,{Z:()=>u});var o=n(7462),a=n(7294),r=n(6010),c=n(5999),l=n(6668),i=n(9960);const s={anchorWithStickyNavbar:"anchorWithStickyNavbar_LWe7",anchorWithHideOnScrollNavbar:"anchorWithHideOnScrollNavbar_WYt5"};function u(e){let{as:t,id:n,...u}=e;const{navbar:{hideOnScroll:m}}=(0,l.L)();if("h1"===t||!n)return a.createElement(t,(0,o.Z)({},u,{id:void 0}));const d=(0,c.I)({id:"theme.common.headingLinkTitle",message:"Direct link to {heading}",description:"Title for link to heading"},{heading:"string"==typeof u.children?u.children:n});return a.createElement(t,(0,o.Z)({},u,{className:(0,r.Z)("anchor",m?s.anchorWithHideOnScrollNavbar:s.anchorWithStickyNavbar,u.className),id:n}),u.children,a.createElement(i.Z,{className:"hash-link",to:`#${n}`,"aria-label":d,title:d},"\u200b"))}},1506:(e,t,n)=>{"use strict";n.d(t,{Z:()=>he});var o=n(7294),a=n(3905),r=n(7462),c=n(5742);var l=n(2389),i=n(6010),s=n(2949),u=n(6668);function m(){const{prism:e}=(0,u.L)(),{colorMode:t}=(0,s.I)(),n=e.theme,o=e.darkTheme||n;return"dark"===t?o:n}var d=n(5281),p=n(7594),f=n.n(p);const g=/title=(?["'])(?.*?)\1/,h=/\{(?<range>[\d,-]+)\}/,y={js:{start:"\\/\\/",end:""},jsBlock:{start:"\\/\\*",end:"\\*\\/"},jsx:{start:"\\{\\s*\\/\\*",end:"\\*\\/\\s*\\}"},bash:{start:"#",end:""},html:{start:"\x3c!--",end:"--\x3e"}};function b(e,t){const n=e.map((e=>{const{start:n,end:o}=y[e];return`(?:${n}\\s*(${t.flatMap((e=>[e.line,e.block?.start,e.block?.end].filter(Boolean))).join("|")})\\s*${o})`})).join("|");return new RegExp(`^\\s*(?:${n})\\s*$`)}function v(e,t){let n=e.replace(/\n$/,"");const{language:o,magicComments:a,metastring:r}=t;if(r&&h.test(r)){const e=r.match(h).groups.range;if(0===a.length)throw new Error(`A highlight range has been given in code block's metastring (\`\`\` ${r}), but no magic comment config is available. Docusaurus applies the first magic comment entry's className for metastring ranges.`);const t=a[0].className,o=f()(e).filter((e=>e>0)).map((e=>[e-1,[t]]));return{lineClassNames:Object.fromEntries(o),code:n}}if(void 0===o)return{lineClassNames:{},code:n};const c=function(e,t){switch(e){case"js":case"javascript":case"ts":case"typescript":return b(["js","jsBlock"],t);case"jsx":case"tsx":return b(["js","jsBlock","jsx"],t);case"html":return b(["js","jsBlock","html"],t);case"python":case"py":case"bash":return b(["bash"],t);case"markdown":case"md":return b(["html","jsx","bash"],t);default:return b(Object.keys(y),t)}}(o,a),l=n.split("\n"),i=Object.fromEntries(a.map((e=>[e.className,{start:0,range:""}]))),s=Object.fromEntries(a.filter((e=>e.line)).map((e=>{let{className:t,line:n}=e;return[n,t]}))),u=Object.fromEntries(a.filter((e=>e.block)).map((e=>{let{className:t,block:n}=e;return[n.start,t]}))),m=Object.fromEntries(a.filter((e=>e.block)).map((e=>{let{className:t,block:n}=e;return[n.end,t]})));for(let p=0;p<l.length;){const e=l[p].match(c);if(!e){p+=1;continue}const t=e.slice(1).find((e=>void 0!==e));s[t]?i[s[t]].range+=`${p},`:u[t]?i[u[t]].start=p:m[t]&&(i[m[t]].range+=`${i[m[t]].start}-${p-1},`),l.splice(p,1)}n=l.join("\n");const d={};return Object.entries(i).forEach((e=>{let[t,{range:n}]=e;f()(n).forEach((e=>{d[e]??=[],d[e].push(t)}))})),{lineClassNames:d,code:n}}const E={codeBlockContainer:"codeBlockContainer_Ckt0"};function k(e){let{as:t,...n}=e;const a=function(e){const t={color:"--prism-color",backgroundColor:"--prism-background-color"},n={};return Object.entries(e.plain).forEach((e=>{let[o,a]=e;const r=t[o];r&&"string"==typeof a&&(n[r]=a)})),n}(m());return o.createElement(t,(0,r.Z)({},n,{style:a,className:(0,i.Z)(n.className,E.codeBlockContainer,d.k.common.codeBlock)}))}const N={codeBlockContent:"codeBlockContent_biex",codeBlockTitle:"codeBlockTitle_Ktv7",codeBlock:"codeBlock_bY9V",codeBlockStandalone:"codeBlockStandalone_MEMb",codeBlockLines:"codeBlockLines_e6Vv",codeBlockLinesWithNumbering:"codeBlockLinesWithNumbering_o6Pm",buttonGroup:"buttonGroup__atx"};function C(e){let{children:t,className:n}=e;return o.createElement(k,{as:"pre",tabIndex:0,className:(0,i.Z)(N.codeBlockStandalone,"thin-scrollbar",n)},o.createElement("code",{className:N.codeBlockLines},t))}var w=n(902);const B={attributes:!0,characterData:!0,childList:!0,subtree:!0};function Z(e,t){const[n,a]=(0,o.useState)(),r=(0,o.useCallback)((()=>{a(e.current?.closest("[role=tabpanel][hidden]"))}),[e,a]);(0,o.useEffect)((()=>{r()}),[r]),function(e,t,n){void 0===n&&(n=B);const a=(0,w.zX)(t),r=(0,w.Ql)(n);(0,o.useEffect)((()=>{const t=new MutationObserver(a);return e&&t.observe(e,r),()=>t.disconnect()}),[e,a,r])}(n,(e=>{e.forEach((e=>{"attributes"===e.type&&"hidden"===e.attributeName&&(t(),r())}))}),{attributes:!0,characterData:!1,childList:!1,subtree:!1})}const T={plain:{backgroundColor:"#2a2734",color:"#9a86fd"},styles:[{types:["comment","prolog","doctype","cdata","punctuation"],style:{color:"#6c6783"}},{types:["namespace"],style:{opacity:.7}},{types:["tag","operator","number"],style:{color:"#e09142"}},{types:["property","function"],style:{color:"#9a86fd"}},{types:["tag-id","selector","atrule-id"],style:{color:"#eeebff"}},{types:["attr-name"],style:{color:"#c4b9fe"}},{types:["boolean","string","entity","url","attr-value","keyword","control","directive","unit","statement","regex","atrule","placeholder","variable"],style:{color:"#ffcc99"}},{types:["deleted"],style:{textDecorationLine:"line-through"}},{types:["inserted"],style:{textDecorationLine:"underline"}},{types:["italic"],style:{fontStyle:"italic"}},{types:["important","bold"],style:{fontWeight:"bold"}},{types:["important"],style:{color:"#c4b9fe"}}]};var L={Prism:n(7410).Z,theme:T};function j(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function _(){return _=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var o in n)Object.prototype.hasOwnProperty.call(n,o)&&(e[o]=n[o])}return e},_.apply(this,arguments)}var x=/\r\n|\r|\n/,O=function(e){0===e.length?e.push({types:["plain"],content:"\n",empty:!0}):1===e.length&&""===e[0].content&&(e[0].content="\n",e[0].empty=!0)},S=function(e,t){var n=e.length;return n>0&&e[n-1]===t?e:e.concat(t)};function P(e,t){var n={};for(var o in e)Object.prototype.hasOwnProperty.call(e,o)&&-1===t.indexOf(o)&&(n[o]=e[o]);return n}var z=function(e){function t(){for(var t=this,n=[],o=arguments.length;o--;)n[o]=arguments[o];e.apply(this,n),j(this,"getThemeDict",(function(e){if(void 0!==t.themeDict&&e.theme===t.prevTheme&&e.language===t.prevLanguage)return t.themeDict;t.prevTheme=e.theme,t.prevLanguage=e.language;var n=e.theme?function(e,t){var n=e.plain,o=Object.create(null),a=e.styles.reduce((function(e,n){var o=n.languages,a=n.style;return o&&!o.includes(t)||n.types.forEach((function(t){var n=_({},e[t],a);e[t]=n})),e}),o);return a.root=n,a.plain=_({},n,{backgroundColor:null}),a}(e.theme,e.language):void 0;return t.themeDict=n})),j(this,"getLineProps",(function(e){var n=e.key,o=e.className,a=e.style,r=_({},P(e,["key","className","style","line"]),{className:"token-line",style:void 0,key:void 0}),c=t.getThemeDict(t.props);return void 0!==c&&(r.style=c.plain),void 0!==a&&(r.style=void 0!==r.style?_({},r.style,a):a),void 0!==n&&(r.key=n),o&&(r.className+=" "+o),r})),j(this,"getStyleForToken",(function(e){var n=e.types,o=e.empty,a=n.length,r=t.getThemeDict(t.props);if(void 0!==r){if(1===a&&"plain"===n[0])return o?{display:"inline-block"}:void 0;if(1===a&&!o)return r[n[0]];var c=o?{display:"inline-block"}:{},l=n.map((function(e){return r[e]}));return Object.assign.apply(Object,[c].concat(l))}})),j(this,"getTokenProps",(function(e){var n=e.key,o=e.className,a=e.style,r=e.token,c=_({},P(e,["key","className","style","token"]),{className:"token "+r.types.join(" "),children:r.content,style:t.getStyleForToken(r),key:void 0});return void 0!==a&&(c.style=void 0!==c.style?_({},c.style,a):a),void 0!==n&&(c.key=n),o&&(c.className+=" "+o),c})),j(this,"tokenize",(function(e,t,n,o){var a={code:t,grammar:n,language:o,tokens:[]};e.hooks.run("before-tokenize",a);var r=a.tokens=e.tokenize(a.code,a.grammar,a.language);return e.hooks.run("after-tokenize",a),r}))}return e&&(t.__proto__=e),t.prototype=Object.create(e&&e.prototype),t.prototype.constructor=t,t.prototype.render=function(){var e=this.props,t=e.Prism,n=e.language,o=e.code,a=e.children,r=this.getThemeDict(this.props),c=t.languages[n];return a({tokens:function(e){for(var t=[[]],n=[e],o=[0],a=[e.length],r=0,c=0,l=[],i=[l];c>-1;){for(;(r=o[c]++)<a[c];){var s=void 0,u=t[c],m=n[c][r];if("string"==typeof m?(u=c>0?u:["plain"],s=m):(u=S(u,m.type),m.alias&&(u=S(u,m.alias)),s=m.content),"string"==typeof s){var d=s.split(x),p=d.length;l.push({types:u,content:d[0]});for(var f=1;f<p;f++)O(l),i.push(l=[]),l.push({types:u,content:d[f]})}else c++,t.push(u),n.push(s),o.push(0),a.push(s.length)}c--,t.pop(),n.pop(),o.pop(),a.pop()}return O(l),i}(void 0!==c?this.tokenize(t,o,c,n):[o]),className:"prism-code language-"+n,style:void 0!==r?r.root:{},getLineProps:this.getLineProps,getTokenProps:this.getTokenProps})},t}(o.Component);const A=z,I={codeLine:"codeLine_lJS_",codeLineNumber:"codeLineNumber_Tfdd",codeLineContent:"codeLineContent_feaV"};function W(e){let{line:t,classNames:n,showLineNumbers:a,getLineProps:c,getTokenProps:l}=e;1===t.length&&"\n"===t[0].content&&(t[0].content="");const s=c({line:t,className:(0,i.Z)(n,a&&I.codeLine)}),u=t.map(((e,t)=>o.createElement("span",(0,r.Z)({key:t},l({token:e,key:t})))));return o.createElement("span",s,a?o.createElement(o.Fragment,null,o.createElement("span",{className:I.codeLineNumber}),o.createElement("span",{className:I.codeLineContent},u)):u,o.createElement("br",null))}var M=n(5999);function H(e){return o.createElement("svg",(0,r.Z)({viewBox:"0 0 24 24"},e),o.createElement("path",{fill:"currentColor",d:"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"}))}function D(e){return o.createElement("svg",(0,r.Z)({viewBox:"0 0 24 24"},e),o.createElement("path",{fill:"currentColor",d:"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"}))}const V={copyButtonCopied:"copyButtonCopied_obH4",copyButtonIcons:"copyButtonIcons_eSgA",copyButtonIcon:"copyButtonIcon_y97N",copyButtonSuccessIcon:"copyButtonSuccessIcon_LjdS"};function R(e){let{code:t,className:n}=e;const[a,r]=(0,o.useState)(!1),c=(0,o.useRef)(void 0),l=(0,o.useCallback)((()=>{!function(e,t){let{target:n=document.body}=void 0===t?{}:t;if("string"!=typeof e)throw new TypeError(`Expected parameter \`text\` to be a \`string\`, got \`${typeof e}\`.`);const o=document.createElement("textarea"),a=document.activeElement;o.value=e,o.setAttribute("readonly",""),o.style.contain="strict",o.style.position="absolute",o.style.left="-9999px",o.style.fontSize="12pt";const r=document.getSelection(),c=r.rangeCount>0&&r.getRangeAt(0);n.append(o),o.select(),o.selectionStart=0,o.selectionEnd=e.length;let l=!1;try{l=document.execCommand("copy")}catch{}o.remove(),c&&(r.removeAllRanges(),r.addRange(c)),a&&a.focus()}(t),r(!0),c.current=window.setTimeout((()=>{r(!1)}),1e3)}),[t]);return(0,o.useEffect)((()=>()=>window.clearTimeout(c.current)),[]),o.createElement("button",{type:"button","aria-label":a?(0,M.I)({id:"theme.CodeBlock.copied",message:"Copied",description:"The copied button label on code blocks"}):(0,M.I)({id:"theme.CodeBlock.copyButtonAriaLabel",message:"Copy code to clipboard",description:"The ARIA label for copy code blocks button"}),title:(0,M.I)({id:"theme.CodeBlock.copy",message:"Copy",description:"The copy button label on code blocks"}),className:(0,i.Z)("clean-btn",n,V.copyButton,a&&V.copyButtonCopied),onClick:l},o.createElement("span",{className:V.copyButtonIcons,"aria-hidden":"true"},o.createElement(H,{className:V.copyButtonIcon}),o.createElement(D,{className:V.copyButtonSuccessIcon})))}function $(e){return o.createElement("svg",(0,r.Z)({viewBox:"0 0 24 24"},e),o.createElement("path",{fill:"currentColor",d:"M4 19h6v-2H4v2zM20 5H4v2h16V5zm-3 6H4v2h13.25c1.1 0 2 .9 2 2s-.9 2-2 2H15v-2l-3 3l3 3v-2h2c2.21 0 4-1.79 4-4s-1.79-4-4-4z"}))}const F={wordWrapButtonIcon:"wordWrapButtonIcon_Bwma",wordWrapButtonEnabled:"wordWrapButtonEnabled_EoeP"};function q(e){let{className:t,onClick:n,isEnabled:a}=e;const r=(0,M.I)({id:"theme.CodeBlock.wordWrapToggle",message:"Toggle word wrap",description:"The title attribute for toggle word wrapping button of code block lines"});return o.createElement("button",{type:"button",onClick:n,className:(0,i.Z)("clean-btn",t,a&&F.wordWrapButtonEnabled),"aria-label":r,title:r},o.createElement($,{className:F.wordWrapButtonIcon,"aria-hidden":"true"}))}function G(e){let{children:t,className:n="",metastring:a,title:c,showLineNumbers:l,language:s}=e;const{prism:{defaultLanguage:d,magicComments:p}}=(0,u.L)(),f=s??function(e){const t=e.split(" ").find((e=>e.startsWith("language-")));return t?.replace(/language-/,"")}(n)??d,h=m(),y=function(){const[e,t]=(0,o.useState)(!1),[n,a]=(0,o.useState)(!1),r=(0,o.useRef)(null),c=(0,o.useCallback)((()=>{const n=r.current.querySelector("code");e?n.removeAttribute("style"):(n.style.whiteSpace="pre-wrap",n.style.overflowWrap="anywhere"),t((e=>!e))}),[r,e]),l=(0,o.useCallback)((()=>{const{scrollWidth:e,clientWidth:t}=r.current,n=e>t||r.current.querySelector("code").hasAttribute("style");a(n)}),[r]);return Z(r,l),(0,o.useEffect)((()=>{l()}),[e,l]),(0,o.useEffect)((()=>(window.addEventListener("resize",l,{passive:!0}),()=>{window.removeEventListener("resize",l)})),[l]),{codeBlockRef:r,isEnabled:e,isCodeScrollable:n,toggle:c}}(),b=function(e){return e?.match(g)?.groups.title??""}(a)||c,{lineClassNames:E,code:C}=v(t,{metastring:a,language:f,magicComments:p}),w=l??function(e){return Boolean(e?.includes("showLineNumbers"))}(a);return o.createElement(k,{as:"div",className:(0,i.Z)(n,f&&!n.includes(`language-${f}`)&&`language-${f}`)},b&&o.createElement("div",{className:N.codeBlockTitle},b),o.createElement("div",{className:N.codeBlockContent},o.createElement(A,(0,r.Z)({},L,{theme:h,code:C,language:f??"text"}),(e=>{let{className:t,tokens:n,getLineProps:a,getTokenProps:r}=e;return o.createElement("pre",{tabIndex:0,ref:y.codeBlockRef,className:(0,i.Z)(t,N.codeBlock,"thin-scrollbar")},o.createElement("code",{className:(0,i.Z)(N.codeBlockLines,w&&N.codeBlockLinesWithNumbering)},n.map(((e,t)=>o.createElement(W,{key:t,line:e,getLineProps:a,getTokenProps:r,classNames:E[t],showLineNumbers:w})))))})),o.createElement("div",{className:N.buttonGroup},(y.isEnabled||y.isCodeScrollable)&&o.createElement(q,{className:N.codeButton,onClick:()=>y.toggle(),isEnabled:y.isEnabled}),o.createElement(R,{className:N.codeButton,code:C}))))}function U(e){let{children:t,...n}=e;const a=(0,l.Z)(),c=function(e){return o.Children.toArray(e).some((e=>(0,o.isValidElement)(e)))?e:Array.isArray(e)?e.join(""):e}(t),i="string"==typeof c?G:C;return o.createElement(i,(0,r.Z)({key:String(a)},n),c)}var Q=n(9960);var X=n(6043);const Y={details:"details_lb9f",isBrowser:"isBrowser_bmU9",collapsibleContent:"collapsibleContent_i85q"};function J(e){return!!e&&("SUMMARY"===e.tagName||J(e.parentElement))}function K(e,t){return!!e&&(e===t||K(e.parentElement,t))}function ee(e){let{summary:t,children:n,...a}=e;const c=(0,l.Z)(),s=(0,o.useRef)(null),{collapsed:u,setCollapsed:m}=(0,X.u)({initialState:!a.open}),[d,p]=(0,o.useState)(a.open),f=o.isValidElement(t)?t:o.createElement("summary",null,t??"Details");return o.createElement("details",(0,r.Z)({},a,{ref:s,open:d,"data-collapsed":u,className:(0,i.Z)(Y.details,c&&Y.isBrowser,a.className),onMouseDown:e=>{J(e.target)&&e.detail>1&&e.preventDefault()},onClick:e=>{e.stopPropagation();const t=e.target;J(t)&&K(t,s.current)&&(e.preventDefault(),u?(m(!1),p(!0)):m(!0))}}),f,o.createElement(X.z,{lazy:!1,collapsed:u,disableSSRStyle:!0,onCollapseTransitionEnd:e=>{m(e),p(!e)}},o.createElement("div",{className:Y.collapsibleContent},n)))}const te={details:"details_b_Ee"},ne="alert alert--info";function oe(e){let{...t}=e;return o.createElement(ee,(0,r.Z)({},t,{className:(0,i.Z)(ne,te.details,t.className)}))}var ae=n(2503);function re(e){return o.createElement(ae.Z,e)}const ce={containsTaskList:"containsTaskList_mC6p"};const le={img:"img_ev3q"};const ie="admonition_LlT9",se="admonitionHeading_tbUL",ue="admonitionIcon_kALy",me="admonitionContent_S0QG";const de={note:{infimaClassName:"secondary",iconComponent:function(){return o.createElement("svg",{viewBox:"0 0 14 16"},o.createElement("path",{fillRule:"evenodd",d:"M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"}))},label:o.createElement(M.Z,{id:"theme.admonition.note",description:"The default label used for the Note admonition (:::note)"},"note")},tip:{infimaClassName:"success",iconComponent:function(){return o.createElement("svg",{viewBox:"0 0 12 16"},o.createElement("path",{fillRule:"evenodd",d:"M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"}))},label:o.createElement(M.Z,{id:"theme.admonition.tip",description:"The default label used for the Tip admonition (:::tip)"},"tip")},danger:{infimaClassName:"danger",iconComponent:function(){return o.createElement("svg",{viewBox:"0 0 12 16"},o.createElement("path",{fillRule:"evenodd",d:"M5.05.31c.81 2.17.41 3.38-.52 4.31C3.55 5.67 1.98 6.45.9 7.98c-1.45 2.05-1.7 6.53 3.53 7.7-2.2-1.16-2.67-4.52-.3-6.61-.61 2.03.53 3.33 1.94 2.86 1.39-.47 2.3.53 2.27 1.67-.02.78-.31 1.44-1.13 1.81 3.42-.59 4.78-3.42 4.78-5.56 0-2.84-2.53-3.22-1.25-5.61-1.52.13-2.03 1.13-1.89 2.75.09 1.08-1.02 1.8-1.86 1.33-.67-.41-.66-1.19-.06-1.78C8.18 5.31 8.68 2.45 5.05.32L5.03.3l.02.01z"}))},label:o.createElement(M.Z,{id:"theme.admonition.danger",description:"The default label used for the Danger admonition (:::danger)"},"danger")},info:{infimaClassName:"info",iconComponent:function(){return o.createElement("svg",{viewBox:"0 0 14 16"},o.createElement("path",{fillRule:"evenodd",d:"M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"}))},label:o.createElement(M.Z,{id:"theme.admonition.info",description:"The default label used for the Info admonition (:::info)"},"info")},caution:{infimaClassName:"warning",iconComponent:function(){return o.createElement("svg",{viewBox:"0 0 16 16"},o.createElement("path",{fillRule:"evenodd",d:"M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z"}))},label:o.createElement(M.Z,{id:"theme.admonition.caution",description:"The default label used for the Caution admonition (:::caution)"},"caution")}},pe={secondary:"note",important:"info",success:"tip",warning:"danger"};function fe(e){const{mdxAdmonitionTitle:t,rest:n}=function(e){const t=o.Children.toArray(e),n=t.find((e=>o.isValidElement(e)&&"mdxAdmonitionTitle"===e.props?.mdxType)),a=o.createElement(o.Fragment,null,t.filter((e=>e!==n)));return{mdxAdmonitionTitle:n,rest:a}}(e.children);return{...e,title:e.title??t,children:n}}const ge={head:function(e){const t=o.Children.map(e.children,(e=>o.isValidElement(e)?function(e){if(e.props?.mdxType&&e.props.originalType){const{mdxType:t,originalType:n,...a}=e.props;return o.createElement(e.props.originalType,a)}return e}(e):e));return o.createElement(c.Z,e,t)},code:function(e){const t=["a","abbr","b","br","button","cite","code","del","dfn","em","i","img","input","ins","kbd","label","object","output","q","ruby","s","small","span","strong","sub","sup","time","u","var","wbr"];return o.Children.toArray(e.children).every((e=>"string"==typeof e&&!e.includes("\n")||(0,o.isValidElement)(e)&&t.includes(e.props?.mdxType)))?o.createElement("code",e):o.createElement(U,e)},a:function(e){return o.createElement(Q.Z,e)},pre:function(e){return o.createElement(U,(0,o.isValidElement)(e.children)&&"code"===e.children.props?.originalType?e.children.props:{...e})},details:function(e){const t=o.Children.toArray(e.children),n=t.find((e=>o.isValidElement(e)&&"summary"===e.props?.mdxType)),a=o.createElement(o.Fragment,null,t.filter((e=>e!==n)));return o.createElement(oe,(0,r.Z)({},e,{summary:n}),a)},ul:function(e){return o.createElement("ul",(0,r.Z)({},e,{className:(t=e.className,(0,i.Z)(t,t?.includes("contains-task-list")&&ce.containsTaskList))}));var t},img:function(e){return o.createElement("img",(0,r.Z)({loading:"lazy"},e,{className:(t=e.className,(0,i.Z)(t,le.img))}));var t},h1:e=>o.createElement(re,(0,r.Z)({as:"h1"},e)),h2:e=>o.createElement(re,(0,r.Z)({as:"h2"},e)),h3:e=>o.createElement(re,(0,r.Z)({as:"h3"},e)),h4:e=>o.createElement(re,(0,r.Z)({as:"h4"},e)),h5:e=>o.createElement(re,(0,r.Z)({as:"h5"},e)),h6:e=>o.createElement(re,(0,r.Z)({as:"h6"},e)),admonition:function(e){const{children:t,type:n,title:a,icon:r}=fe(e),c=function(e){const t=pe[e]??e,n=de[t];return n||(console.warn(`No admonition config found for admonition type "${t}". Using Info as fallback.`),de.info)}(n),l=a??c.label,{iconComponent:s}=c,u=r??o.createElement(s,null);return o.createElement("div",{className:(0,i.Z)(d.k.common.admonition,d.k.common.admonitionType(e.type),"alert",`alert--${c.infimaClassName}`,ie)},o.createElement("div",{className:se},o.createElement("span",{className:ue},u),l),o.createElement("div",{className:me},t))},mermaid:n(1875).Z};function he(e){let{children:t}=e;return o.createElement(a.Zo,{components:ge},t)}},2244:(e,t,n)=>{"use strict";n.d(t,{Z:()=>c});var o=n(7294),a=n(6010),r=n(9960);function c(e){const{permalink:t,title:n,subLabel:c,isNext:l}=e;return o.createElement(r.Z,{className:(0,a.Z)("pagination-nav__link",l?"pagination-nav__link--next":"pagination-nav__link--prev"),to:t},c&&o.createElement("div",{className:"pagination-nav__sublabel"},c),o.createElement("div",{className:"pagination-nav__label"},n))}},3008:(e,t,n)=>{"use strict";n.d(t,{Z:()=>l});var o=n(7294),a=n(6010),r=n(9960);const c={tag:"tag_zVej",tagRegular:"tagRegular_sFm0",tagWithCount:"tagWithCount_h2kH"};function l(e){let{permalink:t,label:n,count:l}=e;return o.createElement(r.Z,{href:t,className:(0,a.Z)(c.tag,l?c.tagWithCount:c.tagRegular)},n,l&&o.createElement("span",null,l))}},1526:(e,t,n)=>{"use strict";n.d(t,{Z:()=>i});var o=n(7294),a=n(6010),r=n(5999),c=n(3008);const l={tags:"tags_jXut",tag:"tag_QGVx"};function i(e){let{tags:t}=e;return o.createElement(o.Fragment,null,o.createElement("b",null,o.createElement(r.Z,{id:"theme.tags.tagsListLabel",description:"The label alongside a tag list"},"Tags:")),o.createElement("ul",{className:(0,a.Z)(l.tags,"padding--none","margin-left--sm")},t.map((e=>{let{label:t,permalink:n}=e;return o.createElement("li",{key:n,className:l.tag},o.createElement(c.Z,{label:t,permalink:n}))}))))}},7594:(e,t)=>{function n(e){let t,n=[];for(let o of e.split(",").map((e=>e.trim())))if(/^-?\d+$/.test(o))n.push(parseInt(o,10));else if(t=o.match(/^(-?\d+)(-|\.\.\.?|\u2025|\u2026|\u22EF)(-?\d+)$/)){let[e,o,a,r]=t;if(o&&r){o=parseInt(o),r=parseInt(r);const e=o<r?1:-1;"-"!==a&&".."!==a&&"\u2025"!==a||(r+=e);for(let t=o;t!==r;t+=e)n.push(t)}}return n}t.default=n,e.exports=n}}]); \ No newline at end of file +(self.webpackChunkdocs=self.webpackChunkdocs||[]).push([[9785],{3905:(e,t,n)=>{"use strict";n.d(t,{Zo:()=>u,kt:()=>f});var o=n(7294);function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function r(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);t&&(o=o.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,o)}return n}function c(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?r(Object(n),!0).forEach((function(t){a(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):r(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function l(e,t){if(null==e)return{};var n,o,a=function(e,t){if(null==e)return{};var n,o,a={},r=Object.keys(e);for(o=0;o<r.length;o++)n=r[o],t.indexOf(n)>=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(o=0;o<r.length;o++)n=r[o],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var i=o.createContext({}),s=function(e){var t=o.useContext(i),n=t;return e&&(n="function"==typeof e?e(t):c(c({},t),e)),n},u=function(e){var t=s(e.components);return o.createElement(i.Provider,{value:t},e.children)},m="mdxType",d={inlineCode:"code",wrapper:function(e){var t=e.children;return o.createElement(o.Fragment,{},t)}},p=o.forwardRef((function(e,t){var n=e.components,a=e.mdxType,r=e.originalType,i=e.parentName,u=l(e,["components","mdxType","originalType","parentName"]),m=s(n),p=a,f=m["".concat(i,".").concat(p)]||m[p]||d[p]||r;return n?o.createElement(f,c(c({ref:t},u),{},{components:n})):o.createElement(f,c({ref:t},u))}));function f(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var r=n.length,c=new Array(r);c[0]=p;var l={};for(var i in t)hasOwnProperty.call(t,i)&&(l[i]=t[i]);l.originalType=e,l[m]="string"==typeof e?e:a,c[1]=l;for(var s=2;s<r;s++)c[s]=n[s];return o.createElement.apply(null,c)}return o.createElement.apply(null,n)}p.displayName="MDXCreateElement"},4881:(e,t,n)=>{"use strict";n.d(t,{Z:()=>u});var o=n(7294),a=n(5999),r=n(5281),c=n(7462),l=n(6010);const i={iconEdit:"iconEdit_Z9Sw"};function s(e){let{className:t,...n}=e;return o.createElement("svg",(0,c.Z)({fill:"currentColor",height:"20",width:"20",viewBox:"0 0 40 40",className:(0,l.Z)(i.iconEdit,t),"aria-hidden":"true"},n),o.createElement("g",null,o.createElement("path",{d:"m34.5 11.7l-3 3.1-6.3-6.3 3.1-3q0.5-0.5 1.2-0.5t1.1 0.5l3.9 3.9q0.5 0.4 0.5 1.1t-0.5 1.2z m-29.5 17.1l18.4-18.5 6.3 6.3-18.4 18.4h-6.3v-6.2z"})))}function u(e){let{editUrl:t}=e;return o.createElement("a",{href:t,target:"_blank",rel:"noreferrer noopener",className:r.k.common.editThisPage},o.createElement(s,null),o.createElement(a.Z,{id:"theme.common.editThisPage",description:"The link label to edit the current page"},"Edit this page"))}},2503:(e,t,n)=>{"use strict";n.d(t,{Z:()=>u});var o=n(7462),a=n(7294),r=n(6010),c=n(5999),l=n(6668),i=n(9960);const s={anchorWithStickyNavbar:"anchorWithStickyNavbar_LWe7",anchorWithHideOnScrollNavbar:"anchorWithHideOnScrollNavbar_WYt5"};function u(e){let{as:t,id:n,...u}=e;const{navbar:{hideOnScroll:m}}=(0,l.L)();if("h1"===t||!n)return a.createElement(t,(0,o.Z)({},u,{id:void 0}));const d=(0,c.I)({id:"theme.common.headingLinkTitle",message:"Direct link to {heading}",description:"Title for link to heading"},{heading:"string"==typeof u.children?u.children:n});return a.createElement(t,(0,o.Z)({},u,{className:(0,r.Z)("anchor",m?s.anchorWithHideOnScrollNavbar:s.anchorWithStickyNavbar,u.className),id:n}),u.children,a.createElement(i.Z,{className:"hash-link",to:`#${n}`,"aria-label":d,title:d},"\u200b"))}},1506:(e,t,n)=>{"use strict";n.d(t,{Z:()=>ye});var o=n(7294),a=n(3905),r=n(7462),c=n(5742);var l=n(2389),i=n(6010),s=n(2949),u=n(6668);function m(){const{prism:e}=(0,u.L)(),{colorMode:t}=(0,s.I)(),n=e.theme,o=e.darkTheme||n;return"dark"===t?o:n}var d=n(5281),p=n(7594),f=n.n(p);const g=/title=(?<quote>["'])(?<title>.*?)\1/,h=/\{(?<range>[\d,-]+)\}/,y={js:{start:"\\/\\/",end:""},jsBlock:{start:"\\/\\*",end:"\\*\\/"},jsx:{start:"\\{\\s*\\/\\*",end:"\\*\\/\\s*\\}"},bash:{start:"#",end:""},html:{start:"\x3c!--",end:"--\x3e"}};function b(e,t){const n=e.map((e=>{const{start:n,end:o}=y[e];return`(?:${n}\\s*(${t.flatMap((e=>[e.line,e.block?.start,e.block?.end].filter(Boolean))).join("|")})\\s*${o})`})).join("|");return new RegExp(`^\\s*(?:${n})\\s*$`)}function v(e,t){let n=e.replace(/\n$/,"");const{language:o,magicComments:a,metastring:r}=t;if(r&&h.test(r)){const e=r.match(h).groups.range;if(0===a.length)throw new Error(`A highlight range has been given in code block's metastring (\`\`\` ${r}), but no magic comment config is available. Docusaurus applies the first magic comment entry's className for metastring ranges.`);const t=a[0].className,o=f()(e).filter((e=>e>0)).map((e=>[e-1,[t]]));return{lineClassNames:Object.fromEntries(o),code:n}}if(void 0===o)return{lineClassNames:{},code:n};const c=function(e,t){switch(e){case"js":case"javascript":case"ts":case"typescript":return b(["js","jsBlock"],t);case"jsx":case"tsx":return b(["js","jsBlock","jsx"],t);case"html":return b(["js","jsBlock","html"],t);case"python":case"py":case"bash":return b(["bash"],t);case"markdown":case"md":return b(["html","jsx","bash"],t);default:return b(Object.keys(y),t)}}(o,a),l=n.split("\n"),i=Object.fromEntries(a.map((e=>[e.className,{start:0,range:""}]))),s=Object.fromEntries(a.filter((e=>e.line)).map((e=>{let{className:t,line:n}=e;return[n,t]}))),u=Object.fromEntries(a.filter((e=>e.block)).map((e=>{let{className:t,block:n}=e;return[n.start,t]}))),m=Object.fromEntries(a.filter((e=>e.block)).map((e=>{let{className:t,block:n}=e;return[n.end,t]})));for(let p=0;p<l.length;){const e=l[p].match(c);if(!e){p+=1;continue}const t=e.slice(1).find((e=>void 0!==e));s[t]?i[s[t]].range+=`${p},`:u[t]?i[u[t]].start=p:m[t]&&(i[m[t]].range+=`${i[m[t]].start}-${p-1},`),l.splice(p,1)}n=l.join("\n");const d={};return Object.entries(i).forEach((e=>{let[t,{range:n}]=e;f()(n).forEach((e=>{d[e]??=[],d[e].push(t)}))})),{lineClassNames:d,code:n}}const E={codeBlockContainer:"codeBlockContainer_Ckt0"};function k(e){let{as:t,...n}=e;const a=function(e){const t={color:"--prism-color",backgroundColor:"--prism-background-color"},n={};return Object.entries(e.plain).forEach((e=>{let[o,a]=e;const r=t[o];r&&"string"==typeof a&&(n[r]=a)})),n}(m());return o.createElement(t,(0,r.Z)({},n,{style:a,className:(0,i.Z)(n.className,E.codeBlockContainer,d.k.common.codeBlock)}))}const N={codeBlockContent:"codeBlockContent_biex",codeBlockTitle:"codeBlockTitle_Ktv7",codeBlock:"codeBlock_bY9V",codeBlockStandalone:"codeBlockStandalone_MEMb",codeBlockLines:"codeBlockLines_e6Vv",codeBlockLinesWithNumbering:"codeBlockLinesWithNumbering_o6Pm",buttonGroup:"buttonGroup__atx"};function C(e){let{children:t,className:n}=e;return o.createElement(k,{as:"pre",tabIndex:0,className:(0,i.Z)(N.codeBlockStandalone,"thin-scrollbar",n)},o.createElement("code",{className:N.codeBlockLines},t))}var w=n(902);const B={attributes:!0,characterData:!0,childList:!0,subtree:!0};function Z(e,t){const[n,a]=(0,o.useState)(),r=(0,o.useCallback)((()=>{a(e.current?.closest("[role=tabpanel][hidden]"))}),[e,a]);(0,o.useEffect)((()=>{r()}),[r]),function(e,t,n){void 0===n&&(n=B);const a=(0,w.zX)(t),r=(0,w.Ql)(n);(0,o.useEffect)((()=>{const t=new MutationObserver(a);return e&&t.observe(e,r),()=>t.disconnect()}),[e,a,r])}(n,(e=>{e.forEach((e=>{"attributes"===e.type&&"hidden"===e.attributeName&&(t(),r())}))}),{attributes:!0,characterData:!1,childList:!1,subtree:!1})}const T={plain:{backgroundColor:"#2a2734",color:"#9a86fd"},styles:[{types:["comment","prolog","doctype","cdata","punctuation"],style:{color:"#6c6783"}},{types:["namespace"],style:{opacity:.7}},{types:["tag","operator","number"],style:{color:"#e09142"}},{types:["property","function"],style:{color:"#9a86fd"}},{types:["tag-id","selector","atrule-id"],style:{color:"#eeebff"}},{types:["attr-name"],style:{color:"#c4b9fe"}},{types:["boolean","string","entity","url","attr-value","keyword","control","directive","unit","statement","regex","atrule","placeholder","variable"],style:{color:"#ffcc99"}},{types:["deleted"],style:{textDecorationLine:"line-through"}},{types:["inserted"],style:{textDecorationLine:"underline"}},{types:["italic"],style:{fontStyle:"italic"}},{types:["important","bold"],style:{fontWeight:"bold"}},{types:["important"],style:{color:"#c4b9fe"}}]};var L={Prism:n(7410).Z,theme:T};function j(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function _(){return _=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var o in n)Object.prototype.hasOwnProperty.call(n,o)&&(e[o]=n[o])}return e},_.apply(this,arguments)}var x=/\r\n|\r|\n/,O=function(e){0===e.length?e.push({types:["plain"],content:"\n",empty:!0}):1===e.length&&""===e[0].content&&(e[0].content="\n",e[0].empty=!0)},S=function(e,t){var n=e.length;return n>0&&e[n-1]===t?e:e.concat(t)};function P(e,t){var n={};for(var o in e)Object.prototype.hasOwnProperty.call(e,o)&&-1===t.indexOf(o)&&(n[o]=e[o]);return n}var z=function(e){function t(){for(var t=this,n=[],o=arguments.length;o--;)n[o]=arguments[o];e.apply(this,n),j(this,"getThemeDict",(function(e){if(void 0!==t.themeDict&&e.theme===t.prevTheme&&e.language===t.prevLanguage)return t.themeDict;t.prevTheme=e.theme,t.prevLanguage=e.language;var n=e.theme?function(e,t){var n=e.plain,o=Object.create(null),a=e.styles.reduce((function(e,n){var o=n.languages,a=n.style;return o&&!o.includes(t)||n.types.forEach((function(t){var n=_({},e[t],a);e[t]=n})),e}),o);return a.root=n,a.plain=_({},n,{backgroundColor:null}),a}(e.theme,e.language):void 0;return t.themeDict=n})),j(this,"getLineProps",(function(e){var n=e.key,o=e.className,a=e.style,r=_({},P(e,["key","className","style","line"]),{className:"token-line",style:void 0,key:void 0}),c=t.getThemeDict(t.props);return void 0!==c&&(r.style=c.plain),void 0!==a&&(r.style=void 0!==r.style?_({},r.style,a):a),void 0!==n&&(r.key=n),o&&(r.className+=" "+o),r})),j(this,"getStyleForToken",(function(e){var n=e.types,o=e.empty,a=n.length,r=t.getThemeDict(t.props);if(void 0!==r){if(1===a&&"plain"===n[0])return o?{display:"inline-block"}:void 0;if(1===a&&!o)return r[n[0]];var c=o?{display:"inline-block"}:{},l=n.map((function(e){return r[e]}));return Object.assign.apply(Object,[c].concat(l))}})),j(this,"getTokenProps",(function(e){var n=e.key,o=e.className,a=e.style,r=e.token,c=_({},P(e,["key","className","style","token"]),{className:"token "+r.types.join(" "),children:r.content,style:t.getStyleForToken(r),key:void 0});return void 0!==a&&(c.style=void 0!==c.style?_({},c.style,a):a),void 0!==n&&(c.key=n),o&&(c.className+=" "+o),c})),j(this,"tokenize",(function(e,t,n,o){var a={code:t,grammar:n,language:o,tokens:[]};e.hooks.run("before-tokenize",a);var r=a.tokens=e.tokenize(a.code,a.grammar,a.language);return e.hooks.run("after-tokenize",a),r}))}return e&&(t.__proto__=e),t.prototype=Object.create(e&&e.prototype),t.prototype.constructor=t,t.prototype.render=function(){var e=this.props,t=e.Prism,n=e.language,o=e.code,a=e.children,r=this.getThemeDict(this.props),c=t.languages[n];return a({tokens:function(e){for(var t=[[]],n=[e],o=[0],a=[e.length],r=0,c=0,l=[],i=[l];c>-1;){for(;(r=o[c]++)<a[c];){var s=void 0,u=t[c],m=n[c][r];if("string"==typeof m?(u=c>0?u:["plain"],s=m):(u=S(u,m.type),m.alias&&(u=S(u,m.alias)),s=m.content),"string"==typeof s){var d=s.split(x),p=d.length;l.push({types:u,content:d[0]});for(var f=1;f<p;f++)O(l),i.push(l=[]),l.push({types:u,content:d[f]})}else c++,t.push(u),n.push(s),o.push(0),a.push(s.length)}c--,t.pop(),n.pop(),o.pop(),a.pop()}return O(l),i}(void 0!==c?this.tokenize(t,o,c,n):[o]),className:"prism-code language-"+n,style:void 0!==r?r.root:{},getLineProps:this.getLineProps,getTokenProps:this.getTokenProps})},t}(o.Component);const A=z,I={codeLine:"codeLine_lJS_",codeLineNumber:"codeLineNumber_Tfdd",codeLineContent:"codeLineContent_feaV"};function W(e){let{line:t,classNames:n,showLineNumbers:a,getLineProps:c,getTokenProps:l}=e;1===t.length&&"\n"===t[0].content&&(t[0].content="");const s=c({line:t,className:(0,i.Z)(n,a&&I.codeLine)}),u=t.map(((e,t)=>o.createElement("span",(0,r.Z)({key:t},l({token:e,key:t})))));return o.createElement("span",s,a?o.createElement(o.Fragment,null,o.createElement("span",{className:I.codeLineNumber}),o.createElement("span",{className:I.codeLineContent},u)):u,o.createElement("br",null))}var M=n(5999);function H(e){return o.createElement("svg",(0,r.Z)({viewBox:"0 0 24 24"},e),o.createElement("path",{fill:"currentColor",d:"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"}))}function D(e){return o.createElement("svg",(0,r.Z)({viewBox:"0 0 24 24"},e),o.createElement("path",{fill:"currentColor",d:"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"}))}const V={copyButtonCopied:"copyButtonCopied_obH4",copyButtonIcons:"copyButtonIcons_eSgA",copyButtonIcon:"copyButtonIcon_y97N",copyButtonSuccessIcon:"copyButtonSuccessIcon_LjdS"};function R(e){let{code:t,className:n}=e;const[a,r]=(0,o.useState)(!1),c=(0,o.useRef)(void 0),l=(0,o.useCallback)((()=>{!function(e,t){let{target:n=document.body}=void 0===t?{}:t;if("string"!=typeof e)throw new TypeError(`Expected parameter \`text\` to be a \`string\`, got \`${typeof e}\`.`);const o=document.createElement("textarea"),a=document.activeElement;o.value=e,o.setAttribute("readonly",""),o.style.contain="strict",o.style.position="absolute",o.style.left="-9999px",o.style.fontSize="12pt";const r=document.getSelection(),c=r.rangeCount>0&&r.getRangeAt(0);n.append(o),o.select(),o.selectionStart=0,o.selectionEnd=e.length;let l=!1;try{l=document.execCommand("copy")}catch{}o.remove(),c&&(r.removeAllRanges(),r.addRange(c)),a&&a.focus()}(t),r(!0),c.current=window.setTimeout((()=>{r(!1)}),1e3)}),[t]);return(0,o.useEffect)((()=>()=>window.clearTimeout(c.current)),[]),o.createElement("button",{type:"button","aria-label":a?(0,M.I)({id:"theme.CodeBlock.copied",message:"Copied",description:"The copied button label on code blocks"}):(0,M.I)({id:"theme.CodeBlock.copyButtonAriaLabel",message:"Copy code to clipboard",description:"The ARIA label for copy code blocks button"}),title:(0,M.I)({id:"theme.CodeBlock.copy",message:"Copy",description:"The copy button label on code blocks"}),className:(0,i.Z)("clean-btn",n,V.copyButton,a&&V.copyButtonCopied),onClick:l},o.createElement("span",{className:V.copyButtonIcons,"aria-hidden":"true"},o.createElement(H,{className:V.copyButtonIcon}),o.createElement(D,{className:V.copyButtonSuccessIcon})))}function $(e){return o.createElement("svg",(0,r.Z)({viewBox:"0 0 24 24"},e),o.createElement("path",{fill:"currentColor",d:"M4 19h6v-2H4v2zM20 5H4v2h16V5zm-3 6H4v2h13.25c1.1 0 2 .9 2 2s-.9 2-2 2H15v-2l-3 3l3 3v-2h2c2.21 0 4-1.79 4-4s-1.79-4-4-4z"}))}const F={wordWrapButtonIcon:"wordWrapButtonIcon_Bwma",wordWrapButtonEnabled:"wordWrapButtonEnabled_EoeP"};function q(e){let{className:t,onClick:n,isEnabled:a}=e;const r=(0,M.I)({id:"theme.CodeBlock.wordWrapToggle",message:"Toggle word wrap",description:"The title attribute for toggle word wrapping button of code block lines"});return o.createElement("button",{type:"button",onClick:n,className:(0,i.Z)("clean-btn",t,a&&F.wordWrapButtonEnabled),"aria-label":r,title:r},o.createElement($,{className:F.wordWrapButtonIcon,"aria-hidden":"true"}))}function G(e){let{children:t,className:n="",metastring:a,title:c,showLineNumbers:l,language:s}=e;const{prism:{defaultLanguage:d,magicComments:p}}=(0,u.L)(),f=s??function(e){const t=e.split(" ").find((e=>e.startsWith("language-")));return t?.replace(/language-/,"")}(n)??d,h=m(),y=function(){const[e,t]=(0,o.useState)(!1),[n,a]=(0,o.useState)(!1),r=(0,o.useRef)(null),c=(0,o.useCallback)((()=>{const n=r.current.querySelector("code");e?n.removeAttribute("style"):(n.style.whiteSpace="pre-wrap",n.style.overflowWrap="anywhere"),t((e=>!e))}),[r,e]),l=(0,o.useCallback)((()=>{const{scrollWidth:e,clientWidth:t}=r.current,n=e>t||r.current.querySelector("code").hasAttribute("style");a(n)}),[r]);return Z(r,l),(0,o.useEffect)((()=>{l()}),[e,l]),(0,o.useEffect)((()=>(window.addEventListener("resize",l,{passive:!0}),()=>{window.removeEventListener("resize",l)})),[l]),{codeBlockRef:r,isEnabled:e,isCodeScrollable:n,toggle:c}}(),b=function(e){return e?.match(g)?.groups.title??""}(a)||c,{lineClassNames:E,code:C}=v(t,{metastring:a,language:f,magicComments:p}),w=l??function(e){return Boolean(e?.includes("showLineNumbers"))}(a);return o.createElement(k,{as:"div",className:(0,i.Z)(n,f&&!n.includes(`language-${f}`)&&`language-${f}`)},b&&o.createElement("div",{className:N.codeBlockTitle},b),o.createElement("div",{className:N.codeBlockContent},o.createElement(A,(0,r.Z)({},L,{theme:h,code:C,language:f??"text"}),(e=>{let{className:t,tokens:n,getLineProps:a,getTokenProps:r}=e;return o.createElement("pre",{tabIndex:0,ref:y.codeBlockRef,className:(0,i.Z)(t,N.codeBlock,"thin-scrollbar")},o.createElement("code",{className:(0,i.Z)(N.codeBlockLines,w&&N.codeBlockLinesWithNumbering)},n.map(((e,t)=>o.createElement(W,{key:t,line:e,getLineProps:a,getTokenProps:r,classNames:E[t],showLineNumbers:w})))))})),o.createElement("div",{className:N.buttonGroup},(y.isEnabled||y.isCodeScrollable)&&o.createElement(q,{className:N.codeButton,onClick:()=>y.toggle(),isEnabled:y.isEnabled}),o.createElement(R,{className:N.codeButton,code:C}))))}function U(e){let{children:t,...n}=e;const a=(0,l.Z)(),c=function(e){return o.Children.toArray(e).some((e=>(0,o.isValidElement)(e)))?e:Array.isArray(e)?e.join(""):e}(t),i="string"==typeof c?G:C;return o.createElement(i,(0,r.Z)({key:String(a)},n),c)}var Q=n(9960);var X=n(6043);const Y={details:"details_lb9f",isBrowser:"isBrowser_bmU9",collapsibleContent:"collapsibleContent_i85q"};function J(e){return!!e&&("SUMMARY"===e.tagName||J(e.parentElement))}function K(e,t){return!!e&&(e===t||K(e.parentElement,t))}function ee(e){let{summary:t,children:n,...a}=e;const c=(0,l.Z)(),s=(0,o.useRef)(null),{collapsed:u,setCollapsed:m}=(0,X.u)({initialState:!a.open}),[d,p]=(0,o.useState)(a.open),f=o.isValidElement(t)?t:o.createElement("summary",null,t??"Details");return o.createElement("details",(0,r.Z)({},a,{ref:s,open:d,"data-collapsed":u,className:(0,i.Z)(Y.details,c&&Y.isBrowser,a.className),onMouseDown:e=>{J(e.target)&&e.detail>1&&e.preventDefault()},onClick:e=>{e.stopPropagation();const t=e.target;J(t)&&K(t,s.current)&&(e.preventDefault(),u?(m(!1),p(!0)):m(!0))}}),f,o.createElement(X.z,{lazy:!1,collapsed:u,disableSSRStyle:!0,onCollapseTransitionEnd:e=>{m(e),p(!e)}},o.createElement("div",{className:Y.collapsibleContent},n)))}const te={details:"details_b_Ee"},ne="alert alert--info";function oe(e){let{...t}=e;return o.createElement(ee,(0,r.Z)({},t,{className:(0,i.Z)(ne,te.details,t.className)}))}var ae=n(2503);function re(e){return o.createElement(ae.Z,e)}const ce={containsTaskList:"containsTaskList_mC6p"};function le(e){if(void 0!==e)return(0,i.Z)(e,e?.includes("contains-task-list")&&ce.containsTaskList)}const ie={img:"img_ev3q"};const se="admonition_LlT9",ue="admonitionHeading_tbUL",me="admonitionIcon_kALy",de="admonitionContent_S0QG";const pe={note:{infimaClassName:"secondary",iconComponent:function(){return o.createElement("svg",{viewBox:"0 0 14 16"},o.createElement("path",{fillRule:"evenodd",d:"M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"}))},label:o.createElement(M.Z,{id:"theme.admonition.note",description:"The default label used for the Note admonition (:::note)"},"note")},tip:{infimaClassName:"success",iconComponent:function(){return o.createElement("svg",{viewBox:"0 0 12 16"},o.createElement("path",{fillRule:"evenodd",d:"M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"}))},label:o.createElement(M.Z,{id:"theme.admonition.tip",description:"The default label used for the Tip admonition (:::tip)"},"tip")},danger:{infimaClassName:"danger",iconComponent:function(){return o.createElement("svg",{viewBox:"0 0 12 16"},o.createElement("path",{fillRule:"evenodd",d:"M5.05.31c.81 2.17.41 3.38-.52 4.31C3.55 5.67 1.98 6.45.9 7.98c-1.45 2.05-1.7 6.53 3.53 7.7-2.2-1.16-2.67-4.52-.3-6.61-.61 2.03.53 3.33 1.94 2.86 1.39-.47 2.3.53 2.27 1.67-.02.78-.31 1.44-1.13 1.81 3.42-.59 4.78-3.42 4.78-5.56 0-2.84-2.53-3.22-1.25-5.61-1.52.13-2.03 1.13-1.89 2.75.09 1.08-1.02 1.8-1.86 1.33-.67-.41-.66-1.19-.06-1.78C8.18 5.31 8.68 2.45 5.05.32L5.03.3l.02.01z"}))},label:o.createElement(M.Z,{id:"theme.admonition.danger",description:"The default label used for the Danger admonition (:::danger)"},"danger")},info:{infimaClassName:"info",iconComponent:function(){return o.createElement("svg",{viewBox:"0 0 14 16"},o.createElement("path",{fillRule:"evenodd",d:"M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"}))},label:o.createElement(M.Z,{id:"theme.admonition.info",description:"The default label used for the Info admonition (:::info)"},"info")},caution:{infimaClassName:"warning",iconComponent:function(){return o.createElement("svg",{viewBox:"0 0 16 16"},o.createElement("path",{fillRule:"evenodd",d:"M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z"}))},label:o.createElement(M.Z,{id:"theme.admonition.caution",description:"The default label used for the Caution admonition (:::caution)"},"caution")}},fe={secondary:"note",important:"info",success:"tip",warning:"danger"};function ge(e){const{mdxAdmonitionTitle:t,rest:n}=function(e){const t=o.Children.toArray(e),n=t.find((e=>o.isValidElement(e)&&"mdxAdmonitionTitle"===e.props?.mdxType)),a=o.createElement(o.Fragment,null,t.filter((e=>e!==n)));return{mdxAdmonitionTitle:n,rest:a}}(e.children);return{...e,title:e.title??t,children:n}}const he={head:function(e){const t=o.Children.map(e.children,(e=>o.isValidElement(e)?function(e){if(e.props?.mdxType&&e.props.originalType){const{mdxType:t,originalType:n,...a}=e.props;return o.createElement(e.props.originalType,a)}return e}(e):e));return o.createElement(c.Z,e,t)},code:function(e){const t=["a","abbr","b","br","button","cite","code","del","dfn","em","i","img","input","ins","kbd","label","object","output","q","ruby","s","small","span","strong","sub","sup","time","u","var","wbr"];return o.Children.toArray(e.children).every((e=>"string"==typeof e&&!e.includes("\n")||(0,o.isValidElement)(e)&&t.includes(e.props?.mdxType)))?o.createElement("code",e):o.createElement(U,e)},a:function(e){return o.createElement(Q.Z,e)},pre:function(e){return o.createElement(U,(0,o.isValidElement)(e.children)&&"code"===e.children.props?.originalType?e.children.props:{...e})},details:function(e){const t=o.Children.toArray(e.children),n=t.find((e=>o.isValidElement(e)&&"summary"===e.props?.mdxType)),a=o.createElement(o.Fragment,null,t.filter((e=>e!==n)));return o.createElement(oe,(0,r.Z)({},e,{summary:n}),a)},ul:function(e){return o.createElement("ul",(0,r.Z)({},e,{className:le(e.className)}))},img:function(e){return o.createElement("img",(0,r.Z)({loading:"lazy"},e,{className:(t=e.className,(0,i.Z)(t,ie.img))}));var t},h1:e=>o.createElement(re,(0,r.Z)({as:"h1"},e)),h2:e=>o.createElement(re,(0,r.Z)({as:"h2"},e)),h3:e=>o.createElement(re,(0,r.Z)({as:"h3"},e)),h4:e=>o.createElement(re,(0,r.Z)({as:"h4"},e)),h5:e=>o.createElement(re,(0,r.Z)({as:"h5"},e)),h6:e=>o.createElement(re,(0,r.Z)({as:"h6"},e)),admonition:function(e){const{children:t,type:n,title:a,icon:r}=ge(e),c=function(e){const t=fe[e]??e,n=pe[t];return n||(console.warn(`No admonition config found for admonition type "${t}". Using Info as fallback.`),pe.info)}(n),l=a??c.label,{iconComponent:s}=c,u=r??o.createElement(s,null);return o.createElement("div",{className:(0,i.Z)(d.k.common.admonition,d.k.common.admonitionType(e.type),"alert",`alert--${c.infimaClassName}`,se)},o.createElement("div",{className:ue},o.createElement("span",{className:me},u),l),o.createElement("div",{className:de},t))},mermaid:n(1875).Z};function ye(e){let{children:t}=e;return o.createElement(a.Zo,{components:he},t)}},2244:(e,t,n)=>{"use strict";n.d(t,{Z:()=>c});var o=n(7294),a=n(6010),r=n(9960);function c(e){const{permalink:t,title:n,subLabel:c,isNext:l}=e;return o.createElement(r.Z,{className:(0,a.Z)("pagination-nav__link",l?"pagination-nav__link--next":"pagination-nav__link--prev"),to:t},c&&o.createElement("div",{className:"pagination-nav__sublabel"},c),o.createElement("div",{className:"pagination-nav__label"},n))}},3008:(e,t,n)=>{"use strict";n.d(t,{Z:()=>l});var o=n(7294),a=n(6010),r=n(9960);const c={tag:"tag_zVej",tagRegular:"tagRegular_sFm0",tagWithCount:"tagWithCount_h2kH"};function l(e){let{permalink:t,label:n,count:l}=e;return o.createElement(r.Z,{href:t,className:(0,a.Z)(c.tag,l?c.tagWithCount:c.tagRegular)},n,l&&o.createElement("span",null,l))}},1526:(e,t,n)=>{"use strict";n.d(t,{Z:()=>i});var o=n(7294),a=n(6010),r=n(5999),c=n(3008);const l={tags:"tags_jXut",tag:"tag_QGVx"};function i(e){let{tags:t}=e;return o.createElement(o.Fragment,null,o.createElement("b",null,o.createElement(r.Z,{id:"theme.tags.tagsListLabel",description:"The label alongside a tag list"},"Tags:")),o.createElement("ul",{className:(0,a.Z)(l.tags,"padding--none","margin-left--sm")},t.map((e=>{let{label:t,permalink:n}=e;return o.createElement("li",{key:n,className:l.tag},o.createElement(c.Z,{label:t,permalink:n}))}))))}},7594:(e,t)=>{function n(e){let t,n=[];for(let o of e.split(",").map((e=>e.trim())))if(/^-?\d+$/.test(o))n.push(parseInt(o,10));else if(t=o.match(/^(-?\d+)(-|\.\.\.?|\u2025|\u2026|\u22EF)(-?\d+)$/)){let[e,o,a,r]=t;if(o&&r){o=parseInt(o),r=parseInt(r);const e=o<r?1:-1;"-"!==a&&".."!==a&&"\u2025"!==a||(r+=e);for(let t=o;t!==r;t+=e)n.push(t)}}return n}t.default=n,e.exports=n}}]); \ No newline at end of file diff --git a/docs/dev/assets/js/aff456d7.6ab5288b.js b/docs/dev/assets/js/aff456d7.6ab5288b.js deleted file mode 100644 index 13ede8df..00000000 --- a/docs/dev/assets/js/aff456d7.6ab5288b.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkdocs=self.webpackChunkdocs||[]).push([[1849],{3905:(e,t,n)=>{n.d(t,{Zo:()=>p,kt:()=>f});var a=n(7294);function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function o(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function l(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?o(Object(n),!0).forEach((function(t){r(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):o(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function i(e,t){if(null==e)return{};var n,a,r=function(e,t){if(null==e)return{};var n,a,r={},o=Object.keys(e);for(a=0;a<o.length;a++)n=o[a],t.indexOf(n)>=0||(r[n]=e[n]);return r}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(a=0;a<o.length;a++)n=o[a],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(r[n]=e[n])}return r}var c=a.createContext({}),s=function(e){var t=a.useContext(c),n=t;return e&&(n="function"==typeof e?e(t):l(l({},t),e)),n},p=function(e){var t=s(e.components);return a.createElement(c.Provider,{value:t},e.children)},u="mdxType",d={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},m=a.forwardRef((function(e,t){var n=e.components,r=e.mdxType,o=e.originalType,c=e.parentName,p=i(e,["components","mdxType","originalType","parentName"]),u=s(n),m=r,f=u["".concat(c,".").concat(m)]||u[m]||d[m]||o;return n?a.createElement(f,l(l({ref:t},p),{},{components:n})):a.createElement(f,l({ref:t},p))}));function f(e,t){var n=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var o=n.length,l=new Array(o);l[0]=m;var i={};for(var c in t)hasOwnProperty.call(t,c)&&(i[c]=t[c]);i.originalType=e,i[u]="string"==typeof e?e:r,l[1]=i;for(var s=2;s<o;s++)l[s]=n[s];return a.createElement.apply(null,l)}return a.createElement.apply(null,n)}m.displayName="MDXCreateElement"},8814:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>l,default:()=>d,frontMatter:()=>o,metadata:()=>i,toc:()=>s});var a=n(7462),r=(n(7294),n(3905));const o={},l="CALC_DISTANCE",i={unversionedId:"sql-syntax/functions/geometry/calc-distance",id:"sql-syntax/functions/geometry/calc-distance",title:"CALC_DISTANCE",description:"The CALC_DISTANCE function is used to calculate the Euclidean distance between two Point type geographical coordinates.",source:"@site/docs/sql-syntax/functions/geometry/calc-distance.md",sourceDirName:"sql-syntax/functions/geometry",slug:"/sql-syntax/functions/geometry/calc-distance",permalink:"/docs/dev/sql-syntax/functions/geometry/calc-distance",draft:!1,tags:[],version:"current",frontMatter:{},sidebar:"autoSidebar",previous:{title:"PREPEND",permalink:"/docs/dev/sql-syntax/functions/list-map/prepend"},next:{title:"GET_X",permalink:"/docs/dev/sql-syntax/functions/geometry/get-x"}},c={},s=[{value:"Syntax",id:"syntax",level:2},{value:"Examples",id:"examples",level:2},{value:"Example 1: Calculate the distance between two points",id:"example-1-calculate-the-distance-between-two-points",level:3},{value:"Errors",id:"errors",level:2}],p={toc:s},u="wrapper";function d(e){let{components:t,...n}=e;return(0,r.kt)(u,(0,a.Z)({},p,n,{components:t,mdxType:"MDXLayout"}),(0,r.kt)("h1",{id:"calc_distance"},"CALC_DISTANCE"),(0,r.kt)("p",null,"The ",(0,r.kt)("inlineCode",{parentName:"p"},"CALC_DISTANCE")," function is used to calculate the Euclidean distance between two ",(0,r.kt)("inlineCode",{parentName:"p"},"Point")," type geographical coordinates."),(0,r.kt)("h2",{id:"syntax"},"Syntax"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-sql"},"CALC_DISTANCE(point1, point2)\n")),(0,r.kt)("p",null,(0,r.kt)("strong",{parentName:"p"},"Parameters:")),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"point1"),": The first geographical coordinate of type ",(0,r.kt)("inlineCode",{parentName:"li"},"Point"),"."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"point2"),": The second geographical coordinate of type ",(0,r.kt)("inlineCode",{parentName:"li"},"Point"),".")),(0,r.kt)("h2",{id:"examples"},"Examples"),(0,r.kt)("p",null,"Consider the following table ",(0,r.kt)("inlineCode",{parentName:"p"},"Foo"),":"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-sql"},"CREATE TABLE Foo (\n geo1 Point,\n geo2 Point,\n bar Float\n);\n")),(0,r.kt)("p",null,"With the following data:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-sql"},"INSERT INTO Foo VALUES (POINT(0.3134, 3.156), POINT(1.415, 3.231), 3);\n")),(0,r.kt)("h3",{id:"example-1-calculate-the-distance-between-two-points"},"Example 1: Calculate the distance between two points"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-sql"},"SELECT CALC_DISTANCE(geo1, geo2) AS georesult FROM Foo;\n")),(0,r.kt)("p",null,(0,r.kt)("strong",{parentName:"p"},"Result:")),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"georesult"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"1.104150152832485")))),(0,r.kt)("h2",{id:"errors"},"Errors"),(0,r.kt)("ol",null,(0,r.kt)("li",{parentName:"ol"},"If the number of arguments is not 2, a ",(0,r.kt)("inlineCode",{parentName:"li"},"FunctionArgsLengthNotMatching")," error will be thrown."),(0,r.kt)("li",{parentName:"ol"},"If any of the arguments are not of type ",(0,r.kt)("inlineCode",{parentName:"li"},"Point"),", a ",(0,r.kt)("inlineCode",{parentName:"li"},"FunctionRequiresPointValue")," error will be thrown."),(0,r.kt)("li",{parentName:"ol"},"If any of the arguments are ",(0,r.kt)("inlineCode",{parentName:"li"},"NULL"),", the result will be ",(0,r.kt)("inlineCode",{parentName:"li"},"NULL"),".")))}d.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/dev/assets/js/aff456d7.dbcb844c.js b/docs/dev/assets/js/aff456d7.dbcb844c.js new file mode 100644 index 00000000..541620ad --- /dev/null +++ b/docs/dev/assets/js/aff456d7.dbcb844c.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs=self.webpackChunkdocs||[]).push([[1849],{3905:(e,t,n)=>{n.d(t,{Zo:()=>p,kt:()=>f});var a=n(7294);function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function o(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function l(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?o(Object(n),!0).forEach((function(t){r(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):o(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function i(e,t){if(null==e)return{};var n,a,r=function(e,t){if(null==e)return{};var n,a,r={},o=Object.keys(e);for(a=0;a<o.length;a++)n=o[a],t.indexOf(n)>=0||(r[n]=e[n]);return r}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(a=0;a<o.length;a++)n=o[a],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(r[n]=e[n])}return r}var c=a.createContext({}),s=function(e){var t=a.useContext(c),n=t;return e&&(n="function"==typeof e?e(t):l(l({},t),e)),n},p=function(e){var t=s(e.components);return a.createElement(c.Provider,{value:t},e.children)},u="mdxType",d={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},m=a.forwardRef((function(e,t){var n=e.components,r=e.mdxType,o=e.originalType,c=e.parentName,p=i(e,["components","mdxType","originalType","parentName"]),u=s(n),m=r,f=u["".concat(c,".").concat(m)]||u[m]||d[m]||o;return n?a.createElement(f,l(l({ref:t},p),{},{components:n})):a.createElement(f,l({ref:t},p))}));function f(e,t){var n=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var o=n.length,l=new Array(o);l[0]=m;var i={};for(var c in t)hasOwnProperty.call(t,c)&&(i[c]=t[c]);i.originalType=e,i[u]="string"==typeof e?e:r,l[1]=i;for(var s=2;s<o;s++)l[s]=n[s];return a.createElement.apply(null,l)}return a.createElement.apply(null,n)}m.displayName="MDXCreateElement"},8814:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>l,default:()=>d,frontMatter:()=>o,metadata:()=>i,toc:()=>s});var a=n(7462),r=(n(7294),n(3905));const o={},l="CALC_DISTANCE",i={unversionedId:"sql-syntax/functions/geometry/calc-distance",id:"sql-syntax/functions/geometry/calc-distance",title:"CALC_DISTANCE",description:"The CALC_DISTANCE function is used to calculate the Euclidean distance between two Point type geographical coordinates.",source:"@site/docs/sql-syntax/functions/geometry/calc-distance.md",sourceDirName:"sql-syntax/functions/geometry",slug:"/sql-syntax/functions/geometry/calc-distance",permalink:"/docs/dev/sql-syntax/functions/geometry/calc-distance",draft:!1,tags:[],version:"current",frontMatter:{},sidebar:"autoSidebar",previous:{title:'SQL Function - "SPLICE"',permalink:"/docs/dev/sql-syntax/functions/list-map/splice"},next:{title:"GET_X",permalink:"/docs/dev/sql-syntax/functions/geometry/get-x"}},c={},s=[{value:"Syntax",id:"syntax",level:2},{value:"Examples",id:"examples",level:2},{value:"Example 1: Calculate the distance between two points",id:"example-1-calculate-the-distance-between-two-points",level:3},{value:"Errors",id:"errors",level:2}],p={toc:s},u="wrapper";function d(e){let{components:t,...n}=e;return(0,r.kt)(u,(0,a.Z)({},p,n,{components:t,mdxType:"MDXLayout"}),(0,r.kt)("h1",{id:"calc_distance"},"CALC_DISTANCE"),(0,r.kt)("p",null,"The ",(0,r.kt)("inlineCode",{parentName:"p"},"CALC_DISTANCE")," function is used to calculate the Euclidean distance between two ",(0,r.kt)("inlineCode",{parentName:"p"},"Point")," type geographical coordinates."),(0,r.kt)("h2",{id:"syntax"},"Syntax"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-sql"},"CALC_DISTANCE(point1, point2)\n")),(0,r.kt)("p",null,(0,r.kt)("strong",{parentName:"p"},"Parameters:")),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"point1"),": The first geographical coordinate of type ",(0,r.kt)("inlineCode",{parentName:"li"},"Point"),"."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"point2"),": The second geographical coordinate of type ",(0,r.kt)("inlineCode",{parentName:"li"},"Point"),".")),(0,r.kt)("h2",{id:"examples"},"Examples"),(0,r.kt)("p",null,"Consider the following table ",(0,r.kt)("inlineCode",{parentName:"p"},"Foo"),":"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-sql"},"CREATE TABLE Foo (\n geo1 Point,\n geo2 Point,\n bar Float\n);\n")),(0,r.kt)("p",null,"With the following data:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-sql"},"INSERT INTO Foo VALUES (POINT(0.3134, 3.156), POINT(1.415, 3.231), 3);\n")),(0,r.kt)("h3",{id:"example-1-calculate-the-distance-between-two-points"},"Example 1: Calculate the distance between two points"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-sql"},"SELECT CALC_DISTANCE(geo1, geo2) AS georesult FROM Foo;\n")),(0,r.kt)("p",null,(0,r.kt)("strong",{parentName:"p"},"Result:")),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"georesult"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"1.104150152832485")))),(0,r.kt)("h2",{id:"errors"},"Errors"),(0,r.kt)("ol",null,(0,r.kt)("li",{parentName:"ol"},"If the number of arguments is not 2, a ",(0,r.kt)("inlineCode",{parentName:"li"},"FunctionArgsLengthNotMatching")," error will be thrown."),(0,r.kt)("li",{parentName:"ol"},"If any of the arguments are not of type ",(0,r.kt)("inlineCode",{parentName:"li"},"Point"),", a ",(0,r.kt)("inlineCode",{parentName:"li"},"FunctionRequiresPointValue")," error will be thrown."),(0,r.kt)("li",{parentName:"ol"},"If any of the arguments are ",(0,r.kt)("inlineCode",{parentName:"li"},"NULL"),", the result will be ",(0,r.kt)("inlineCode",{parentName:"li"},"NULL"),".")))}d.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/dev/assets/js/main.6ac6dfb4.js b/docs/dev/assets/js/main.6ac6dfb4.js new file mode 100644 index 00000000..9c819636 --- /dev/null +++ b/docs/dev/assets/js/main.6ac6dfb4.js @@ -0,0 +1,2 @@ +/*! For license information please see main.6ac6dfb4.js.LICENSE.txt */ +(self.webpackChunkdocs=self.webpackChunkdocs||[]).push([[179],{723:(e,t,n)=>{"use strict";n.d(t,{Z:()=>p});var a=n(7294),r=n(7462),o=n(8356),s=n.n(o),i=n(6887);const l={"007e0817":[()=>n.e(9063).then(n.bind(n,3212)),"@site/docs/sql-syntax/functions/text/ltrim.md",3212],"017e736e":[()=>n.e(6685).then(n.bind(n,8301)),"@site/docs/ast-builder/statements/querying/creating-derived-subqueries.md",8301],"01a12966":[()=>n.e(1965).then(n.bind(n,5498)),"@site/docs/getting-started/nodejs.md",5498],"01a85c17":[()=>Promise.all([n.e(532),n.e(4013)]).then(n.bind(n,1223)),"@theme/BlogTagsListPage",1223],"02aa4531":[()=>n.e(5667).then(n.bind(n,2327)),"@site/docs/ast-builder/functions/math/conversion.md",2327],"02bfc02d":[()=>n.e(846).then(n.bind(n,488)),"@site/docs/ast-builder/functions/text/trimming.md",488],"037683de":[()=>n.e(7677).then(n.bind(n,1330)),"@site/docs/ast-builder/statements/data-manipulation/updating-data.md",1330],"0544f90b":[()=>n.e(9600).then(n.bind(n,8435)),"@site/docs/sql-syntax/statements/data-definition/create-index.md",8435],"06322d53":[()=>n.e(1279).then(n.bind(n,9837)),"@site/docs/sql-syntax/functions/text/initcap.md",9837],"07294b24":[()=>n.e(3726).then(n.bind(n,7785)),"@site/docs/ast-builder/functions/text/padding.md",7785],"078a6308":[()=>n.e(3554).then(n.bind(n,7765)),"@site/docs/ast-builder/functions/others/null-handling.md",7765],"0b621d16":[()=>n.e(7462).then(n.bind(n,3701)),"@site/docs/sql-syntax/data-types/decimal.md",3701],"0c18287f":[()=>n.e(3475).then(n.bind(n,194)),"@site/docs/sql-syntax/functions/list-map/append.md",194],"0c94c658":[()=>n.e(3454).then(n.bind(n,141)),"@site/docs/sql-syntax/statements/data-definition/alter-table.md",141],"0ccdbf16":[()=>n.e(5315).then(n.t.bind(n,2853,19)),"~blog/default/docs-dev-blog-tags-nosql-50f-list.json",2853],"0ea64360":[()=>n.e(3372).then(n.bind(n,9767)),"@site/docs/sql-syntax/functions/others/generate-uuid.md",9767],"153137de":[()=>n.e(6199).then(n.t.bind(n,3163,19)),"~blog/default/docs-dev-blog-tags-tdd-09c.json",3163],"15868c40":[()=>n.e(689).then(n.bind(n,8337)),"@site/docs/sql-syntax/functions/text/position.md",8337],"160faf1d":[()=>n.e(2365).then(n.bind(n,2629)),"@site/docs/sql-syntax/functions/math/radians.md",2629],"16815c2a":[()=>n.e(3371).then(n.bind(n,1118)),"@site/docs/ast-builder/statements/querying/data-sorting-and-limiting.md",1118],17896441:[()=>Promise.all([n.e(532),n.e(9785),n.e(7918)]).then(n.bind(n,8945)),"@theme/DocItem",8945],"1798d0b3":[()=>n.e(4046).then(n.bind(n,4872)),"@site/docs/sql-syntax/data-types/bytea.md",4872],"194e858c":[()=>n.e(2305).then(n.bind(n,2507)),"@site/docs/storages/developing-custom-storages/store-traits/alter-table.md",2507],"1a3daba8":[()=>n.e(4945).then(n.bind(n,3711)),"@site/docs/sql-syntax/functions/geometry/point.md",3711],"1b8ca8c3":[()=>n.e(9147).then(n.bind(n,6781)),"@site/docs/sql-syntax/functions/math/floor.md",6781],"1be78505":[()=>Promise.all([n.e(532),n.e(9514)]).then(n.bind(n,9963)),"@theme/DocPage",9963],"1c41eae2":[()=>n.e(4450).then(n.t.bind(n,4469,19)),"/home/runner/work/gluesql/gluesql/docs/.docusaurus/docusaurus-plugin-content-blog/default/plugin-route-context-module-100.json",4469],"1c93e70c":[()=>n.e(8506).then(n.bind(n,5429)),"@site/docs/getting-started/cli.md",5429],"1cdac986":[()=>n.e(2215).then(n.bind(n,5878)),"@site/docs/ast-builder/functions/text/text-manipulation.md",5878],"1ce64703":[()=>n.e(3337).then(n.bind(n,9782)),"@site/docs/ast-builder/functions/math/rounding.md",9782],"1e4e1fb6":[()=>n.e(4909).then(n.t.bind(n,3769,19)),"/home/runner/work/gluesql/gluesql/docs/.docusaurus/docusaurus-plugin-content-docs/default/plugin-route-context-module-100.json",3769],"20e2ece2":[()=>n.e(4785).then(n.bind(n,3700)),"@site/blog/2023-05-30-revolutionizing-databases-by-unifying-query-interfaces.md?truncated=true",3700],"234733fd":[()=>n.e(3188).then(n.bind(n,2830)),"@site/blog/2023-05-27-release-v0.14.md",2830],"23f93eeb":[()=>n.e(7793).then(n.bind(n,6064)),"@site/blog/2023-05-27-release-v0.14.md?truncated=true",6064],25196878:[()=>n.e(1395).then(n.bind(n,1737)),"@site/blog/2023-05-30-test-driven-documentation.md",1737],"26c0a43c":[()=>n.e(7785).then(n.bind(n,6693)),"@site/docs/ast-builder/functions/others/type-conversion.md",6693],"2a4d41ed":[()=>n.e(4004).then(n.bind(n,3386)),"@site/docs/sql-syntax/functions/geometry/get-y.md",3386],"2b265210":[()=>n.e(8142).then(n.bind(n,389)),"@site/docs/ast-builder/expressions/pattern-matching.md",389],"2bed8b6f":[()=>n.e(127).then(n.t.bind(n,3194,19)),"~blog/default/docs-dev-blog-tags-automation-99a-list.json",3194],"2c0d2b92":[()=>n.e(5944).then(n.bind(n,4557)),"@site/docs/sql-syntax/data-types/list.md",4557],"2d9479c4":[()=>n.e(2809).then(n.bind(n,7885)),"@site/docs/sql-syntax/statements/querying/where.md",7885],"2f7bd5c8":[()=>n.e(3058).then(n.bind(n,104)),"@site/docs/sql-syntax/functions/math/cos.md",104],"31526b20":[()=>n.e(9020).then(n.bind(n,6947)),"@site/docs/sql-syntax/intro.md",6947],"31f1dbb1":[()=>n.e(9903).then(n.t.bind(n,1873,19)),"~blog/default/docs-dev-blog-tags-automation-99a.json",1873],"3245f64b":[()=>n.e(6132).then(n.bind(n,3427)),"@site/docs/sql-syntax/statements/querying/aggregation.md",3427],"345c600d":[()=>n.e(1375).then(n.bind(n,160)),"@site/docs/storages/developing-custom-storages/using-test-suite.md",160],"376759eb":[()=>n.e(16).then(n.bind(n,7484)),"@site/docs/ast-builder/statements/data-manipulation/deleting-data.md",7484],"385623dc":[()=>n.e(9643).then(n.bind(n,2621)),"@site/docs/sql-syntax/functions/math/rand.md",2621],"38a882bf":[()=>n.e(9667).then(n.t.bind(n,802,19)),"~blog/default/docs-dev-blog-tags-database-f6d-list.json",802],"3961e600":[()=>n.e(2842).then(n.bind(n,9085)),"@site/docs/storages/supported-storages/json-storage.md",9085],"3cfbc8af":[()=>n.e(2691).then(n.bind(n,4207)),"@site/docs/ast-builder/functions/text/character-conversion.md",4207],"402da695":[()=>n.e(5682).then(n.bind(n,1138)),"@site/docs/sql-syntax/statements/data-definition/drop-table.md",1138],40386700:[()=>n.e(9695).then(n.t.bind(n,2918,19)),"~blog/default/docs-dev-blog-tags-gluesql-5e6-list.json",2918],41718851:[()=>n.e(4244).then(n.bind(n,4245)),"@site/docs/sql-syntax/functions/text/trim.md",4245],44954150:[()=>n.e(3357).then(n.bind(n,8055)),"@site/docs/ast-builder/expressions/operator-based.md",8055],"44f79c8d":[()=>n.e(7123).then(n.bind(n,8261)),"@site/docs/storages/developing-custom-storages/store-traits/custom-function-mut.md",8261],"463dc00f":[()=>n.e(4538).then(n.bind(n,5730)),"@site/docs/ast-builder/functions/date-&-time/formatting.md",5730],"482a391c":[()=>n.e(6508).then(n.bind(n,4364)),"@site/docs/storages/developing-custom-storages/store-traits/store.md",4364],"488157d7":[()=>n.e(9162).then(n.bind(n,2138)),"@site/docs/storages/developing-custom-storages/store-traits/transaction.md",2138],"4a9d0f4c":[()=>n.e(7385).then(n.bind(n,2741)),"@site/docs/sql-syntax/functions/math/mod.md",2741],"4aa001c0":[()=>n.e(1003).then(n.bind(n,2308)),"@site/docs/sql-syntax/statements/data-definition/drop-index.md",2308],"4add0c6c":[()=>n.e(9132).then(n.bind(n,5311)),"@site/docs/ast-builder/intro.md",5311],"4be897c9":[()=>n.e(6741).then(n.bind(n,5066)),"@site/docs/ast-builder/statements/querying/data-injection.md",5066],"4d9df5b1":[()=>n.e(4818).then(n.bind(n,8236)),"@site/docs/sql-syntax/functions/list-map/splice.md",8236],"4f675ae9":[()=>n.e(7233).then(n.bind(n,1046)),"@site/docs/sql-syntax/functions/datetime/extract.md",1046],"5058a078":[()=>n.e(4746).then(n.bind(n,1822)),"@site/blog/2023-05-30-test-driven-documentation.md?truncated=true",1822],50818478:[()=>n.e(6094).then(n.bind(n,918)),"@site/docs/sql-syntax/data-types/map.md",918],"5242ac2d":[()=>n.e(3317).then(n.bind(n,4871)),"@site/docs/sql-syntax/functions/math/sqrt.md",4871],"54df49be":[()=>n.e(3575).then(n.t.bind(n,5625,19)),"~blog/default/docs-dev-blog-tags-release-note-9fd.json",5625],"56ccfc32":[()=>n.e(7194).then(n.bind(n,1710)),"@site/docs/sql-syntax/functions/math/ceil.md",1710],"5a8c7729":[()=>n.e(3004).then(n.bind(n,8869)),"@site/docs/sql-syntax/functions/math/abs.md",8869],"5cdfb1f2":[()=>n.e(7486).then(n.bind(n,4094)),"@site/docs/storages/developing-custom-storages/store-traits/index-mut.md",4094],"5df6e7df":[()=>n.e(9978).then(n.bind(n,583)),"@site/docs/ast-builder/expressions/nested.md",583],"5eabd930":[()=>n.e(5558).then(n.bind(n,3398)),"@site/docs/sql-syntax/functions/text/right.md",3398],65722401:[()=>n.e(7513).then(n.t.bind(n,8354,19)),"~blog/default/docs-dev-blog-tags-v-0-14-0b1-list.json",8354],"65f7a26b":[()=>n.e(9760).then(n.t.bind(n,7968,19)),"~blog/default/docs-dev-blog-tags-sql-e5f.json",7968],67002961:[()=>n.e(4875).then(n.t.bind(n,1679,19)),"~blog/default/docs-dev-blog-tags-proposal-ab6-list.json",1679],"67d1434e":[()=>n.e(9502).then(n.bind(n,9e3)),"@site/docs/storages/supported-storages/composite-storage.md",9e3],"6870612e":[()=>n.e(1827).then(n.bind(n,6775)),"@site/docs/sql-syntax/functions/math/sign.md",6775],"6875c492":[()=>Promise.all([n.e(532),n.e(9785),n.e(6048),n.e(8610)]).then(n.bind(n,1714)),"@theme/BlogTagsPostsPage",1714],"68c17ba1":[()=>n.e(2616).then(n.bind(n,1)),"@site/docs/sql-syntax/functions/math/asin.md",1],"6ba4a510":[()=>n.e(7518).then(n.bind(n,4510)),"@site/docs/sql-syntax/functions/math/acos.md",4510],"6c5232c2":[()=>n.e(8599).then(n.bind(n,9242)),"@site/docs/sql-syntax/statements/metadata/data-dictionary.md",9242],"6e772156":[()=>n.e(8253).then(n.bind(n,889)),"@site/docs/storages/supported-storages/memory-storage.md",889],"6ff6e7c9":[()=>n.e(8215).then(n.bind(n,410)),"@site/docs/sql-syntax/data-types/interval.md",410],"72c409f7":[()=>n.e(5458).then(n.bind(n,955)),"@site/docs/getting-started/rust.md",955],"7310a4fe":[()=>n.e(2047).then(n.bind(n,9576)),"@site/docs/sql-syntax/statements/querying/schemaless.md",9576],"7457c448":[()=>n.e(4452).then(n.bind(n,8621)),"@site/docs/sql-syntax/functions/text/rpad.md",8621],"768594c0":[()=>n.e(3944).then(n.t.bind(n,2483,19)),"~blog/default/docs-dev-blog-tags-nosql-50f.json",2483],"772fc39d":[()=>n.e(3851).then(n.bind(n,1777)),"@site/blog/2023-05-30-revolutionizing-databases-by-unifying-query-interfaces.md",1777],"77b9a1ed":[()=>n.e(7062).then(n.t.bind(n,1303,19)),"~blog/default/docs-dev-blog-tags-test-driven-documentation-210-list.json",1303],"77cc432a":[()=>n.e(3159).then(n.bind(n,995)),"@site/docs/sql-syntax/functions/list-map/prepend.md",995],"79c85cd0":[()=>n.e(5962).then(n.t.bind(n,2284,19)),"~blog/default/docs-dev-blog-tags-documentation-32b.json",2284],"7d170ab0":[()=>n.e(1768).then(n.bind(n,7232)),"@site/blog/2023-05-29-breaking-the-boundary.md",7232],"7e0ce508":[()=>n.e(3394).then(n.bind(n,8233)),"@site/docs/sql-syntax/functions/math/round.md",8233],"7ea7f008":[()=>n.e(8905).then(n.bind(n,5338)),"@site/docs/ast-builder/functions/date-&-time/date-and-time-extraction.md",5338],"814f3328":[()=>n.e(2535).then(n.t.bind(n,5641,19)),"~blog/default/blog-post-list-prop-default.json",5641],"81bf07f5":[()=>n.e(3367).then(n.bind(n,227)),"@site/docs/ast-builder/functions/list-&-map/list-and-map-concatenation.md",227],"81cb5929":[()=>n.e(3193).then(n.t.bind(n,8232,19)),"~blog/default/docs-dev-blog-feb.json",8232],"81f6aa2c":[()=>n.e(5756).then(n.bind(n,2750)),"@site/docs/sql-syntax/functions/text/lower.md",2750],"83b912d4":[()=>n.e(7449).then(n.bind(n,6153)),"@site/docs/storages/developing-custom-storages/store-traits/custom-function.md",6153],"8417e7a5":[()=>n.e(3768).then(n.bind(n,9950)),"@site/blog/2023-05-29-breaking-the-boundary.md?truncated=true",9950],"85afcbde":[()=>n.e(3390).then(n.bind(n,8475)),"@site/docs/sql-syntax/functions/math/tan.md",8475],"86a1f821":[()=>n.e(9992).then(n.bind(n,603)),"@site/docs/sql-syntax/statements/data-definition/create-table.md",603],"89196f72":[()=>n.e(7219).then(n.bind(n,9571)),"@site/docs/ast-builder/functions/math/special-mathematical.md",9571],"89739c9f":[()=>n.e(6350).then(n.t.bind(n,4943,19)),"~blog/default/docs-dev-blog-tags-tags-74b.json",4943],"89fc5f00":[()=>n.e(2627).then(n.bind(n,6897)),"@site/docs/ast-builder/functions/geometry/distance-calculation.md",6897],"8be9dc67":[()=>n.e(3905).then(n.bind(n,6323)),"@site/docs/sql-syntax/statements/data-manipulation/update.md",6323],"8c7569e5":[()=>n.e(5737).then(n.bind(n,8878)),"@site/docs/ast-builder/functions/date-&-time/current-date-and-time.md",8878],"8cf2dd9c":[()=>n.e(9722).then(n.bind(n,6571)),"@site/docs/sql-syntax/functions/text/chr.md",6571],"8d6e802b":[()=>n.e(5843).then(n.bind(n,7407)),"@site/docs/storages/supported-storages/sled-storage.md",7407],"9017a27d":[()=>n.e(1354).then(n.t.bind(n,9252,19)),"~blog/default/docs-dev-blog-tags-v-0-14-0b1.json",9252],"920bdc78":[()=>n.e(6669).then(n.bind(n,6014)),"@site/docs/sql-syntax/functions/math/div.md",6014],"928a5d6f":[()=>n.e(6489).then(n.bind(n,174)),"@site/docs/sql-syntax/functions/datetime/to-date.md",174],"92dd0956":[()=>n.e(104).then(n.bind(n,5729)),"@site/docs/sql-syntax/statements/data-manipulation/delete.md",5729],"935f2afb":[()=>n.e(53).then(n.t.bind(n,1109,19)),"~docs/default/version-current-metadata-prop-751.json",1109],"93e7cfc5":[()=>n.e(3704).then(n.t.bind(n,6428,19)),"~blog/default/docs-dev-blog-tags-documentation-32b-list.json",6428],"952dfacb":[()=>n.e(6155).then(n.bind(n,9783)),"@site/docs/storages/supported-storages/idb-storage.md",9783],"9624c11c":[()=>n.e(203).then(n.t.bind(n,5350,19)),"~blog/default/docs-dev-blog-tags-chat-gpt-3f4.json",5350],"97081ee7":[()=>n.e(3619).then(n.bind(n,4555)),"@site/docs/sql-syntax/functions/text/lpad.md",4555],"980f8d5e":[()=>n.e(7344).then(n.bind(n,4732)),"@site/docs/ast-builder/functions/math/logarithmic-and-exponential.md",4732],"98306a23":[()=>n.e(5123).then(n.bind(n,74)),"@site/docs/sql-syntax/functions/datetime/now.md",74],"9a1c8bc6":[()=>n.e(7669).then(n.bind(n,5401)),"@site/docs/sql-syntax/functions/math/sin.md",5401],"9a3e57da":[()=>n.e(8894).then(n.bind(n,3717)),"@site/docs/sql-syntax/functions/geometry/get-x.md",3717],"9bbfd40a":[()=>n.e(1788).then(n.t.bind(n,350,19)),"~blog/default/docs-dev-blog-tags-database-f6d.json",350],"9c5158ac":[()=>n.e(1470).then(n.bind(n,7984)),"@site/docs/ast-builder/functions/math/basic-arithmetic.md",7984],"9d02ad31":[()=>n.e(6017).then(n.t.bind(n,5288,19)),"~blog/default/docs-dev-blog-tags-query-interface-47d.json",5288],"9e4087bc":[()=>n.e(3608).then(n.bind(n,3169)),"@theme/BlogArchivePage",3169],a2ab2bad:[()=>n.e(1715).then(n.bind(n,420)),"@site/docs/ast-builder/functions/list-&-map/list-manipulation.md",420],a470b55c:[()=>n.e(6989).then(n.bind(n,2451)),"@site/docs/sql-syntax/functions/text/concat.md",2451],a4bc1622:[()=>n.e(1983).then(n.bind(n,4392)),"@site/docs/ast-builder/expressions/conditional.md",4392],a5971d1a:[()=>n.e(156).then(n.bind(n,4394)),"@site/docs/sql-syntax/data-types/date.md",4394],a6177d3d:[()=>n.e(9818).then(n.t.bind(n,5837,19)),"~blog/default/docs-dev-blog-tags-query-interface-47d-list.json",5837],a6aa9e1f:[()=>Promise.all([n.e(532),n.e(9785),n.e(6048),n.e(3089)]).then(n.bind(n,46)),"@theme/BlogListPage",46],a6b6486c:[()=>n.e(7839).then(n.bind(n,8954)),"@site/docs/ast-builder/functions/geometry/point-creation.md",8954],a7153b78:[()=>n.e(950).then(n.bind(n,3568)),"@site/docs/sql-syntax/functions/datetime/to-time.md",3568],a7e6874c:[()=>n.e(340).then(n.bind(n,3672)),"@site/docs/sql-syntax/functions/math/power.md",3672],a8d11699:[()=>n.e(5391).then(n.bind(n,9291)),"@site/docs/sql-syntax/data-types/timestamp.md",9291],a9e26133:[()=>n.e(2177).then(n.bind(n,119)),"@site/docs/sql-syntax/data-types/inet.md",119],aa1cf9a2:[()=>n.e(9986).then(n.bind(n,4596)),"@site/docs/sql-syntax/data-types/integers.md",4596],acfabe81:[()=>n.e(998).then(n.bind(n,6712)),"@site/docs/ast-builder/functions/date-&-time/conversion.md",6712],ae3eef3e:[()=>n.e(6212).then(n.bind(n,8173)),"@site/docs/sql-syntax/functions/math/ln.md",8173],ae967838:[()=>n.e(4561).then(n.bind(n,4712)),"@site/docs/sql-syntax/functions/text/reverse.md",4712],afebe5f1:[()=>n.e(636).then(n.bind(n,5353)),"@site/docs/sql-syntax/functions/math/log10.md",5353],aff456d7:[()=>n.e(1849).then(n.bind(n,8814)),"@site/docs/sql-syntax/functions/geometry/calc-distance.md",8814],b1f622a1:[()=>n.e(1452).then(n.t.bind(n,7731,19)),"~blog/default/docs-dev-blog-archive-c7c.json",7731],b209ab8a:[()=>n.e(5906).then(n.bind(n,8633)),"@site/docs/storages/intro.md",8633],b3de9677:[()=>n.e(6555).then(n.bind(n,8826)),"@site/docs/ast-builder/statements/querying/data-aggregation.md",8826],b57ca7d5:[()=>n.e(5297).then(n.bind(n,6093)),"@site/docs/sql-syntax/functions/text/repeat.md",6093],b6bceaff:[()=>n.e(3587).then(n.bind(n,6414)),"@site/docs/ast-builder/expressions/value-checking.md",6414],b7661aba:[()=>n.e(9054).then(n.bind(n,5512)),"@site/docs/sql-syntax/functions/text/upper.md",5512],b7da1136:[()=>n.e(3216).then(n.bind(n,9665)),"@site/docs/sql-syntax/statements/querying/limit.md",9665],ba43b2d5:[()=>n.e(7496).then(n.bind(n,3557)),"@site/docs/sql-syntax/functions/math/atan.md",3557],bac2c42d:[()=>n.e(1610).then(n.bind(n,2163)),"@site/docs/ast-builder/statements/data-manipulation/inserting-data.md",2163],bb43b8ce:[()=>n.e(7870).then(n.bind(n,7846)),"@site/docs/sql-syntax/functions/others/cast.md",7846],bfb64759:[()=>n.e(5401).then(n.bind(n,2576)),"@site/docs/sql-syntax/data-types/uuid.md",2576],c251e734:[()=>n.e(5952).then(n.bind(n,5423)),"@site/docs/storages/developing-custom-storages/intro.md",5423],c2e5ab4f:[()=>n.e(3151).then(n.bind(n,2906)),"@site/docs/sql-syntax/functions/datetime/to-timestamp.md",2906],c30ee527:[()=>n.e(9661).then(n.bind(n,3140)),"@site/docs/sql-syntax/statements/metadata/show-tables.md",3140],c377a04b:[()=>n.e(6971).then(n.bind(n,1269)),"@site/docs/index.md",1269],c5b25a7c:[()=>n.e(9266).then(n.bind(n,9027)),"@site/docs/sql-syntax/functions/text/concat-ws.md",9027],c5e834bc:[()=>n.e(9385).then(n.bind(n,6961)),"@site/docs/ast-builder/functions/math/trigonometric.md",6961],c97e0540:[()=>n.e(7332).then(n.bind(n,1745)),"@site/docs/sql-syntax/functions/math/degrees.md",1745],c9d1eb08:[()=>n.e(6448).then(n.bind(n,2218)),"@site/docs/sql-syntax/functions/text/rtrim.md",2218],ccc49370:[()=>Promise.all([n.e(532),n.e(9785),n.e(6048),n.e(6103)]).then(n.bind(n,5203)),"@theme/BlogPostPage",5203],cdaafcc9:[()=>n.e(1500).then(n.bind(n,4570)),"@site/docs/sql-syntax/functions/math/gcd.md",4570],cf518063:[()=>n.e(6979).then(n.bind(n,4077)),"@site/docs/sql-syntax/functions/list-map/concat.md",4077],d077f377:[()=>n.e(1929).then(n.bind(n,4119)),"@site/docs/sql-syntax/data-types/text.md",4119],d4251823:[()=>n.e(4176).then(n.bind(n,692)),"@site/docs/sql-syntax/functions/text/find-idx.md",692],d5aa49f9:[()=>n.e(7901).then(n.bind(n,8991)),"@site/docs/ast-builder/functions/others/unique-identifier.md",8991],d7a493e6:[()=>n.e(3020).then(n.bind(n,3270)),"@site/docs/ast-builder/functions/text/case-conversion.md",3270],d8746e52:[()=>n.e(8697).then(n.bind(n,4524)),"@site/docs/sql-syntax/functions/text/substr.md",4524],d941076d:[()=>n.e(8662).then(n.bind(n,483)),"@site/docs/storages/developing-custom-storages/store-traits/index-trait.md",483],d97b7d4d:[()=>n.e(9586).then(n.bind(n,1078)),"@site/docs/ast-builder/statements/querying/using-preloaded-data.md",1078],daad7c1d:[()=>n.e(2463).then(n.t.bind(n,7641,19)),"~blog/default/docs-dev-blog-tags-gluesql-5e6.json",7641],dafe2799:[()=>n.e(9616).then(n.bind(n,4674)),"@site/docs/sql-syntax/functions/text/left.md",4674],db0d9cb2:[()=>n.e(777).then(n.bind(n,6377)),"@site/docs/sql-syntax/functions/math/log.md",6377],db5d1fe1:[()=>n.e(6044).then(n.t.bind(n,2938,19)),"~blog/default/docs-dev-blog-tags-chat-gpt-3f4-list.json",2938],dc5cc32c:[()=>n.e(6186).then(n.t.bind(n,6354,19)),"~blog/default/docs-dev-blog-tags-tdd-09c-list.json",6354],dc8f2f6c:[()=>n.e(1164).then(n.bind(n,5008)),"@site/docs/sql-syntax/statements/querying/join.md",5008],df2eb7da:[()=>n.e(6694).then(n.bind(n,1443)),"@site/docs/sql-syntax/statements/data-manipulation/insert.md",1443],e06425d1:[()=>n.e(221).then(n.bind(n,7661)),"@site/docs/sql-syntax/functions/text/ascii.md",7661],e10f7c24:[()=>n.e(4213).then(n.bind(n,8438)),"@site/docs/getting-started/javascript-web.md",8438],e158c27a:[()=>n.e(5589).then(n.bind(n,652)),"@site/docs/sql-syntax/statements/transaction.md",652],e329d2fa:[()=>n.e(4792).then(n.bind(n,4908)),"@site/docs/storages/developing-custom-storages/store-traits/metadata.md",4908],e46b95eb:[()=>n.e(5085).then(n.bind(n,3564)),"@site/docs/storages/supported-storages/shared-memory-storage.md",3564],e4f709d1:[()=>n.e(6533).then(n.bind(n,5094)),"@site/docs/sql-syntax/functions/math/lcm.md",5094],e519b4b4:[()=>n.e(9101).then(n.t.bind(n,5588,19)),"~blog/default/docs-dev-blog-tags-proposal-ab6.json",5588],e5f53749:[()=>n.e(930).then(n.bind(n,8967)),"@site/docs/ast-builder/statements/querying/data-joining.md",8967],e68f8ad6:[()=>n.e(2988).then(n.bind(n,2149)),"@site/docs/sql-syntax/data-types/boolean.md",2149],ebe12d94:[()=>n.e(5889).then(n.bind(n,4980)),"@site/docs/storages/developing-custom-storages/store-traits/store-mut.md",4980],ebfca923:[()=>n.e(4637).then(n.t.bind(n,6893,19)),"~blog/default/docs-dev-blog-tags-sql-e5f-list.json",6893],eceb3b9b:[()=>n.e(8851).then(n.bind(n,8338)),"@site/docs/sql-syntax/functions/math/pi.md",8338],edb9b0b8:[()=>n.e(560).then(n.bind(n,5555)),"@site/docs/storages/supported-storages/web-storage.md",5555],ee244d12:[()=>n.e(1530).then(n.bind(n,1895)),"@site/docs/ast-builder/statements/querying/fetching-data-from-storage.md",1895],ee6dd1d2:[()=>n.e(4734).then(n.t.bind(n,4513,19)),"~blog/default/docs-dev-blog-tags-release-note-9fd-list.json",4513],f1257df2:[()=>n.e(7257).then(n.bind(n,6607)),"@site/docs/sql-syntax/functions/math/log2.md",6607],f18bbaf6:[()=>n.e(811).then(n.bind(n,1994)),"@site/docs/sql-syntax/functions/datetime/format.md",1994],f33f2c05:[()=>n.e(6470).then(n.bind(n,9276)),"@site/docs/sql-syntax/data-types/float.md",9276],f6ca3de5:[()=>n.e(4706).then(n.bind(n,4065)),"@site/docs/ast-builder/functions/geometry/coordinate-extraction.md",4065],f81fb924:[()=>n.e(438).then(n.t.bind(n,665,19)),"~blog/default/docs-dev-blog-tags-test-driven-documentation-210.json",665],f914cfe8:[()=>n.e(2690).then(n.bind(n,5756)),"@site/docs/ast-builder/statements/querying/data-selection-and-projection.md",5756],f9553497:[()=>n.e(4033).then(n.bind(n,4176)),"@site/docs/ast-builder/functions/text/position-and-indexing.md",4176],fa5466f2:[()=>n.e(314).then(n.bind(n,9192)),"@site/docs/sql-syntax/functions/others/ifnull.md",9192],faca410e:[()=>n.e(6811).then(n.bind(n,5870)),"@site/docs/sql-syntax/functions/math/exp.md",5870],ff7b8d8e:[()=>n.e(3344).then(n.bind(n,1922)),"@site/docs/sql-syntax/data-types/time.md",1922]};function c(e){let{error:t,retry:n,pastDelay:r}=e;return t?a.createElement("div",{style:{textAlign:"center",color:"#fff",backgroundColor:"#fa383e",borderColor:"#fa383e",borderStyle:"solid",borderRadius:"0.25rem",borderWidth:"1px",boxSizing:"border-box",display:"block",padding:"1rem",flex:"0 0 50%",marginLeft:"25%",marginRight:"25%",marginTop:"5rem",maxWidth:"50%",width:"100%"}},a.createElement("p",null,String(t)),a.createElement("div",null,a.createElement("button",{type:"button",onClick:n},"Retry"))):r?a.createElement("div",{style:{display:"flex",justifyContent:"center",alignItems:"center",height:"100vh"}},a.createElement("svg",{id:"loader",style:{width:128,height:110,position:"absolute",top:"calc(100vh - 64%)"},viewBox:"0 0 45 45",xmlns:"http://www.w3.org/2000/svg",stroke:"#61dafb"},a.createElement("g",{fill:"none",fillRule:"evenodd",transform:"translate(1 1)",strokeWidth:"2"},a.createElement("circle",{cx:"22",cy:"22",r:"6",strokeOpacity:"0"},a.createElement("animate",{attributeName:"r",begin:"1.5s",dur:"3s",values:"6;22",calcMode:"linear",repeatCount:"indefinite"}),a.createElement("animate",{attributeName:"stroke-opacity",begin:"1.5s",dur:"3s",values:"1;0",calcMode:"linear",repeatCount:"indefinite"}),a.createElement("animate",{attributeName:"stroke-width",begin:"1.5s",dur:"3s",values:"2;0",calcMode:"linear",repeatCount:"indefinite"})),a.createElement("circle",{cx:"22",cy:"22",r:"6",strokeOpacity:"0"},a.createElement("animate",{attributeName:"r",begin:"3s",dur:"3s",values:"6;22",calcMode:"linear",repeatCount:"indefinite"}),a.createElement("animate",{attributeName:"stroke-opacity",begin:"3s",dur:"3s",values:"1;0",calcMode:"linear",repeatCount:"indefinite"}),a.createElement("animate",{attributeName:"stroke-width",begin:"3s",dur:"3s",values:"2;0",calcMode:"linear",repeatCount:"indefinite"})),a.createElement("circle",{cx:"22",cy:"22",r:"8"},a.createElement("animate",{attributeName:"r",begin:"0s",dur:"1.5s",values:"6;1;2;3;4;5;6",calcMode:"linear",repeatCount:"indefinite"}))))):null}var u=n(9670),d=n(226);function f(e,t){if("*"===e)return s()({loading:c,loader:()=>n.e(4972).then(n.bind(n,4972)),modules:["@theme/NotFound"],webpack:()=>[4972],render(e,t){const n=e.default;return a.createElement(d.z,{value:{plugin:{name:"native",id:"default"}}},a.createElement(n,t))}});const o=i[`${e}-${t}`],f={},p=[],m=[],g=(0,u.Z)(o);return Object.entries(g).forEach((e=>{let[t,n]=e;const a=l[n];a&&(f[t]=a[0],p.push(a[1]),m.push(a[2]))})),s().Map({loading:c,loader:f,modules:p,webpack:()=>m,render(t,n){const s=JSON.parse(JSON.stringify(o));Object.entries(t).forEach((t=>{let[n,a]=t;const r=a.default;if(!r)throw new Error(`The page component at ${e} doesn't have a default export. This makes it impossible to render anything. Consider default-exporting a React component.`);"object"!=typeof r&&"function"!=typeof r||Object.keys(a).filter((e=>"default"!==e)).forEach((e=>{r[e]=a[e]}));let o=s;const i=n.split(".");i.slice(0,-1).forEach((e=>{o=o[e]})),o[i[i.length-1]]=r}));const i=s.__comp;delete s.__comp;const l=s.__context;return delete s.__context,a.createElement(d.z,{value:l},a.createElement(i,(0,r.Z)({},s,n)))}})}const p=[{path:"/docs/dev/blog",component:f("/docs/dev/blog","9f6"),exact:!0},{path:"/docs/dev/blog/archive",component:f("/docs/dev/blog/archive","f0a"),exact:!0},{path:"/docs/dev/blog/breaking-the-boundary-between-sql-and-nosql",component:f("/docs/dev/blog/breaking-the-boundary-between-sql-and-nosql","150"),exact:!0},{path:"/docs/dev/blog/release-v0.14",component:f("/docs/dev/blog/release-v0.14","d1b"),exact:!0},{path:"/docs/dev/blog/revolutionizing-databases-by-unifying-query-interfaces",component:f("/docs/dev/blog/revolutionizing-databases-by-unifying-query-interfaces","c88"),exact:!0},{path:"/docs/dev/blog/tags",component:f("/docs/dev/blog/tags","946"),exact:!0},{path:"/docs/dev/blog/tags/automation",component:f("/docs/dev/blog/tags/automation","7a5"),exact:!0},{path:"/docs/dev/blog/tags/chat-gpt",component:f("/docs/dev/blog/tags/chat-gpt","65d"),exact:!0},{path:"/docs/dev/blog/tags/database",component:f("/docs/dev/blog/tags/database","53f"),exact:!0},{path:"/docs/dev/blog/tags/documentation",component:f("/docs/dev/blog/tags/documentation","7d2"),exact:!0},{path:"/docs/dev/blog/tags/gluesql",component:f("/docs/dev/blog/tags/gluesql","22b"),exact:!0},{path:"/docs/dev/blog/tags/nosql",component:f("/docs/dev/blog/tags/nosql","582"),exact:!0},{path:"/docs/dev/blog/tags/proposal",component:f("/docs/dev/blog/tags/proposal","5c5"),exact:!0},{path:"/docs/dev/blog/tags/query-interface",component:f("/docs/dev/blog/tags/query-interface","ee0"),exact:!0},{path:"/docs/dev/blog/tags/release-note",component:f("/docs/dev/blog/tags/release-note","991"),exact:!0},{path:"/docs/dev/blog/tags/sql",component:f("/docs/dev/blog/tags/sql","959"),exact:!0},{path:"/docs/dev/blog/tags/tdd",component:f("/docs/dev/blog/tags/tdd","ff0"),exact:!0},{path:"/docs/dev/blog/tags/test-driven-documentation",component:f("/docs/dev/blog/tags/test-driven-documentation","fcc"),exact:!0},{path:"/docs/dev/blog/tags/v-0-14",component:f("/docs/dev/blog/tags/v-0-14","b4d"),exact:!0},{path:"/docs/dev/blog/test-driven-documentation",component:f("/docs/dev/blog/test-driven-documentation","af8"),exact:!0},{path:"/docs/dev/",component:f("/docs/dev/","d5f"),routes:[{path:"/docs/dev/",component:f("/docs/dev/","666"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/ast-builder/expressions/conditional",component:f("/docs/dev/ast-builder/expressions/conditional","32d"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/ast-builder/expressions/nested",component:f("/docs/dev/ast-builder/expressions/nested","dcd"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/ast-builder/expressions/operator-based",component:f("/docs/dev/ast-builder/expressions/operator-based","172"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/ast-builder/expressions/pattern-matching",component:f("/docs/dev/ast-builder/expressions/pattern-matching","8b6"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/ast-builder/expressions/value-checking",component:f("/docs/dev/ast-builder/expressions/value-checking","c44"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/ast-builder/functions/date-&-time/conversion",component:f("/docs/dev/ast-builder/functions/date-&-time/conversion","bf0"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/ast-builder/functions/date-&-time/current-date-and-time",component:f("/docs/dev/ast-builder/functions/date-&-time/current-date-and-time","16a"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/ast-builder/functions/date-&-time/date-and-time-extraction",component:f("/docs/dev/ast-builder/functions/date-&-time/date-and-time-extraction","273"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/ast-builder/functions/date-&-time/formatting",component:f("/docs/dev/ast-builder/functions/date-&-time/formatting","b9b"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/ast-builder/functions/geometry/coordinate-extraction",component:f("/docs/dev/ast-builder/functions/geometry/coordinate-extraction","5d6"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/ast-builder/functions/geometry/distance-calculation",component:f("/docs/dev/ast-builder/functions/geometry/distance-calculation","900"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/ast-builder/functions/geometry/point-creation",component:f("/docs/dev/ast-builder/functions/geometry/point-creation","1a3"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/ast-builder/functions/list-&-map/list-and-map-concatenation",component:f("/docs/dev/ast-builder/functions/list-&-map/list-and-map-concatenation","35b"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/ast-builder/functions/list-&-map/list-manipulation",component:f("/docs/dev/ast-builder/functions/list-&-map/list-manipulation","2cf"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/ast-builder/functions/math/basic-arithmetic",component:f("/docs/dev/ast-builder/functions/math/basic-arithmetic","f0a"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/ast-builder/functions/math/conversion",component:f("/docs/dev/ast-builder/functions/math/conversion","7c8"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/ast-builder/functions/math/logarithmic-and-exponential",component:f("/docs/dev/ast-builder/functions/math/logarithmic-and-exponential","fb1"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/ast-builder/functions/math/rounding",component:f("/docs/dev/ast-builder/functions/math/rounding","7ca"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/ast-builder/functions/math/special-mathematical",component:f("/docs/dev/ast-builder/functions/math/special-mathematical","3ee"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/ast-builder/functions/math/trigonometric",component:f("/docs/dev/ast-builder/functions/math/trigonometric","29b"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/ast-builder/functions/others/null-handling",component:f("/docs/dev/ast-builder/functions/others/null-handling","948"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/ast-builder/functions/others/type-conversion",component:f("/docs/dev/ast-builder/functions/others/type-conversion","a77"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/ast-builder/functions/others/unique-identifier",component:f("/docs/dev/ast-builder/functions/others/unique-identifier","0a6"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/ast-builder/functions/text/case-conversion",component:f("/docs/dev/ast-builder/functions/text/case-conversion","605"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/ast-builder/functions/text/character-conversion",component:f("/docs/dev/ast-builder/functions/text/character-conversion","919"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/ast-builder/functions/text/padding",component:f("/docs/dev/ast-builder/functions/text/padding","7b6"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/ast-builder/functions/text/position-and-indexing",component:f("/docs/dev/ast-builder/functions/text/position-and-indexing","1ed"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/ast-builder/functions/text/text-manipulation",component:f("/docs/dev/ast-builder/functions/text/text-manipulation","762"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/ast-builder/functions/text/trimming",component:f("/docs/dev/ast-builder/functions/text/trimming","63b"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/ast-builder/intro",component:f("/docs/dev/ast-builder/intro","06b"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/ast-builder/statements/data-manipulation/deleting-data",component:f("/docs/dev/ast-builder/statements/data-manipulation/deleting-data","9f7"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/ast-builder/statements/data-manipulation/inserting-data",component:f("/docs/dev/ast-builder/statements/data-manipulation/inserting-data","83e"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/ast-builder/statements/data-manipulation/updating-data",component:f("/docs/dev/ast-builder/statements/data-manipulation/updating-data","6c8"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/ast-builder/statements/querying/creating-derived-subqueries",component:f("/docs/dev/ast-builder/statements/querying/creating-derived-subqueries","f4d"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/ast-builder/statements/querying/data-aggregation",component:f("/docs/dev/ast-builder/statements/querying/data-aggregation","5f9"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/ast-builder/statements/querying/data-injection",component:f("/docs/dev/ast-builder/statements/querying/data-injection","a84"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/ast-builder/statements/querying/data-joining",component:f("/docs/dev/ast-builder/statements/querying/data-joining","2c0"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/ast-builder/statements/querying/data-selection-and-projection",component:f("/docs/dev/ast-builder/statements/querying/data-selection-and-projection","34f"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/ast-builder/statements/querying/data-sorting-and-limiting",component:f("/docs/dev/ast-builder/statements/querying/data-sorting-and-limiting","234"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/ast-builder/statements/querying/fetching-data-from-storage",component:f("/docs/dev/ast-builder/statements/querying/fetching-data-from-storage","b2e"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/ast-builder/statements/querying/using-preloaded-data",component:f("/docs/dev/ast-builder/statements/querying/using-preloaded-data","35f"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/getting-started/cli",component:f("/docs/dev/getting-started/cli","f3c"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/getting-started/javascript-web",component:f("/docs/dev/getting-started/javascript-web","ae6"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/getting-started/nodejs",component:f("/docs/dev/getting-started/nodejs","37e"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/getting-started/rust",component:f("/docs/dev/getting-started/rust","3fc"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/data-types/boolean",component:f("/docs/dev/sql-syntax/data-types/boolean","c7f"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/data-types/bytea",component:f("/docs/dev/sql-syntax/data-types/bytea","ed8"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/data-types/date",component:f("/docs/dev/sql-syntax/data-types/date","612"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/data-types/decimal",component:f("/docs/dev/sql-syntax/data-types/decimal","3f2"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/data-types/float",component:f("/docs/dev/sql-syntax/data-types/float","f0c"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/data-types/inet",component:f("/docs/dev/sql-syntax/data-types/inet","5c7"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/data-types/integers",component:f("/docs/dev/sql-syntax/data-types/integers","171"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/data-types/interval",component:f("/docs/dev/sql-syntax/data-types/interval","59c"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/data-types/list",component:f("/docs/dev/sql-syntax/data-types/list","0c2"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/data-types/map",component:f("/docs/dev/sql-syntax/data-types/map","744"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/data-types/text",component:f("/docs/dev/sql-syntax/data-types/text","f2f"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/data-types/time",component:f("/docs/dev/sql-syntax/data-types/time","66e"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/data-types/timestamp",component:f("/docs/dev/sql-syntax/data-types/timestamp","546"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/data-types/uuid",component:f("/docs/dev/sql-syntax/data-types/uuid","5fa"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/datetime/extract",component:f("/docs/dev/sql-syntax/functions/datetime/extract","ae9"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/datetime/format",component:f("/docs/dev/sql-syntax/functions/datetime/format","2c8"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/datetime/now",component:f("/docs/dev/sql-syntax/functions/datetime/now","93b"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/datetime/to-date",component:f("/docs/dev/sql-syntax/functions/datetime/to-date","8b3"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/datetime/to-time",component:f("/docs/dev/sql-syntax/functions/datetime/to-time","b6e"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/datetime/to-timestamp",component:f("/docs/dev/sql-syntax/functions/datetime/to-timestamp","52a"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/geometry/calc-distance",component:f("/docs/dev/sql-syntax/functions/geometry/calc-distance","e9f"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/geometry/get-x",component:f("/docs/dev/sql-syntax/functions/geometry/get-x","2ae"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/geometry/get-y",component:f("/docs/dev/sql-syntax/functions/geometry/get-y","54a"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/geometry/point",component:f("/docs/dev/sql-syntax/functions/geometry/point","12a"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/list-map/append",component:f("/docs/dev/sql-syntax/functions/list-map/append","be2"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/list-map/concat",component:f("/docs/dev/sql-syntax/functions/list-map/concat","cc9"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/list-map/prepend",component:f("/docs/dev/sql-syntax/functions/list-map/prepend","7d8"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/list-map/splice",component:f("/docs/dev/sql-syntax/functions/list-map/splice","d4b"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/math/abs",component:f("/docs/dev/sql-syntax/functions/math/abs","b85"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/math/acos",component:f("/docs/dev/sql-syntax/functions/math/acos","ec1"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/math/asin",component:f("/docs/dev/sql-syntax/functions/math/asin","c78"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/math/atan",component:f("/docs/dev/sql-syntax/functions/math/atan","ad0"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/math/ceil",component:f("/docs/dev/sql-syntax/functions/math/ceil","0d5"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/math/cos",component:f("/docs/dev/sql-syntax/functions/math/cos","8ae"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/math/degrees",component:f("/docs/dev/sql-syntax/functions/math/degrees","e0e"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/math/div",component:f("/docs/dev/sql-syntax/functions/math/div","048"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/math/exp",component:f("/docs/dev/sql-syntax/functions/math/exp","a31"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/math/floor",component:f("/docs/dev/sql-syntax/functions/math/floor","03a"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/math/gcd",component:f("/docs/dev/sql-syntax/functions/math/gcd","f38"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/math/lcm",component:f("/docs/dev/sql-syntax/functions/math/lcm","1c7"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/math/ln",component:f("/docs/dev/sql-syntax/functions/math/ln","700"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/math/log",component:f("/docs/dev/sql-syntax/functions/math/log","4e6"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/math/log10",component:f("/docs/dev/sql-syntax/functions/math/log10","09d"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/math/log2",component:f("/docs/dev/sql-syntax/functions/math/log2","204"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/math/mod",component:f("/docs/dev/sql-syntax/functions/math/mod","1fe"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/math/pi",component:f("/docs/dev/sql-syntax/functions/math/pi","4b0"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/math/power",component:f("/docs/dev/sql-syntax/functions/math/power","a7d"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/math/radians",component:f("/docs/dev/sql-syntax/functions/math/radians","09d"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/math/rand",component:f("/docs/dev/sql-syntax/functions/math/rand","5c1"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/math/round",component:f("/docs/dev/sql-syntax/functions/math/round","73f"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/math/sign",component:f("/docs/dev/sql-syntax/functions/math/sign","da7"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/math/sin",component:f("/docs/dev/sql-syntax/functions/math/sin","98d"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/math/sqrt",component:f("/docs/dev/sql-syntax/functions/math/sqrt","d79"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/math/tan",component:f("/docs/dev/sql-syntax/functions/math/tan","a32"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/others/cast",component:f("/docs/dev/sql-syntax/functions/others/cast","5c2"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/others/generate-uuid",component:f("/docs/dev/sql-syntax/functions/others/generate-uuid","7ff"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/others/ifnull",component:f("/docs/dev/sql-syntax/functions/others/ifnull","bfe"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/text/ascii",component:f("/docs/dev/sql-syntax/functions/text/ascii","6f0"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/text/chr",component:f("/docs/dev/sql-syntax/functions/text/chr","791"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/text/concat",component:f("/docs/dev/sql-syntax/functions/text/concat","2d3"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/text/concat-ws",component:f("/docs/dev/sql-syntax/functions/text/concat-ws","7cc"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/text/find-idx",component:f("/docs/dev/sql-syntax/functions/text/find-idx","e63"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/text/initcap",component:f("/docs/dev/sql-syntax/functions/text/initcap","d0b"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/text/left",component:f("/docs/dev/sql-syntax/functions/text/left","6d7"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/text/lower",component:f("/docs/dev/sql-syntax/functions/text/lower","913"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/text/lpad",component:f("/docs/dev/sql-syntax/functions/text/lpad","832"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/text/ltrim",component:f("/docs/dev/sql-syntax/functions/text/ltrim","076"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/text/position",component:f("/docs/dev/sql-syntax/functions/text/position","184"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/text/repeat",component:f("/docs/dev/sql-syntax/functions/text/repeat","6c9"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/text/reverse",component:f("/docs/dev/sql-syntax/functions/text/reverse","007"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/text/right",component:f("/docs/dev/sql-syntax/functions/text/right","f07"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/text/rpad",component:f("/docs/dev/sql-syntax/functions/text/rpad","93e"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/text/rtrim",component:f("/docs/dev/sql-syntax/functions/text/rtrim","e76"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/text/substr",component:f("/docs/dev/sql-syntax/functions/text/substr","d8c"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/text/trim",component:f("/docs/dev/sql-syntax/functions/text/trim","ce4"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/text/upper",component:f("/docs/dev/sql-syntax/functions/text/upper","6b6"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/intro",component:f("/docs/dev/sql-syntax/intro","d94"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/statements/data-definition/alter-table",component:f("/docs/dev/sql-syntax/statements/data-definition/alter-table","259"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/statements/data-definition/create-index",component:f("/docs/dev/sql-syntax/statements/data-definition/create-index","ba4"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/statements/data-definition/create-table",component:f("/docs/dev/sql-syntax/statements/data-definition/create-table","9fd"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/statements/data-definition/drop-index",component:f("/docs/dev/sql-syntax/statements/data-definition/drop-index","69c"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/statements/data-definition/drop-table",component:f("/docs/dev/sql-syntax/statements/data-definition/drop-table","f80"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/statements/data-manipulation/delete",component:f("/docs/dev/sql-syntax/statements/data-manipulation/delete","927"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/statements/data-manipulation/insert",component:f("/docs/dev/sql-syntax/statements/data-manipulation/insert","10a"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/statements/data-manipulation/update",component:f("/docs/dev/sql-syntax/statements/data-manipulation/update","967"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/statements/metadata/data-dictionary",component:f("/docs/dev/sql-syntax/statements/metadata/data-dictionary","114"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/statements/metadata/show-tables",component:f("/docs/dev/sql-syntax/statements/metadata/show-tables","1bf"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/statements/querying/aggregation",component:f("/docs/dev/sql-syntax/statements/querying/aggregation","5df"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/statements/querying/join",component:f("/docs/dev/sql-syntax/statements/querying/join","796"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/statements/querying/limit",component:f("/docs/dev/sql-syntax/statements/querying/limit","762"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/statements/querying/schemaless",component:f("/docs/dev/sql-syntax/statements/querying/schemaless","afa"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/statements/querying/where",component:f("/docs/dev/sql-syntax/statements/querying/where","bb5"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/statements/transaction",component:f("/docs/dev/sql-syntax/statements/transaction","411"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/storages/developing-custom-storages/intro",component:f("/docs/dev/storages/developing-custom-storages/intro","c6d"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/storages/developing-custom-storages/store-traits/alter-table",component:f("/docs/dev/storages/developing-custom-storages/store-traits/alter-table","4c5"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/storages/developing-custom-storages/store-traits/custom-function",component:f("/docs/dev/storages/developing-custom-storages/store-traits/custom-function","e5b"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/storages/developing-custom-storages/store-traits/custom-function-mut",component:f("/docs/dev/storages/developing-custom-storages/store-traits/custom-function-mut","0cc"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/storages/developing-custom-storages/store-traits/index-mut",component:f("/docs/dev/storages/developing-custom-storages/store-traits/index-mut","78f"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/storages/developing-custom-storages/store-traits/index-trait",component:f("/docs/dev/storages/developing-custom-storages/store-traits/index-trait","aa3"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/storages/developing-custom-storages/store-traits/metadata",component:f("/docs/dev/storages/developing-custom-storages/store-traits/metadata","2a5"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/storages/developing-custom-storages/store-traits/store",component:f("/docs/dev/storages/developing-custom-storages/store-traits/store","262"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/storages/developing-custom-storages/store-traits/store-mut",component:f("/docs/dev/storages/developing-custom-storages/store-traits/store-mut","853"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/storages/developing-custom-storages/store-traits/transaction",component:f("/docs/dev/storages/developing-custom-storages/store-traits/transaction","bd7"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/storages/developing-custom-storages/using-test-suite",component:f("/docs/dev/storages/developing-custom-storages/using-test-suite","a37"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/storages/intro",component:f("/docs/dev/storages/intro","8d9"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/storages/supported-storages/composite-storage",component:f("/docs/dev/storages/supported-storages/composite-storage","93e"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/storages/supported-storages/idb-storage",component:f("/docs/dev/storages/supported-storages/idb-storage","787"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/storages/supported-storages/json-storage",component:f("/docs/dev/storages/supported-storages/json-storage","207"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/storages/supported-storages/memory-storage",component:f("/docs/dev/storages/supported-storages/memory-storage","695"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/storages/supported-storages/shared-memory-storage",component:f("/docs/dev/storages/supported-storages/shared-memory-storage","418"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/storages/supported-storages/sled-storage",component:f("/docs/dev/storages/supported-storages/sled-storage","fb0"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/storages/supported-storages/web-storage",component:f("/docs/dev/storages/supported-storages/web-storage","14a"),exact:!0,sidebar:"autoSidebar"}]},{path:"*",component:f("*")}]},8934:(e,t,n)=>{"use strict";n.d(t,{_:()=>r,t:()=>o});var a=n(7294);const r=a.createContext(!1);function o(e){let{children:t}=e;const[n,o]=(0,a.useState)(!1);return(0,a.useEffect)((()=>{o(!0)}),[]),a.createElement(r.Provider,{value:n},t)}},7221:(e,t,n)=>{"use strict";var a=n(7294),r=n(3935),o=n(3727),s=n(405),i=n(412);const l=[n(2497),n(3310),n(8320),n(2295)];var c=n(723),u=n(6550),d=n(8790);function f(e){let{children:t}=e;return a.createElement(a.Fragment,null,t)}var p=n(7462),m=n(5742),g=n(2263),h=n(4996),b=n(6668),v=n(1944),y=n(4711),x=n(9727),w=n(3320),S=n(8780),E=n(197);function k(){const{i18n:{defaultLocale:e,localeConfigs:t}}=(0,g.Z)(),n=(0,y.l)();return a.createElement(m.Z,null,Object.entries(t).map((e=>{let[t,{htmlLang:r}]=e;return a.createElement("link",{key:t,rel:"alternate",href:n.createUrl({locale:t,fullyQualified:!0}),hrefLang:r})})),a.createElement("link",{rel:"alternate",href:n.createUrl({locale:e,fullyQualified:!0}),hrefLang:"x-default"}))}function _(e){let{permalink:t}=e;const{siteConfig:{url:n}}=(0,g.Z)(),r=function(){const{siteConfig:{url:e,baseUrl:t,trailingSlash:n}}=(0,g.Z)(),{pathname:a}=(0,u.TH)();return e+(0,S.applyTrailingSlash)((0,h.Z)(a),{trailingSlash:n,baseUrl:t})}(),o=t?`${n}${t}`:r;return a.createElement(m.Z,null,a.createElement("meta",{property:"og:url",content:o}),a.createElement("link",{rel:"canonical",href:o}))}function C(){const{i18n:{currentLocale:e}}=(0,g.Z)(),{metadata:t,image:n}=(0,b.L)();return a.createElement(a.Fragment,null,a.createElement(m.Z,null,a.createElement("meta",{name:"twitter:card",content:"summary_large_image"}),a.createElement("body",{className:x.h})),n&&a.createElement(v.d,{image:n}),a.createElement(_,null),a.createElement(k,null),a.createElement(E.Z,{tag:w.HX,locale:e}),a.createElement(m.Z,null,t.map(((e,t)=>a.createElement("meta",(0,p.Z)({key:t},e))))))}const q=new Map;function T(e){if(q.has(e.pathname))return{...e,pathname:q.get(e.pathname)};if((0,d.f)(c.Z,e.pathname).some((e=>{let{route:t}=e;return!0===t.exact})))return q.set(e.pathname,e.pathname),e;const t=e.pathname.trim().replace(/(?:\/index)?\.html$/,"")||"/";return q.set(e.pathname,t),{...e,pathname:t}}var A=n(8934),L=n(8940);function N(e){for(var t=arguments.length,n=new Array(t>1?t-1:0),a=1;a<t;a++)n[a-1]=arguments[a];const r=l.map((t=>{const a=t.default?.[e]??t[e];return a?.(...n)}));return()=>r.forEach((e=>e?.()))}const O=function(e){let{children:t,location:n,previousLocation:r}=e;return(0,a.useLayoutEffect)((()=>{r!==n&&(!function(e){let{location:t,previousLocation:n}=e;if(!n)return;const a=t.pathname===n.pathname,r=t.hash===n.hash,o=t.search===n.search;if(a&&r&&!o)return;const{hash:s}=t;if(s){const e=decodeURIComponent(s.substring(1)),t=document.getElementById(e);t?.scrollIntoView()}else window.scrollTo(0,0)}({location:n,previousLocation:r}),N("onRouteDidUpdate",{previousLocation:r,location:n}))}),[r,n]),t};function P(e){const t=Array.from(new Set([e,decodeURI(e)])).map((e=>(0,d.f)(c.Z,e))).flat();return Promise.all(t.map((e=>e.route.component.preload?.())))}class I extends a.Component{previousLocation;routeUpdateCleanupCb;constructor(e){super(e),this.previousLocation=null,this.routeUpdateCleanupCb=i.Z.canUseDOM?N("onRouteUpdate",{previousLocation:null,location:this.props.location}):()=>{},this.state={nextRouteHasLoaded:!0}}shouldComponentUpdate(e,t){if(e.location===this.props.location)return t.nextRouteHasLoaded;const n=e.location;return this.previousLocation=this.props.location,this.setState({nextRouteHasLoaded:!1}),this.routeUpdateCleanupCb=N("onRouteUpdate",{previousLocation:this.previousLocation,location:n}),P(n.pathname).then((()=>{this.routeUpdateCleanupCb(),this.setState({nextRouteHasLoaded:!0})})).catch((e=>{console.warn(e),window.location.reload()})),!1}render(){const{children:e,location:t}=this.props;return a.createElement(O,{previousLocation:this.previousLocation,location:t},a.createElement(u.AW,{location:t,render:()=>e}))}}const R=I,M="__docusaurus-base-url-issue-banner-container",D="__docusaurus-base-url-issue-banner",F="__docusaurus-base-url-issue-banner-suggestion-container",B="__DOCUSAURUS_INSERT_BASEURL_BANNER";function j(e){return`\nwindow['${B}'] = true;\n\ndocument.addEventListener('DOMContentLoaded', maybeInsertBanner);\n\nfunction maybeInsertBanner() {\n var shouldInsert = window['${B}'];\n shouldInsert && insertBanner();\n}\n\nfunction insertBanner() {\n var bannerContainer = document.getElementById('${M}');\n if (!bannerContainer) {\n return;\n }\n var bannerHtml = ${JSON.stringify(function(e){return`\n<div id="${D}" style="border: thick solid red; background-color: rgb(255, 230, 179); margin: 20px; padding: 20px; font-size: 20px;">\n <p style="font-weight: bold; font-size: 30px;">Your Docusaurus site did not load properly.</p>\n <p>A very common reason is a wrong site <a href="https://docusaurus.io/docs/docusaurus.config.js/#baseUrl" style="font-weight: bold;">baseUrl configuration</a>.</p>\n <p>Current configured baseUrl = <span style="font-weight: bold; color: red;">${e}</span> ${"/"===e?" (default value)":""}</p>\n <p>We suggest trying baseUrl = <span id="${F}" style="font-weight: bold; color: green;"></span></p>\n</div>\n`}(e)).replace(/</g,"\\<")};\n bannerContainer.innerHTML = bannerHtml;\n var suggestionContainer = document.getElementById('${F}');\n var actualHomePagePath = window.location.pathname;\n var suggestedBaseUrl = actualHomePagePath.substr(-1) === '/'\n ? actualHomePagePath\n : actualHomePagePath + '/';\n suggestionContainer.innerHTML = suggestedBaseUrl;\n}\n`}function z(){const{siteConfig:{baseUrl:e}}=(0,g.Z)();return(0,a.useLayoutEffect)((()=>{window[B]=!1}),[]),a.createElement(a.Fragment,null,!i.Z.canUseDOM&&a.createElement(m.Z,null,a.createElement("script",null,j(e))),a.createElement("div",{id:M}))}function $(){const{siteConfig:{baseUrl:e,baseUrlIssueBanner:t}}=(0,g.Z)(),{pathname:n}=(0,u.TH)();return t&&n===e?a.createElement(z,null):null}function U(){const{siteConfig:{favicon:e,title:t,noIndex:n},i18n:{currentLocale:r,localeConfigs:o}}=(0,g.Z)(),s=(0,h.Z)(e),{htmlLang:i,direction:l}=o[r];return a.createElement(m.Z,null,a.createElement("html",{lang:i,dir:l}),a.createElement("title",null,t),a.createElement("meta",{property:"og:title",content:t}),a.createElement("meta",{name:"viewport",content:"width=device-width, initial-scale=1.0"}),n&&a.createElement("meta",{name:"robots",content:"noindex, nofollow"}),e&&a.createElement("link",{rel:"icon",href:s}))}var Z=n(4763),H=n(2389);function V(){const e=(0,H.Z)();return a.createElement(m.Z,null,a.createElement("html",{"data-has-hydrated":e}))}function W(){const e=(0,d.H)(c.Z),t=(0,u.TH)();return a.createElement(Z.Z,null,a.createElement(L.M,null,a.createElement(A.t,null,a.createElement(f,null,a.createElement(U,null),a.createElement(C,null),a.createElement($,null),a.createElement(R,{location:T(t)},e)),a.createElement(V,null))))}var G=n(6887);const Y=function(e){try{return document.createElement("link").relList.supports(e)}catch{return!1}}("prefetch")?function(e){return new Promise(((t,n)=>{if("undefined"==typeof document)return void n();const a=document.createElement("link");a.setAttribute("rel","prefetch"),a.setAttribute("href",e),a.onload=()=>t(),a.onerror=()=>n();const r=document.getElementsByTagName("head")[0]??document.getElementsByName("script")[0]?.parentNode;r?.appendChild(a)}))}:function(e){return new Promise(((t,n)=>{const a=new XMLHttpRequest;a.open("GET",e,!0),a.withCredentials=!0,a.onload=()=>{200===a.status?t():n()},a.send(null)}))};var K=n(9670);const Q=new Set,X=new Set,J=()=>navigator.connection?.effectiveType.includes("2g")||navigator.connection?.saveData,ee={prefetch(e){if(!(e=>!J()&&!X.has(e)&&!Q.has(e))(e))return!1;Q.add(e);const t=(0,d.f)(c.Z,e).flatMap((e=>{return t=e.route.path,Object.entries(G).filter((e=>{let[n]=e;return n.replace(/-[^-]+$/,"")===t})).flatMap((e=>{let[,t]=e;return Object.values((0,K.Z)(t))}));var t}));return Promise.all(t.map((e=>{const t=n.gca(e);return t&&!t.includes("undefined")?Y(t).catch((()=>{})):Promise.resolve()})))},preload:e=>!!(e=>!J()&&!X.has(e))(e)&&(X.add(e),P(e))},te=Object.freeze(ee);if(i.Z.canUseDOM){window.docusaurus=te;const e=r.hydrate;P(window.location.pathname).then((()=>{e(a.createElement(s.B6,null,a.createElement(o.VK,null,a.createElement(W,null))),document.getElementById("__docusaurus"))}))}},8940:(e,t,n)=>{"use strict";n.d(t,{_:()=>u,M:()=>d});var a=n(7294),r=n(6809);const o=JSON.parse('{"docusaurus-plugin-content-docs":{"default":{"path":"/docs/dev/","versions":[{"name":"current","label":"Next","isLast":true,"path":"/docs/dev/","mainDocId":"index","docs":[{"id":"ast-builder/expressions/conditional","path":"/docs/dev/ast-builder/expressions/conditional","sidebar":"autoSidebar"},{"id":"ast-builder/expressions/nested","path":"/docs/dev/ast-builder/expressions/nested","sidebar":"autoSidebar"},{"id":"ast-builder/expressions/operator-based","path":"/docs/dev/ast-builder/expressions/operator-based","sidebar":"autoSidebar"},{"id":"ast-builder/expressions/pattern-matching","path":"/docs/dev/ast-builder/expressions/pattern-matching","sidebar":"autoSidebar"},{"id":"ast-builder/expressions/value-checking","path":"/docs/dev/ast-builder/expressions/value-checking","sidebar":"autoSidebar"},{"id":"ast-builder/functions/date-&-time/conversion","path":"/docs/dev/ast-builder/functions/date-&-time/conversion","sidebar":"autoSidebar"},{"id":"ast-builder/functions/date-&-time/current-date-and-time","path":"/docs/dev/ast-builder/functions/date-&-time/current-date-and-time","sidebar":"autoSidebar"},{"id":"ast-builder/functions/date-&-time/date-and-time-extraction","path":"/docs/dev/ast-builder/functions/date-&-time/date-and-time-extraction","sidebar":"autoSidebar"},{"id":"ast-builder/functions/date-&-time/formatting","path":"/docs/dev/ast-builder/functions/date-&-time/formatting","sidebar":"autoSidebar"},{"id":"ast-builder/functions/geometry/coordinate-extraction","path":"/docs/dev/ast-builder/functions/geometry/coordinate-extraction","sidebar":"autoSidebar"},{"id":"ast-builder/functions/geometry/distance-calculation","path":"/docs/dev/ast-builder/functions/geometry/distance-calculation","sidebar":"autoSidebar"},{"id":"ast-builder/functions/geometry/point-creation","path":"/docs/dev/ast-builder/functions/geometry/point-creation","sidebar":"autoSidebar"},{"id":"ast-builder/functions/list-&-map/list-and-map-concatenation","path":"/docs/dev/ast-builder/functions/list-&-map/list-and-map-concatenation","sidebar":"autoSidebar"},{"id":"ast-builder/functions/list-&-map/list-manipulation","path":"/docs/dev/ast-builder/functions/list-&-map/list-manipulation","sidebar":"autoSidebar"},{"id":"ast-builder/functions/math/basic-arithmetic","path":"/docs/dev/ast-builder/functions/math/basic-arithmetic","sidebar":"autoSidebar"},{"id":"ast-builder/functions/math/conversion","path":"/docs/dev/ast-builder/functions/math/conversion","sidebar":"autoSidebar"},{"id":"ast-builder/functions/math/logarithmic-and-exponential","path":"/docs/dev/ast-builder/functions/math/logarithmic-and-exponential","sidebar":"autoSidebar"},{"id":"ast-builder/functions/math/rounding","path":"/docs/dev/ast-builder/functions/math/rounding","sidebar":"autoSidebar"},{"id":"ast-builder/functions/math/special-mathematical","path":"/docs/dev/ast-builder/functions/math/special-mathematical","sidebar":"autoSidebar"},{"id":"ast-builder/functions/math/trigonometric","path":"/docs/dev/ast-builder/functions/math/trigonometric","sidebar":"autoSidebar"},{"id":"ast-builder/functions/others/null-handling","path":"/docs/dev/ast-builder/functions/others/null-handling","sidebar":"autoSidebar"},{"id":"ast-builder/functions/others/type-conversion","path":"/docs/dev/ast-builder/functions/others/type-conversion","sidebar":"autoSidebar"},{"id":"ast-builder/functions/others/unique-identifier","path":"/docs/dev/ast-builder/functions/others/unique-identifier","sidebar":"autoSidebar"},{"id":"ast-builder/functions/text/case-conversion","path":"/docs/dev/ast-builder/functions/text/case-conversion","sidebar":"autoSidebar"},{"id":"ast-builder/functions/text/character-conversion","path":"/docs/dev/ast-builder/functions/text/character-conversion","sidebar":"autoSidebar"},{"id":"ast-builder/functions/text/padding","path":"/docs/dev/ast-builder/functions/text/padding","sidebar":"autoSidebar"},{"id":"ast-builder/functions/text/position-and-indexing","path":"/docs/dev/ast-builder/functions/text/position-and-indexing","sidebar":"autoSidebar"},{"id":"ast-builder/functions/text/text-manipulation","path":"/docs/dev/ast-builder/functions/text/text-manipulation","sidebar":"autoSidebar"},{"id":"ast-builder/functions/text/trimming","path":"/docs/dev/ast-builder/functions/text/trimming","sidebar":"autoSidebar"},{"id":"ast-builder/intro","path":"/docs/dev/ast-builder/intro","sidebar":"autoSidebar"},{"id":"ast-builder/statements/data-manipulation/deleting-data","path":"/docs/dev/ast-builder/statements/data-manipulation/deleting-data","sidebar":"autoSidebar"},{"id":"ast-builder/statements/data-manipulation/inserting-data","path":"/docs/dev/ast-builder/statements/data-manipulation/inserting-data","sidebar":"autoSidebar"},{"id":"ast-builder/statements/data-manipulation/updating-data","path":"/docs/dev/ast-builder/statements/data-manipulation/updating-data","sidebar":"autoSidebar"},{"id":"ast-builder/statements/querying/creating-derived-subqueries","path":"/docs/dev/ast-builder/statements/querying/creating-derived-subqueries","sidebar":"autoSidebar"},{"id":"ast-builder/statements/querying/data-aggregation","path":"/docs/dev/ast-builder/statements/querying/data-aggregation","sidebar":"autoSidebar"},{"id":"ast-builder/statements/querying/data-injection","path":"/docs/dev/ast-builder/statements/querying/data-injection","sidebar":"autoSidebar"},{"id":"ast-builder/statements/querying/data-joining","path":"/docs/dev/ast-builder/statements/querying/data-joining","sidebar":"autoSidebar"},{"id":"ast-builder/statements/querying/data-selection-and-projection","path":"/docs/dev/ast-builder/statements/querying/data-selection-and-projection","sidebar":"autoSidebar"},{"id":"ast-builder/statements/querying/data-sorting-and-limiting","path":"/docs/dev/ast-builder/statements/querying/data-sorting-and-limiting","sidebar":"autoSidebar"},{"id":"ast-builder/statements/querying/fetching-data-from-storage","path":"/docs/dev/ast-builder/statements/querying/fetching-data-from-storage","sidebar":"autoSidebar"},{"id":"ast-builder/statements/querying/using-preloaded-data","path":"/docs/dev/ast-builder/statements/querying/using-preloaded-data","sidebar":"autoSidebar"},{"id":"getting-started/cli","path":"/docs/dev/getting-started/cli","sidebar":"autoSidebar"},{"id":"getting-started/javascript-web","path":"/docs/dev/getting-started/javascript-web","sidebar":"autoSidebar"},{"id":"getting-started/nodejs","path":"/docs/dev/getting-started/nodejs","sidebar":"autoSidebar"},{"id":"getting-started/rust","path":"/docs/dev/getting-started/rust","sidebar":"autoSidebar"},{"id":"index","path":"/docs/dev/","sidebar":"autoSidebar"},{"id":"sql-syntax/data-types/boolean","path":"/docs/dev/sql-syntax/data-types/boolean","sidebar":"autoSidebar"},{"id":"sql-syntax/data-types/bytea","path":"/docs/dev/sql-syntax/data-types/bytea","sidebar":"autoSidebar"},{"id":"sql-syntax/data-types/date","path":"/docs/dev/sql-syntax/data-types/date","sidebar":"autoSidebar"},{"id":"sql-syntax/data-types/decimal","path":"/docs/dev/sql-syntax/data-types/decimal","sidebar":"autoSidebar"},{"id":"sql-syntax/data-types/float","path":"/docs/dev/sql-syntax/data-types/float","sidebar":"autoSidebar"},{"id":"sql-syntax/data-types/inet","path":"/docs/dev/sql-syntax/data-types/inet","sidebar":"autoSidebar"},{"id":"sql-syntax/data-types/integers","path":"/docs/dev/sql-syntax/data-types/integers","sidebar":"autoSidebar"},{"id":"sql-syntax/data-types/interval","path":"/docs/dev/sql-syntax/data-types/interval","sidebar":"autoSidebar"},{"id":"sql-syntax/data-types/list","path":"/docs/dev/sql-syntax/data-types/list","sidebar":"autoSidebar"},{"id":"sql-syntax/data-types/map","path":"/docs/dev/sql-syntax/data-types/map","sidebar":"autoSidebar"},{"id":"sql-syntax/data-types/text","path":"/docs/dev/sql-syntax/data-types/text","sidebar":"autoSidebar"},{"id":"sql-syntax/data-types/time","path":"/docs/dev/sql-syntax/data-types/time","sidebar":"autoSidebar"},{"id":"sql-syntax/data-types/timestamp","path":"/docs/dev/sql-syntax/data-types/timestamp","sidebar":"autoSidebar"},{"id":"sql-syntax/data-types/uuid","path":"/docs/dev/sql-syntax/data-types/uuid","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/datetime/extract","path":"/docs/dev/sql-syntax/functions/datetime/extract","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/datetime/format","path":"/docs/dev/sql-syntax/functions/datetime/format","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/datetime/now","path":"/docs/dev/sql-syntax/functions/datetime/now","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/datetime/to-date","path":"/docs/dev/sql-syntax/functions/datetime/to-date","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/datetime/to-time","path":"/docs/dev/sql-syntax/functions/datetime/to-time","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/datetime/to-timestamp","path":"/docs/dev/sql-syntax/functions/datetime/to-timestamp","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/geometry/calc-distance","path":"/docs/dev/sql-syntax/functions/geometry/calc-distance","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/geometry/get-x","path":"/docs/dev/sql-syntax/functions/geometry/get-x","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/geometry/get-y","path":"/docs/dev/sql-syntax/functions/geometry/get-y","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/geometry/point","path":"/docs/dev/sql-syntax/functions/geometry/point","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/list-map/append","path":"/docs/dev/sql-syntax/functions/list-map/append","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/list-map/concat","path":"/docs/dev/sql-syntax/functions/list-map/concat","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/list-map/prepend","path":"/docs/dev/sql-syntax/functions/list-map/prepend","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/list-map/splice","path":"/docs/dev/sql-syntax/functions/list-map/splice","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/math/abs","path":"/docs/dev/sql-syntax/functions/math/abs","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/math/acos","path":"/docs/dev/sql-syntax/functions/math/acos","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/math/asin","path":"/docs/dev/sql-syntax/functions/math/asin","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/math/atan","path":"/docs/dev/sql-syntax/functions/math/atan","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/math/ceil","path":"/docs/dev/sql-syntax/functions/math/ceil","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/math/cos","path":"/docs/dev/sql-syntax/functions/math/cos","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/math/degrees","path":"/docs/dev/sql-syntax/functions/math/degrees","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/math/div","path":"/docs/dev/sql-syntax/functions/math/div","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/math/exp","path":"/docs/dev/sql-syntax/functions/math/exp","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/math/floor","path":"/docs/dev/sql-syntax/functions/math/floor","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/math/gcd","path":"/docs/dev/sql-syntax/functions/math/gcd","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/math/lcm","path":"/docs/dev/sql-syntax/functions/math/lcm","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/math/ln","path":"/docs/dev/sql-syntax/functions/math/ln","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/math/log","path":"/docs/dev/sql-syntax/functions/math/log","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/math/log10","path":"/docs/dev/sql-syntax/functions/math/log10","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/math/log2","path":"/docs/dev/sql-syntax/functions/math/log2","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/math/mod","path":"/docs/dev/sql-syntax/functions/math/mod","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/math/pi","path":"/docs/dev/sql-syntax/functions/math/pi","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/math/power","path":"/docs/dev/sql-syntax/functions/math/power","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/math/radians","path":"/docs/dev/sql-syntax/functions/math/radians","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/math/rand","path":"/docs/dev/sql-syntax/functions/math/rand","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/math/round","path":"/docs/dev/sql-syntax/functions/math/round","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/math/sign","path":"/docs/dev/sql-syntax/functions/math/sign","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/math/sin","path":"/docs/dev/sql-syntax/functions/math/sin","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/math/sqrt","path":"/docs/dev/sql-syntax/functions/math/sqrt","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/math/tan","path":"/docs/dev/sql-syntax/functions/math/tan","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/others/cast","path":"/docs/dev/sql-syntax/functions/others/cast","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/others/generate-uuid","path":"/docs/dev/sql-syntax/functions/others/generate-uuid","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/others/ifnull","path":"/docs/dev/sql-syntax/functions/others/ifnull","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/text/ascii","path":"/docs/dev/sql-syntax/functions/text/ascii","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/text/chr","path":"/docs/dev/sql-syntax/functions/text/chr","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/text/concat","path":"/docs/dev/sql-syntax/functions/text/concat","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/text/concat-ws","path":"/docs/dev/sql-syntax/functions/text/concat-ws","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/text/find-idx","path":"/docs/dev/sql-syntax/functions/text/find-idx","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/text/initcap","path":"/docs/dev/sql-syntax/functions/text/initcap","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/text/left","path":"/docs/dev/sql-syntax/functions/text/left","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/text/lower","path":"/docs/dev/sql-syntax/functions/text/lower","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/text/lpad","path":"/docs/dev/sql-syntax/functions/text/lpad","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/text/ltrim","path":"/docs/dev/sql-syntax/functions/text/ltrim","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/text/position","path":"/docs/dev/sql-syntax/functions/text/position","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/text/repeat","path":"/docs/dev/sql-syntax/functions/text/repeat","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/text/reverse","path":"/docs/dev/sql-syntax/functions/text/reverse","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/text/right","path":"/docs/dev/sql-syntax/functions/text/right","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/text/rpad","path":"/docs/dev/sql-syntax/functions/text/rpad","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/text/rtrim","path":"/docs/dev/sql-syntax/functions/text/rtrim","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/text/substr","path":"/docs/dev/sql-syntax/functions/text/substr","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/text/trim","path":"/docs/dev/sql-syntax/functions/text/trim","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/text/upper","path":"/docs/dev/sql-syntax/functions/text/upper","sidebar":"autoSidebar"},{"id":"sql-syntax/intro","path":"/docs/dev/sql-syntax/intro","sidebar":"autoSidebar"},{"id":"sql-syntax/statements/data-definition/alter-table","path":"/docs/dev/sql-syntax/statements/data-definition/alter-table","sidebar":"autoSidebar"},{"id":"sql-syntax/statements/data-definition/create-index","path":"/docs/dev/sql-syntax/statements/data-definition/create-index","sidebar":"autoSidebar"},{"id":"sql-syntax/statements/data-definition/create-table","path":"/docs/dev/sql-syntax/statements/data-definition/create-table","sidebar":"autoSidebar"},{"id":"sql-syntax/statements/data-definition/drop-index","path":"/docs/dev/sql-syntax/statements/data-definition/drop-index","sidebar":"autoSidebar"},{"id":"sql-syntax/statements/data-definition/drop-table","path":"/docs/dev/sql-syntax/statements/data-definition/drop-table","sidebar":"autoSidebar"},{"id":"sql-syntax/statements/data-manipulation/delete","path":"/docs/dev/sql-syntax/statements/data-manipulation/delete","sidebar":"autoSidebar"},{"id":"sql-syntax/statements/data-manipulation/insert","path":"/docs/dev/sql-syntax/statements/data-manipulation/insert","sidebar":"autoSidebar"},{"id":"sql-syntax/statements/data-manipulation/update","path":"/docs/dev/sql-syntax/statements/data-manipulation/update","sidebar":"autoSidebar"},{"id":"sql-syntax/statements/metadata/data-dictionary","path":"/docs/dev/sql-syntax/statements/metadata/data-dictionary","sidebar":"autoSidebar"},{"id":"sql-syntax/statements/metadata/show-tables","path":"/docs/dev/sql-syntax/statements/metadata/show-tables","sidebar":"autoSidebar"},{"id":"sql-syntax/statements/querying/aggregation","path":"/docs/dev/sql-syntax/statements/querying/aggregation","sidebar":"autoSidebar"},{"id":"sql-syntax/statements/querying/join","path":"/docs/dev/sql-syntax/statements/querying/join","sidebar":"autoSidebar"},{"id":"sql-syntax/statements/querying/limit","path":"/docs/dev/sql-syntax/statements/querying/limit","sidebar":"autoSidebar"},{"id":"sql-syntax/statements/querying/schemaless","path":"/docs/dev/sql-syntax/statements/querying/schemaless","sidebar":"autoSidebar"},{"id":"sql-syntax/statements/querying/where","path":"/docs/dev/sql-syntax/statements/querying/where","sidebar":"autoSidebar"},{"id":"sql-syntax/statements/transaction","path":"/docs/dev/sql-syntax/statements/transaction","sidebar":"autoSidebar"},{"id":"storages/developing-custom-storages/intro","path":"/docs/dev/storages/developing-custom-storages/intro","sidebar":"autoSidebar"},{"id":"storages/developing-custom-storages/store-traits/alter-table","path":"/docs/dev/storages/developing-custom-storages/store-traits/alter-table","sidebar":"autoSidebar"},{"id":"storages/developing-custom-storages/store-traits/custom-function","path":"/docs/dev/storages/developing-custom-storages/store-traits/custom-function","sidebar":"autoSidebar"},{"id":"storages/developing-custom-storages/store-traits/custom-function-mut","path":"/docs/dev/storages/developing-custom-storages/store-traits/custom-function-mut","sidebar":"autoSidebar"},{"id":"storages/developing-custom-storages/store-traits/index-mut","path":"/docs/dev/storages/developing-custom-storages/store-traits/index-mut","sidebar":"autoSidebar"},{"id":"storages/developing-custom-storages/store-traits/index-trait","path":"/docs/dev/storages/developing-custom-storages/store-traits/index-trait","sidebar":"autoSidebar"},{"id":"storages/developing-custom-storages/store-traits/metadata","path":"/docs/dev/storages/developing-custom-storages/store-traits/metadata","sidebar":"autoSidebar"},{"id":"storages/developing-custom-storages/store-traits/store","path":"/docs/dev/storages/developing-custom-storages/store-traits/store","sidebar":"autoSidebar"},{"id":"storages/developing-custom-storages/store-traits/store-mut","path":"/docs/dev/storages/developing-custom-storages/store-traits/store-mut","sidebar":"autoSidebar"},{"id":"storages/developing-custom-storages/store-traits/transaction","path":"/docs/dev/storages/developing-custom-storages/store-traits/transaction","sidebar":"autoSidebar"},{"id":"storages/developing-custom-storages/using-test-suite","path":"/docs/dev/storages/developing-custom-storages/using-test-suite","sidebar":"autoSidebar"},{"id":"storages/intro","path":"/docs/dev/storages/intro","sidebar":"autoSidebar"},{"id":"storages/supported-storages/composite-storage","path":"/docs/dev/storages/supported-storages/composite-storage","sidebar":"autoSidebar"},{"id":"storages/supported-storages/idb-storage","path":"/docs/dev/storages/supported-storages/idb-storage","sidebar":"autoSidebar"},{"id":"storages/supported-storages/json-storage","path":"/docs/dev/storages/supported-storages/json-storage","sidebar":"autoSidebar"},{"id":"storages/supported-storages/memory-storage","path":"/docs/dev/storages/supported-storages/memory-storage","sidebar":"autoSidebar"},{"id":"storages/supported-storages/shared-memory-storage","path":"/docs/dev/storages/supported-storages/shared-memory-storage","sidebar":"autoSidebar"},{"id":"storages/supported-storages/sled-storage","path":"/docs/dev/storages/supported-storages/sled-storage","sidebar":"autoSidebar"},{"id":"storages/supported-storages/web-storage","path":"/docs/dev/storages/supported-storages/web-storage","sidebar":"autoSidebar"}],"draftIds":[],"sidebars":{"autoSidebar":{"link":{"path":"/docs/dev/","label":"index"}}}}],"breadcrumbs":true}}}'),s=JSON.parse('{"defaultLocale":"en","locales":["en"],"path":"i18n","currentLocale":"en","localeConfigs":{"en":{"label":"English","direction":"ltr","htmlLang":"en","calendar":"gregory","path":"en"}}}');var i=n(7529);const l=JSON.parse('{"docusaurusVersion":"2.4.3","siteVersion":"0.0.0","pluginVersions":{"docusaurus-plugin-content-docs":{"type":"package","name":"@docusaurus/plugin-content-docs","version":"2.4.3"},"docusaurus-plugin-content-blog":{"type":"package","name":"@docusaurus/plugin-content-blog","version":"2.4.3"},"docusaurus-plugin-sitemap":{"type":"package","name":"@docusaurus/plugin-sitemap","version":"2.4.3"},"docusaurus-theme-classic":{"type":"package","name":"@docusaurus/theme-classic","version":"2.4.3"}}}'),c={siteConfig:r.default,siteMetadata:l,globalData:o,i18n:s,codeTranslations:i},u=a.createContext(c);function d(e){let{children:t}=e;return a.createElement(u.Provider,{value:c},t)}},4763:(e,t,n)=>{"use strict";n.d(t,{Z:()=>f});var a=n(7294),r=n(412),o=n(5742),s=n(8780),i=n(7961);function l(e){let{error:t,tryAgain:n}=e;return a.createElement("div",{style:{display:"flex",flexDirection:"column",justifyContent:"center",alignItems:"flex-start",minHeight:"100vh",width:"100%",maxWidth:"80ch",fontSize:"20px",margin:"0 auto",padding:"1rem"}},a.createElement("h1",{style:{fontSize:"3rem"}},"This page crashed"),a.createElement("button",{type:"button",onClick:n,style:{margin:"1rem 0",fontSize:"2rem",cursor:"pointer",borderRadius:20,padding:"1rem"}},"Try again"),a.createElement(c,{error:t}))}function c(e){let{error:t}=e;const n=(0,s.getErrorCausalChain)(t).map((e=>e.message)).join("\n\nCause:\n");return a.createElement("p",{style:{whiteSpace:"pre-wrap"}},n)}function u(e){let{error:t,tryAgain:n}=e;return a.createElement(f,{fallback:()=>a.createElement(l,{error:t,tryAgain:n})},a.createElement(o.Z,null,a.createElement("title",null,"Page Error")),a.createElement(i.Z,null,a.createElement(l,{error:t,tryAgain:n})))}const d=e=>a.createElement(u,e);class f extends a.Component{constructor(e){super(e),this.state={error:null}}componentDidCatch(e){r.Z.canUseDOM&&this.setState({error:e})}render(){const{children:e}=this.props,{error:t}=this.state;if(t){const e={error:t,tryAgain:()=>this.setState({error:null})};return(this.props.fallback??d)(e)}return e??null}}},412:(e,t,n)=>{"use strict";n.d(t,{Z:()=>r});const a="undefined"!=typeof window&&"document"in window&&"createElement"in window.document,r={canUseDOM:a,canUseEventListeners:a&&("addEventListener"in window||"attachEvent"in window),canUseIntersectionObserver:a&&"IntersectionObserver"in window,canUseViewport:a&&"screen"in window}},5742:(e,t,n)=>{"use strict";n.d(t,{Z:()=>o});var a=n(7294),r=n(405);function o(e){return a.createElement(r.ql,e)}},9960:(e,t,n)=>{"use strict";n.d(t,{Z:()=>p});var a=n(7462),r=n(7294),o=n(3727),s=n(8780),i=n(2263),l=n(3919),c=n(412);const u=r.createContext({collectLink:()=>{}});var d=n(4996);function f(e,t){let{isNavLink:n,to:f,href:p,activeClassName:m,isActive:g,"data-noBrokenLinkCheck":h,autoAddBaseUrl:b=!0,...v}=e;const{siteConfig:{trailingSlash:y,baseUrl:x}}=(0,i.Z)(),{withBaseUrl:w}=(0,d.C)(),S=(0,r.useContext)(u),E=(0,r.useRef)(null);(0,r.useImperativeHandle)(t,(()=>E.current));const k=f||p;const _=(0,l.Z)(k),C=k?.replace("pathname://","");let q=void 0!==C?(T=C,b&&(e=>e.startsWith("/"))(T)?w(T):T):void 0;var T;q&&_&&(q=(0,s.applyTrailingSlash)(q,{trailingSlash:y,baseUrl:x}));const A=(0,r.useRef)(!1),L=n?o.OL:o.rU,N=c.Z.canUseIntersectionObserver,O=(0,r.useRef)(),P=()=>{A.current||null==q||(window.docusaurus.preload(q),A.current=!0)};(0,r.useEffect)((()=>(!N&&_&&null!=q&&window.docusaurus.prefetch(q),()=>{N&&O.current&&O.current.disconnect()})),[O,q,N,_]);const I=q?.startsWith("#")??!1,R=!q||!_||I;return R||h||S.collectLink(q),R?r.createElement("a",(0,a.Z)({ref:E,href:q},k&&!_&&{target:"_blank",rel:"noopener noreferrer"},v)):r.createElement(L,(0,a.Z)({},v,{onMouseEnter:P,onTouchStart:P,innerRef:e=>{E.current=e,N&&e&&_&&(O.current=new window.IntersectionObserver((t=>{t.forEach((t=>{e===t.target&&(t.isIntersecting||t.intersectionRatio>0)&&(O.current.unobserve(e),O.current.disconnect(),null!=q&&window.docusaurus.prefetch(q))}))})),O.current.observe(e))},to:q},n&&{isActive:g,activeClassName:m}))}const p=r.forwardRef(f)},1875:(e,t,n)=>{"use strict";n.d(t,{Z:()=>a});const a=()=>null},5999:(e,t,n)=>{"use strict";n.d(t,{Z:()=>l,I:()=>i});var a=n(7294);function r(e,t){const n=e.split(/(\{\w+\})/).map(((e,n)=>{if(n%2==1){const n=t?.[e.slice(1,-1)];if(void 0!==n)return n}return e}));return n.some((e=>(0,a.isValidElement)(e)))?n.map(((e,t)=>(0,a.isValidElement)(e)?a.cloneElement(e,{key:t}):e)).filter((e=>""!==e)):n.join("")}var o=n(7529);function s(e){let{id:t,message:n}=e;if(void 0===t&&void 0===n)throw new Error("Docusaurus translation declarations must have at least a translation id or a default translation message");return o[t??n]??n??t}function i(e,t){let{message:n,id:a}=e;return r(s({message:n,id:a}),t)}function l(e){let{children:t,id:n,values:o}=e;if(t&&"string"!=typeof t)throw console.warn("Illegal <Translate> children",t),new Error("The Docusaurus <Translate> component only accept simple string values");const i=s({message:t,id:n});return a.createElement(a.Fragment,null,r(i,o))}},9935:(e,t,n)=>{"use strict";n.d(t,{m:()=>a});const a="default"},3919:(e,t,n)=>{"use strict";function a(e){return/^(?:\w*:|\/\/)/.test(e)}function r(e){return void 0!==e&&!a(e)}n.d(t,{Z:()=>r,b:()=>a})},4996:(e,t,n)=>{"use strict";n.d(t,{C:()=>s,Z:()=>i});var a=n(7294),r=n(2263),o=n(3919);function s(){const{siteConfig:{baseUrl:e,url:t}}=(0,r.Z)(),n=(0,a.useCallback)(((n,a)=>function(e,t,n,a){let{forcePrependBaseUrl:r=!1,absolute:s=!1}=void 0===a?{}:a;if(!n||n.startsWith("#")||(0,o.b)(n))return n;if(r)return t+n.replace(/^\//,"");if(n===t.replace(/\/$/,""))return t;const i=n.startsWith(t)?n:t+n.replace(/^\//,"");return s?e+i:i}(t,e,n,a)),[t,e]);return{withBaseUrl:n}}function i(e,t){void 0===t&&(t={});const{withBaseUrl:n}=s();return n(e,t)}},2263:(e,t,n)=>{"use strict";n.d(t,{Z:()=>o});var a=n(7294),r=n(8940);function o(){return(0,a.useContext)(r._)}},2389:(e,t,n)=>{"use strict";n.d(t,{Z:()=>o});var a=n(7294),r=n(8934);function o(){return(0,a.useContext)(r._)}},9670:(e,t,n)=>{"use strict";n.d(t,{Z:()=>r});const a=e=>"object"==typeof e&&!!e&&Object.keys(e).length>0;function r(e){const t={};return function e(n,r){Object.entries(n).forEach((n=>{let[o,s]=n;const i=r?`${r}.${o}`:o;a(s)?e(s,i):t[i]=s}))}(e),t}},226:(e,t,n)=>{"use strict";n.d(t,{_:()=>r,z:()=>o});var a=n(7294);const r=a.createContext(null);function o(e){let{children:t,value:n}=e;const o=a.useContext(r),s=(0,a.useMemo)((()=>function(e){let{parent:t,value:n}=e;if(!t){if(!n)throw new Error("Unexpected: no Docusaurus route context found");if(!("plugin"in n))throw new Error("Unexpected: Docusaurus topmost route context has no `plugin` attribute");return n}const a={...t.data,...n?.data};return{plugin:t.plugin,data:a}}({parent:o,value:n})),[o,n]);return a.createElement(r.Provider,{value:s},t)}},143:(e,t,n)=>{"use strict";n.d(t,{Iw:()=>g,gA:()=>f,_r:()=>u,Jo:()=>h,zh:()=>d,yW:()=>m,gB:()=>p});var a=n(6550),r=n(2263),o=n(9935);function s(e,t){void 0===t&&(t={});const n=function(){const{globalData:e}=(0,r.Z)();return e}()[e];if(!n&&t.failfast)throw new Error(`Docusaurus plugin global data not found for "${e}" plugin.`);return n}const i=e=>e.versions.find((e=>e.isLast));function l(e,t){const n=function(e,t){const n=i(e);return[...e.versions.filter((e=>e!==n)),n].find((e=>!!(0,a.LX)(t,{path:e.path,exact:!1,strict:!1})))}(e,t),r=n?.docs.find((e=>!!(0,a.LX)(t,{path:e.path,exact:!0,strict:!1})));return{activeVersion:n,activeDoc:r,alternateDocVersions:r?function(t){const n={};return e.versions.forEach((e=>{e.docs.forEach((a=>{a.id===t&&(n[e.name]=a)}))})),n}(r.id):{}}}const c={},u=()=>s("docusaurus-plugin-content-docs")??c,d=e=>function(e,t,n){void 0===t&&(t=o.m),void 0===n&&(n={});const a=s(e),r=a?.[t];if(!r&&n.failfast)throw new Error(`Docusaurus plugin global data not found for "${e}" plugin with id "${t}".`);return r}("docusaurus-plugin-content-docs",e,{failfast:!0});function f(e){void 0===e&&(e={});const t=u(),{pathname:n}=(0,a.TH)();return function(e,t,n){void 0===n&&(n={});const r=Object.entries(e).sort(((e,t)=>t[1].path.localeCompare(e[1].path))).find((e=>{let[,n]=e;return!!(0,a.LX)(t,{path:n.path,exact:!1,strict:!1})})),o=r?{pluginId:r[0],pluginData:r[1]}:void 0;if(!o&&n.failfast)throw new Error(`Can't find active docs plugin for "${t}" pathname, while it was expected to be found. Maybe you tried to use a docs feature that can only be used on a docs-related page? Existing docs plugin paths are: ${Object.values(e).map((e=>e.path)).join(", ")}`);return o}(t,n,e)}function p(e){return d(e).versions}function m(e){const t=d(e);return i(t)}function g(e){const t=d(e),{pathname:n}=(0,a.TH)();return l(t,n)}function h(e){const t=d(e),{pathname:n}=(0,a.TH)();return function(e,t){const n=i(e);return{latestDocSuggestion:l(e,t).alternateDocVersions[n.name],latestVersionSuggestion:n}}(t,n)}},8320:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>o});var a=n(4865),r=n.n(a);r().configure({showSpinner:!1});const o={onRouteUpdate(e){let{location:t,previousLocation:n}=e;if(n&&t.pathname!==n.pathname){const e=window.setTimeout((()=>{r().start()}),200);return()=>window.clearTimeout(e)}},onRouteDidUpdate(){r().done()}}},3310:(e,t,n)=>{"use strict";n.r(t);var a=n(7410),r=n(6809);!function(e){const{themeConfig:{prism:t}}=r.default,{additionalLanguages:a}=t;globalThis.Prism=e,a.forEach((e=>{n(6045)(`./prism-${e}`)})),delete globalThis.Prism}(a.Z)},9471:(e,t,n)=>{"use strict";n.d(t,{Z:()=>o});var a=n(7294);const r={iconExternalLink:"iconExternalLink_nPIU"};function o(e){let{width:t=13.5,height:n=13.5}=e;return a.createElement("svg",{width:t,height:n,"aria-hidden":"true",viewBox:"0 0 24 24",className:r.iconExternalLink},a.createElement("path",{fill:"currentColor",d:"M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"}))}},7961:(e,t,n)=>{"use strict";n.d(t,{Z:()=>dt});var a=n(7294),r=n(6010),o=n(4763),s=n(1944),i=n(7462),l=n(6550),c=n(5999),u=n(5936);const d="__docusaurus_skipToContent_fallback";function f(e){e.setAttribute("tabindex","-1"),e.focus(),e.removeAttribute("tabindex")}function p(){const e=(0,a.useRef)(null),{action:t}=(0,l.k6)(),n=(0,a.useCallback)((e=>{e.preventDefault();const t=document.querySelector("main:first-of-type")??document.getElementById(d);t&&f(t)}),[]);return(0,u.S)((n=>{let{location:a}=n;e.current&&!a.hash&&"PUSH"===t&&f(e.current)})),{containerRef:e,onClick:n}}const m=(0,c.I)({id:"theme.common.skipToMainContent",description:"The skip to content label used for accessibility, allowing to rapidly navigate to main content with keyboard tab/enter navigation",message:"Skip to main content"});function g(e){const t=e.children??m,{containerRef:n,onClick:r}=p();return a.createElement("div",{ref:n,role:"region","aria-label":m},a.createElement("a",(0,i.Z)({},e,{href:`#${d}`,onClick:r}),t))}var h=n(5281),b=n(9727);const v={skipToContent:"skipToContent_fXgn"};function y(){return a.createElement(g,{className:v.skipToContent})}var x=n(6668),w=n(9689);function S(e){let{width:t=21,height:n=21,color:r="currentColor",strokeWidth:o=1.2,className:s,...l}=e;return a.createElement("svg",(0,i.Z)({viewBox:"0 0 15 15",width:t,height:n},l),a.createElement("g",{stroke:r,strokeWidth:o},a.createElement("path",{d:"M.75.75l13.5 13.5M14.25.75L.75 14.25"})))}const E={closeButton:"closeButton_CVFx"};function k(e){return a.createElement("button",(0,i.Z)({type:"button","aria-label":(0,c.I)({id:"theme.AnnouncementBar.closeButtonAriaLabel",message:"Close",description:"The ARIA label for close button of announcement bar"})},e,{className:(0,r.Z)("clean-btn close",E.closeButton,e.className)}),a.createElement(S,{width:14,height:14,strokeWidth:3.1}))}const _={content:"content_knG7"};function C(e){const{announcementBar:t}=(0,x.L)(),{content:n}=t;return a.createElement("div",(0,i.Z)({},e,{className:(0,r.Z)(_.content,e.className),dangerouslySetInnerHTML:{__html:n}}))}const q={announcementBar:"announcementBar_mb4j",announcementBarPlaceholder:"announcementBarPlaceholder_vyr4",announcementBarClose:"announcementBarClose_gvF7",announcementBarContent:"announcementBarContent_xLdY"};function T(){const{announcementBar:e}=(0,x.L)(),{isActive:t,close:n}=(0,w.nT)();if(!t)return null;const{backgroundColor:r,textColor:o,isCloseable:s}=e;return a.createElement("div",{className:q.announcementBar,style:{backgroundColor:r,color:o},role:"banner"},s&&a.createElement("div",{className:q.announcementBarPlaceholder}),a.createElement(C,{className:q.announcementBarContent}),s&&a.createElement(k,{onClick:n,className:q.announcementBarClose}))}var A=n(2961),L=n(2466);var N=n(902),O=n(3102);const P=a.createContext(null);function I(e){let{children:t}=e;const n=function(){const e=(0,A.e)(),t=(0,O.HY)(),[n,r]=(0,a.useState)(!1),o=null!==t.component,s=(0,N.D9)(o);return(0,a.useEffect)((()=>{o&&!s&&r(!0)}),[o,s]),(0,a.useEffect)((()=>{o?e.shown||r(!0):r(!1)}),[e.shown,o]),(0,a.useMemo)((()=>[n,r]),[n])}();return a.createElement(P.Provider,{value:n},t)}function R(e){if(e.component){const t=e.component;return a.createElement(t,e.props)}}function M(){const e=(0,a.useContext)(P);if(!e)throw new N.i6("NavbarSecondaryMenuDisplayProvider");const[t,n]=e,r=(0,a.useCallback)((()=>n(!1)),[n]),o=(0,O.HY)();return(0,a.useMemo)((()=>({shown:t,hide:r,content:R(o)})),[r,o,t])}function D(e){let{header:t,primaryMenu:n,secondaryMenu:o}=e;const{shown:s}=M();return a.createElement("div",{className:"navbar-sidebar"},t,a.createElement("div",{className:(0,r.Z)("navbar-sidebar__items",{"navbar-sidebar__items--show-secondary":s})},a.createElement("div",{className:"navbar-sidebar__item menu"},n),a.createElement("div",{className:"navbar-sidebar__item menu"},o)))}var F=n(2949),B=n(2389);function j(e){return a.createElement("svg",(0,i.Z)({viewBox:"0 0 24 24",width:24,height:24},e),a.createElement("path",{fill:"currentColor",d:"M12,9c1.65,0,3,1.35,3,3s-1.35,3-3,3s-3-1.35-3-3S10.35,9,12,9 M12,7c-2.76,0-5,2.24-5,5s2.24,5,5,5s5-2.24,5-5 S14.76,7,12,7L12,7z M2,13l2,0c0.55,0,1-0.45,1-1s-0.45-1-1-1l-2,0c-0.55,0-1,0.45-1,1S1.45,13,2,13z M20,13l2,0c0.55,0,1-0.45,1-1 s-0.45-1-1-1l-2,0c-0.55,0-1,0.45-1,1S19.45,13,20,13z M11,2v2c0,0.55,0.45,1,1,1s1-0.45,1-1V2c0-0.55-0.45-1-1-1S11,1.45,11,2z M11,20v2c0,0.55,0.45,1,1,1s1-0.45,1-1v-2c0-0.55-0.45-1-1-1C11.45,19,11,19.45,11,20z M5.99,4.58c-0.39-0.39-1.03-0.39-1.41,0 c-0.39,0.39-0.39,1.03,0,1.41l1.06,1.06c0.39,0.39,1.03,0.39,1.41,0s0.39-1.03,0-1.41L5.99,4.58z M18.36,16.95 c-0.39-0.39-1.03-0.39-1.41,0c-0.39,0.39-0.39,1.03,0,1.41l1.06,1.06c0.39,0.39,1.03,0.39,1.41,0c0.39-0.39,0.39-1.03,0-1.41 L18.36,16.95z M19.42,5.99c0.39-0.39,0.39-1.03,0-1.41c-0.39-0.39-1.03-0.39-1.41,0l-1.06,1.06c-0.39,0.39-0.39,1.03,0,1.41 s1.03,0.39,1.41,0L19.42,5.99z M7.05,18.36c0.39-0.39,0.39-1.03,0-1.41c-0.39-0.39-1.03-0.39-1.41,0l-1.06,1.06 c-0.39,0.39-0.39,1.03,0,1.41s1.03,0.39,1.41,0L7.05,18.36z"}))}function z(e){return a.createElement("svg",(0,i.Z)({viewBox:"0 0 24 24",width:24,height:24},e),a.createElement("path",{fill:"currentColor",d:"M9.37,5.51C9.19,6.15,9.1,6.82,9.1,7.5c0,4.08,3.32,7.4,7.4,7.4c0.68,0,1.35-0.09,1.99-0.27C17.45,17.19,14.93,19,12,19 c-3.86,0-7-3.14-7-7C5,9.07,6.81,6.55,9.37,5.51z M12,3c-4.97,0-9,4.03-9,9s4.03,9,9,9s9-4.03,9-9c0-0.46-0.04-0.92-0.1-1.36 c-0.98,1.37-2.58,2.26-4.4,2.26c-2.98,0-5.4-2.42-5.4-5.4c0-1.81,0.89-3.42,2.26-4.4C12.92,3.04,12.46,3,12,3L12,3z"}))}const $={toggle:"toggle_vylO",toggleButton:"toggleButton_gllP",darkToggleIcon:"darkToggleIcon_wfgR",lightToggleIcon:"lightToggleIcon_pyhR",toggleButtonDisabled:"toggleButtonDisabled_aARS"};function U(e){let{className:t,buttonClassName:n,value:o,onChange:s}=e;const i=(0,B.Z)(),l=(0,c.I)({message:"Switch between dark and light mode (currently {mode})",id:"theme.colorToggle.ariaLabel",description:"The ARIA label for the navbar color mode toggle"},{mode:"dark"===o?(0,c.I)({message:"dark mode",id:"theme.colorToggle.ariaLabel.mode.dark",description:"The name for the dark color mode"}):(0,c.I)({message:"light mode",id:"theme.colorToggle.ariaLabel.mode.light",description:"The name for the light color mode"})});return a.createElement("div",{className:(0,r.Z)($.toggle,t)},a.createElement("button",{className:(0,r.Z)("clean-btn",$.toggleButton,!i&&$.toggleButtonDisabled,n),type:"button",onClick:()=>s("dark"===o?"light":"dark"),disabled:!i,title:l,"aria-label":l,"aria-live":"polite"},a.createElement(j,{className:(0,r.Z)($.toggleIcon,$.lightToggleIcon)}),a.createElement(z,{className:(0,r.Z)($.toggleIcon,$.darkToggleIcon)})))}const Z=a.memo(U),H={darkNavbarColorModeToggle:"darkNavbarColorModeToggle_X3D1"};function V(e){let{className:t}=e;const n=(0,x.L)().navbar.style,r=(0,x.L)().colorMode.disableSwitch,{colorMode:o,setColorMode:s}=(0,F.I)();return r?null:a.createElement(Z,{className:t,buttonClassName:"dark"===n?H.darkNavbarColorModeToggle:void 0,value:o,onChange:s})}var W=n(1327);function G(){return a.createElement(W.Z,{className:"navbar__brand",imageClassName:"navbar__logo",titleClassName:"navbar__title text--truncate"})}function Y(){const e=(0,A.e)();return a.createElement("button",{type:"button","aria-label":(0,c.I)({id:"theme.docs.sidebar.closeSidebarButtonAriaLabel",message:"Close navigation bar",description:"The ARIA label for close button of mobile sidebar"}),className:"clean-btn navbar-sidebar__close",onClick:()=>e.toggle()},a.createElement(S,{color:"var(--ifm-color-emphasis-600)"}))}function K(){return a.createElement("div",{className:"navbar-sidebar__brand"},a.createElement(G,null),a.createElement(V,{className:"margin-right--md"}),a.createElement(Y,null))}var Q=n(9960),X=n(4996),J=n(3919);function ee(e,t){return void 0!==e&&void 0!==t&&new RegExp(e,"gi").test(t)}var te=n(9471);function ne(e){let{activeBasePath:t,activeBaseRegex:n,to:r,href:o,label:s,html:l,isDropdownLink:c,prependBaseUrlToHref:u,...d}=e;const f=(0,X.Z)(r),p=(0,X.Z)(t),m=(0,X.Z)(o,{forcePrependBaseUrl:!0}),g=s&&o&&!(0,J.Z)(o),h=l?{dangerouslySetInnerHTML:{__html:l}}:{children:a.createElement(a.Fragment,null,s,g&&a.createElement(te.Z,c&&{width:12,height:12}))};return o?a.createElement(Q.Z,(0,i.Z)({href:u?m:o},d,h)):a.createElement(Q.Z,(0,i.Z)({to:f,isNavLink:!0},(t||n)&&{isActive:(e,t)=>n?ee(n,t.pathname):t.pathname.startsWith(p)},d,h))}function ae(e){let{className:t,isDropdownItem:n=!1,...o}=e;const s=a.createElement(ne,(0,i.Z)({className:(0,r.Z)(n?"dropdown__link":"navbar__item navbar__link",t),isDropdownLink:n},o));return n?a.createElement("li",null,s):s}function re(e){let{className:t,isDropdownItem:n,...o}=e;return a.createElement("li",{className:"menu__list-item"},a.createElement(ne,(0,i.Z)({className:(0,r.Z)("menu__link",t)},o)))}function oe(e){let{mobile:t=!1,position:n,...r}=e;const o=t?re:ae;return a.createElement(o,(0,i.Z)({},r,{activeClassName:r.activeClassName??(t?"menu__link--active":"navbar__link--active")}))}var se=n(6043),ie=n(8596),le=n(2263);function ce(e,t){return e.some((e=>function(e,t){return!!(0,ie.Mg)(e.to,t)||!!ee(e.activeBaseRegex,t)||!(!e.activeBasePath||!t.startsWith(e.activeBasePath))}(e,t)))}function ue(e){let{items:t,position:n,className:o,onClick:s,...l}=e;const c=(0,a.useRef)(null),[u,d]=(0,a.useState)(!1);return(0,a.useEffect)((()=>{const e=e=>{c.current&&!c.current.contains(e.target)&&d(!1)};return document.addEventListener("mousedown",e),document.addEventListener("touchstart",e),document.addEventListener("focusin",e),()=>{document.removeEventListener("mousedown",e),document.removeEventListener("touchstart",e),document.removeEventListener("focusin",e)}}),[c]),a.createElement("div",{ref:c,className:(0,r.Z)("navbar__item","dropdown","dropdown--hoverable",{"dropdown--right":"right"===n,"dropdown--show":u})},a.createElement(ne,(0,i.Z)({"aria-haspopup":"true","aria-expanded":u,role:"button",href:l.to?void 0:"#",className:(0,r.Z)("navbar__link",o)},l,{onClick:l.to?void 0:e=>e.preventDefault(),onKeyDown:e=>{"Enter"===e.key&&(e.preventDefault(),d(!u))}}),l.children??l.label),a.createElement("ul",{className:"dropdown__menu"},t.map(((e,t)=>a.createElement(ke,(0,i.Z)({isDropdownItem:!0,activeClassName:"dropdown__link--active"},e,{key:t}))))))}function de(e){let{items:t,className:n,position:o,onClick:s,...c}=e;const u=function(){const{siteConfig:{baseUrl:e}}=(0,le.Z)(),{pathname:t}=(0,l.TH)();return t.replace(e,"/")}(),d=ce(t,u),{collapsed:f,toggleCollapsed:p,setCollapsed:m}=(0,se.u)({initialState:()=>!d});return(0,a.useEffect)((()=>{d&&m(!d)}),[u,d,m]),a.createElement("li",{className:(0,r.Z)("menu__list-item",{"menu__list-item--collapsed":f})},a.createElement(ne,(0,i.Z)({role:"button",className:(0,r.Z)("menu__link menu__link--sublist menu__link--sublist-caret",n)},c,{onClick:e=>{e.preventDefault(),p()}}),c.children??c.label),a.createElement(se.z,{lazy:!0,as:"ul",className:"menu__list",collapsed:f},t.map(((e,t)=>a.createElement(ke,(0,i.Z)({mobile:!0,isDropdownItem:!0,onClick:s,activeClassName:"menu__link--active"},e,{key:t}))))))}function fe(e){let{mobile:t=!1,...n}=e;const r=t?de:ue;return a.createElement(r,n)}var pe=n(4711);function me(e){let{width:t=20,height:n=20,...r}=e;return a.createElement("svg",(0,i.Z)({viewBox:"0 0 24 24",width:t,height:n,"aria-hidden":!0},r),a.createElement("path",{fill:"currentColor",d:"M12.87 15.07l-2.54-2.51.03-.03c1.74-1.94 2.98-4.17 3.71-6.53H17V4h-7V2H8v2H1v1.99h11.17C11.5 7.92 10.44 9.75 9 11.35 8.07 10.32 7.3 9.19 6.69 8h-2c.73 1.63 1.73 3.17 2.98 4.56l-5.09 5.02L4 19l5-5 3.11 3.11.76-2.04zM18.5 10h-2L12 22h2l1.12-3h4.75L21 22h2l-4.5-12zm-2.62 7l1.62-4.33L19.12 17h-3.24z"}))}const ge="iconLanguage_nlXk";var he=n(1875);const be={searchBox:"searchBox_ZlJk"};function ve(e){let{children:t,className:n}=e;return a.createElement("div",{className:(0,r.Z)(n,be.searchBox)},t)}var ye=n(143),xe=n(2802);var we=n(373);const Se=e=>e.docs.find((t=>t.id===e.mainDocId));const Ee={default:oe,localeDropdown:function(e){let{mobile:t,dropdownItemsBefore:n,dropdownItemsAfter:r,...o}=e;const{i18n:{currentLocale:s,locales:u,localeConfigs:d}}=(0,le.Z)(),f=(0,pe.l)(),{search:p,hash:m}=(0,l.TH)(),g=[...n,...u.map((e=>{const n=`${`pathname://${f.createUrl({locale:e,fullyQualified:!1})}`}${p}${m}`;return{label:d[e].label,lang:d[e].htmlLang,to:n,target:"_self",autoAddBaseUrl:!1,className:e===s?t?"menu__link--active":"dropdown__link--active":""}})),...r],h=t?(0,c.I)({message:"Languages",id:"theme.navbar.mobileLanguageDropdown.label",description:"The label for the mobile language switcher dropdown"}):d[s].label;return a.createElement(fe,(0,i.Z)({},o,{mobile:t,label:a.createElement(a.Fragment,null,a.createElement(me,{className:ge}),h),items:g}))},search:function(e){let{mobile:t,className:n}=e;return t?null:a.createElement(ve,{className:n},a.createElement(he.Z,null))},dropdown:fe,html:function(e){let{value:t,className:n,mobile:o=!1,isDropdownItem:s=!1}=e;const i=s?"li":"div";return a.createElement(i,{className:(0,r.Z)({navbar__item:!o&&!s,"menu__list-item":o},n),dangerouslySetInnerHTML:{__html:t}})},doc:function(e){let{docId:t,label:n,docsPluginId:r,...o}=e;const{activeDoc:s}=(0,ye.Iw)(r),l=(0,xe.vY)(t,r);return null===l?null:a.createElement(oe,(0,i.Z)({exact:!0},o,{isActive:()=>s?.path===l.path||!!s?.sidebar&&s.sidebar===l.sidebar,label:n??l.id,to:l.path}))},docSidebar:function(e){let{sidebarId:t,label:n,docsPluginId:r,...o}=e;const{activeDoc:s}=(0,ye.Iw)(r),l=(0,xe.oz)(t,r).link;if(!l)throw new Error(`DocSidebarNavbarItem: Sidebar with ID "${t}" doesn't have anything to be linked to.`);return a.createElement(oe,(0,i.Z)({exact:!0},o,{isActive:()=>s?.sidebar===t,label:n??l.label,to:l.path}))},docsVersion:function(e){let{label:t,to:n,docsPluginId:r,...o}=e;const s=(0,xe.lO)(r)[0],l=t??s.label,c=n??(e=>e.docs.find((t=>t.id===e.mainDocId)))(s).path;return a.createElement(oe,(0,i.Z)({},o,{label:l,to:c}))},docsVersionDropdown:function(e){let{mobile:t,docsPluginId:n,dropdownActiveClassDisabled:r,dropdownItemsBefore:o,dropdownItemsAfter:s,...u}=e;const{search:d,hash:f}=(0,l.TH)(),p=(0,ye.Iw)(n),m=(0,ye.gB)(n),{savePreferredVersionName:g}=(0,we.J)(n),h=[...o,...m.map((e=>{const t=p.alternateDocVersions[e.name]??Se(e);return{label:e.label,to:`${t.path}${d}${f}`,isActive:()=>e===p.activeVersion,onClick:()=>g(e.name)}})),...s],b=(0,xe.lO)(n)[0],v=t&&h.length>1?(0,c.I)({id:"theme.navbar.mobileVersionsDropdown.label",message:"Versions",description:"The label for the navbar versions dropdown on mobile view"}):b.label,y=t&&h.length>1?void 0:Se(b).path;return h.length<=1?a.createElement(oe,(0,i.Z)({},u,{mobile:t,label:v,to:y,isActive:r?()=>!1:void 0})):a.createElement(fe,(0,i.Z)({},u,{mobile:t,label:v,to:y,items:h,isActive:r?()=>!1:void 0}))}};function ke(e){let{type:t,...n}=e;const r=function(e,t){return e&&"default"!==e?e:"items"in t?"dropdown":"default"}(t,n),o=Ee[r];if(!o)throw new Error(`No NavbarItem component found for type "${t}".`);return a.createElement(o,n)}function _e(){const e=(0,A.e)(),t=(0,x.L)().navbar.items;return a.createElement("ul",{className:"menu__list"},t.map(((t,n)=>a.createElement(ke,(0,i.Z)({mobile:!0},t,{onClick:()=>e.toggle(),key:n})))))}function Ce(e){return a.createElement("button",(0,i.Z)({},e,{type:"button",className:"clean-btn navbar-sidebar__back"}),a.createElement(c.Z,{id:"theme.navbar.mobileSidebarSecondaryMenu.backButtonLabel",description:"The label of the back button to return to main menu, inside the mobile navbar sidebar secondary menu (notably used to display the docs sidebar)"},"\u2190 Back to main menu"))}function qe(){const e=0===(0,x.L)().navbar.items.length,t=M();return a.createElement(a.Fragment,null,!e&&a.createElement(Ce,{onClick:()=>t.hide()}),t.content)}function Te(){const e=(0,A.e)();var t;return void 0===(t=e.shown)&&(t=!0),(0,a.useEffect)((()=>(document.body.style.overflow=t?"hidden":"visible",()=>{document.body.style.overflow="visible"})),[t]),e.shouldRender?a.createElement(D,{header:a.createElement(K,null),primaryMenu:a.createElement(_e,null),secondaryMenu:a.createElement(qe,null)}):null}const Ae={navbarHideable:"navbarHideable_m1mJ",navbarHidden:"navbarHidden_jGov"};function Le(e){return a.createElement("div",(0,i.Z)({role:"presentation"},e,{className:(0,r.Z)("navbar-sidebar__backdrop",e.className)}))}function Ne(e){let{children:t}=e;const{navbar:{hideOnScroll:n,style:o}}=(0,x.L)(),s=(0,A.e)(),{navbarRef:i,isNavbarVisible:l}=function(e){const[t,n]=(0,a.useState)(e),r=(0,a.useRef)(!1),o=(0,a.useRef)(0),s=(0,a.useCallback)((e=>{null!==e&&(o.current=e.getBoundingClientRect().height)}),[]);return(0,L.RF)(((t,a)=>{let{scrollY:s}=t;if(!e)return;if(s<o.current)return void n(!0);if(r.current)return void(r.current=!1);const i=a?.scrollY,l=document.documentElement.scrollHeight-o.current,c=window.innerHeight;i&&s>=i?n(!1):s+c<l&&n(!0)})),(0,u.S)((t=>{if(!e)return;const a=t.location.hash;if(a?document.getElementById(a.substring(1)):void 0)return r.current=!0,void n(!1);n(!0)})),{navbarRef:s,isNavbarVisible:t}}(n);return a.createElement("nav",{ref:i,"aria-label":(0,c.I)({id:"theme.NavBar.navAriaLabel",message:"Main",description:"The ARIA label for the main navigation"}),className:(0,r.Z)("navbar","navbar--fixed-top",n&&[Ae.navbarHideable,!l&&Ae.navbarHidden],{"navbar--dark":"dark"===o,"navbar--primary":"primary"===o,"navbar-sidebar--show":s.shown})},t,a.createElement(Le,{onClick:s.toggle}),a.createElement(Te,null))}var Oe=n(8780);const Pe={errorBoundaryError:"errorBoundaryError_a6uf"};function Ie(e){return a.createElement("button",(0,i.Z)({type:"button"},e),a.createElement(c.Z,{id:"theme.ErrorPageContent.tryAgain",description:"The label of the button to try again rendering when the React error boundary captures an error"},"Try again"))}function Re(e){let{error:t}=e;const n=(0,Oe.getErrorCausalChain)(t).map((e=>e.message)).join("\n\nCause:\n");return a.createElement("p",{className:Pe.errorBoundaryError},n)}class Me extends a.Component{componentDidCatch(e,t){throw this.props.onError(e,t)}render(){return this.props.children}}const De="right";function Fe(e){let{width:t=30,height:n=30,className:r,...o}=e;return a.createElement("svg",(0,i.Z)({className:r,width:t,height:n,viewBox:"0 0 30 30","aria-hidden":"true"},o),a.createElement("path",{stroke:"currentColor",strokeLinecap:"round",strokeMiterlimit:"10",strokeWidth:"2",d:"M4 7h22M4 15h22M4 23h22"}))}function Be(){const{toggle:e,shown:t}=(0,A.e)();return a.createElement("button",{onClick:e,"aria-label":(0,c.I)({id:"theme.docs.sidebar.toggleSidebarButtonAriaLabel",message:"Toggle navigation bar",description:"The ARIA label for hamburger menu button of mobile navigation"}),"aria-expanded":t,className:"navbar__toggle clean-btn",type:"button"},a.createElement(Fe,null))}const je={colorModeToggle:"colorModeToggle_DEke"};function ze(e){let{items:t}=e;return a.createElement(a.Fragment,null,t.map(((e,t)=>a.createElement(Me,{key:t,onError:t=>new Error(`A theme navbar item failed to render.\nPlease double-check the following navbar item (themeConfig.navbar.items) of your Docusaurus config:\n${JSON.stringify(e,null,2)}`,{cause:t})},a.createElement(ke,e)))))}function $e(e){let{left:t,right:n}=e;return a.createElement("div",{className:"navbar__inner"},a.createElement("div",{className:"navbar__items"},t),a.createElement("div",{className:"navbar__items navbar__items--right"},n))}function Ue(){const e=(0,A.e)(),t=(0,x.L)().navbar.items,[n,r]=function(e){function t(e){return"left"===(e.position??De)}return[e.filter(t),e.filter((e=>!t(e)))]}(t),o=t.find((e=>"search"===e.type));return a.createElement($e,{left:a.createElement(a.Fragment,null,!e.disabled&&a.createElement(Be,null),a.createElement(G,null),a.createElement(ze,{items:n})),right:a.createElement(a.Fragment,null,a.createElement(ze,{items:r}),a.createElement(V,{className:je.colorModeToggle}),!o&&a.createElement(ve,null,a.createElement(he.Z,null)))})}function Ze(){return a.createElement(Ne,null,a.createElement(Ue,null))}function He(e){let{item:t}=e;const{to:n,href:r,label:o,prependBaseUrlToHref:s,...l}=t,c=(0,X.Z)(n),u=(0,X.Z)(r,{forcePrependBaseUrl:!0});return a.createElement(Q.Z,(0,i.Z)({className:"footer__link-item"},r?{href:s?u:r}:{to:c},l),o,r&&!(0,J.Z)(r)&&a.createElement(te.Z,null))}function Ve(e){let{item:t}=e;return t.html?a.createElement("li",{className:"footer__item",dangerouslySetInnerHTML:{__html:t.html}}):a.createElement("li",{key:t.href??t.to,className:"footer__item"},a.createElement(He,{item:t}))}function We(e){let{column:t}=e;return a.createElement("div",{className:"col footer__col"},a.createElement("div",{className:"footer__title"},t.title),a.createElement("ul",{className:"footer__items clean-list"},t.items.map(((e,t)=>a.createElement(Ve,{key:t,item:e})))))}function Ge(e){let{columns:t}=e;return a.createElement("div",{className:"row footer__links"},t.map(((e,t)=>a.createElement(We,{key:t,column:e}))))}function Ye(){return a.createElement("span",{className:"footer__link-separator"},"\xb7")}function Ke(e){let{item:t}=e;return t.html?a.createElement("span",{className:"footer__link-item",dangerouslySetInnerHTML:{__html:t.html}}):a.createElement(He,{item:t})}function Qe(e){let{links:t}=e;return a.createElement("div",{className:"footer__links text--center"},a.createElement("div",{className:"footer__links"},t.map(((e,n)=>a.createElement(a.Fragment,{key:n},a.createElement(Ke,{item:e}),t.length!==n+1&&a.createElement(Ye,null))))))}function Xe(e){let{links:t}=e;return function(e){return"title"in e[0]}(t)?a.createElement(Ge,{columns:t}):a.createElement(Qe,{links:t})}var Je=n(941);const et={footerLogoLink:"footerLogoLink_BH7S"};function tt(e){let{logo:t}=e;const{withBaseUrl:n}=(0,X.C)(),o={light:n(t.src),dark:n(t.srcDark??t.src)};return a.createElement(Je.Z,{className:(0,r.Z)("footer__logo",t.className),alt:t.alt,sources:o,width:t.width,height:t.height,style:t.style})}function nt(e){let{logo:t}=e;return t.href?a.createElement(Q.Z,{href:t.href,className:et.footerLogoLink,target:t.target},a.createElement(tt,{logo:t})):a.createElement(tt,{logo:t})}function at(e){let{copyright:t}=e;return a.createElement("div",{className:"footer__copyright",dangerouslySetInnerHTML:{__html:t}})}function rt(e){let{style:t,links:n,logo:o,copyright:s}=e;return a.createElement("footer",{className:(0,r.Z)("footer",{"footer--dark":"dark"===t})},a.createElement("div",{className:"container container-fluid"},n,(o||s)&&a.createElement("div",{className:"footer__bottom text--center"},o&&a.createElement("div",{className:"margin-bottom--sm"},o),s)))}function ot(){const{footer:e}=(0,x.L)();if(!e)return null;const{copyright:t,links:n,logo:r,style:o}=e;return a.createElement(rt,{style:o,links:n&&n.length>0&&a.createElement(Xe,{links:n}),logo:r&&a.createElement(nt,{logo:r}),copyright:t&&a.createElement(at,{copyright:t})})}const st=a.memo(ot),it=(0,N.Qc)([F.S,w.pl,L.OC,we.L5,s.VC,function(e){let{children:t}=e;return a.createElement(O.n2,null,a.createElement(A.M,null,a.createElement(I,null,t)))}]);function lt(e){let{children:t}=e;return a.createElement(it,null,t)}function ct(e){let{error:t,tryAgain:n}=e;return a.createElement("main",{className:"container margin-vert--xl"},a.createElement("div",{className:"row"},a.createElement("div",{className:"col col--6 col--offset-3"},a.createElement("h1",{className:"hero__title"},a.createElement(c.Z,{id:"theme.ErrorPageContent.title",description:"The title of the fallback page when the page crashed"},"This page crashed.")),a.createElement("div",{className:"margin-vert--lg"},a.createElement(Ie,{onClick:n,className:"button button--primary shadow--lw"})),a.createElement("hr",null),a.createElement("div",{className:"margin-vert--md"},a.createElement(Re,{error:t})))))}const ut={mainWrapper:"mainWrapper_z2l0"};function dt(e){const{children:t,noFooter:n,wrapperClassName:i,title:l,description:c}=e;return(0,b.t)(),a.createElement(lt,null,a.createElement(s.d,{title:l,description:c}),a.createElement(y,null),a.createElement(T,null),a.createElement(Ze,null),a.createElement("div",{id:d,className:(0,r.Z)(h.k.wrapper.main,ut.mainWrapper,i)},a.createElement(o.Z,{fallback:e=>a.createElement(ct,e)},t)),!n&&a.createElement(st,null))}},1327:(e,t,n)=>{"use strict";n.d(t,{Z:()=>d});var a=n(7462),r=n(7294),o=n(9960),s=n(4996),i=n(2263),l=n(6668),c=n(941);function u(e){let{logo:t,alt:n,imageClassName:a}=e;const o={light:(0,s.Z)(t.src),dark:(0,s.Z)(t.srcDark||t.src)},i=r.createElement(c.Z,{className:t.className,sources:o,height:t.height,width:t.width,alt:n,style:t.style});return a?r.createElement("div",{className:a},i):i}function d(e){const{siteConfig:{title:t}}=(0,i.Z)(),{navbar:{title:n,logo:c}}=(0,l.L)(),{imageClassName:d,titleClassName:f,...p}=e,m=(0,s.Z)(c?.href||"/"),g=n?"":t,h=c?.alt??g;return r.createElement(o.Z,(0,a.Z)({to:m},p,c?.target&&{target:c.target}),c&&r.createElement(u,{logo:c,alt:h,imageClassName:d}),null!=n&&r.createElement("b",{className:f},n))}},197:(e,t,n)=>{"use strict";n.d(t,{Z:()=>o});var a=n(7294),r=n(5742);function o(e){let{locale:t,version:n,tag:o}=e;const s=t;return a.createElement(r.Z,null,t&&a.createElement("meta",{name:"docusaurus_locale",content:t}),n&&a.createElement("meta",{name:"docusaurus_version",content:n}),o&&a.createElement("meta",{name:"docusaurus_tag",content:o}),s&&a.createElement("meta",{name:"docsearch:language",content:s}),n&&a.createElement("meta",{name:"docsearch:version",content:n}),o&&a.createElement("meta",{name:"docsearch:docusaurus_tag",content:o}))}},941:(e,t,n)=>{"use strict";n.d(t,{Z:()=>c});var a=n(7462),r=n(7294),o=n(6010),s=n(2389),i=n(2949);const l={themedImage:"themedImage_ToTc","themedImage--light":"themedImage--light_HNdA","themedImage--dark":"themedImage--dark_i4oU"};function c(e){const t=(0,s.Z)(),{colorMode:n}=(0,i.I)(),{sources:c,className:u,alt:d,...f}=e,p=t?"dark"===n?["dark"]:["light"]:["light","dark"];return r.createElement(r.Fragment,null,p.map((e=>r.createElement("img",(0,a.Z)({key:e,src:c[e],alt:d,className:(0,o.Z)(l.themedImage,l[`themedImage--${e}`],u)},f)))))}},6043:(e,t,n)=>{"use strict";n.d(t,{u:()=>l,z:()=>h});var a=n(7462),r=n(7294),o=n(412),s=n(1442);const i="ease-in-out";function l(e){let{initialState:t}=e;const[n,a]=(0,r.useState)(t??!1),o=(0,r.useCallback)((()=>{a((e=>!e))}),[]);return{collapsed:n,setCollapsed:a,toggleCollapsed:o}}const c={display:"none",overflow:"hidden",height:"0px"},u={display:"block",overflow:"visible",height:"auto"};function d(e,t){const n=t?c:u;e.style.display=n.display,e.style.overflow=n.overflow,e.style.height=n.height}function f(e){let{collapsibleRef:t,collapsed:n,animation:a}=e;const o=(0,r.useRef)(!1);(0,r.useEffect)((()=>{const e=t.current;function r(){const t=e.scrollHeight,n=a?.duration??function(e){if((0,s.n)())return 1;const t=e/36;return Math.round(10*(4+15*t**.25+t/5))}(t);return{transition:`height ${n}ms ${a?.easing??i}`,height:`${t}px`}}function l(){const t=r();e.style.transition=t.transition,e.style.height=t.height}if(!o.current)return d(e,n),void(o.current=!0);return e.style.willChange="height",function(){const t=requestAnimationFrame((()=>{n?(l(),requestAnimationFrame((()=>{e.style.height=c.height,e.style.overflow=c.overflow}))):(e.style.display="block",requestAnimationFrame((()=>{l()})))}));return()=>cancelAnimationFrame(t)}()}),[t,n,a])}function p(e){if(!o.Z.canUseDOM)return e?c:u}function m(e){let{as:t="div",collapsed:n,children:a,animation:o,onCollapseTransitionEnd:s,className:i,disableSSRStyle:l}=e;const c=(0,r.useRef)(null);return f({collapsibleRef:c,collapsed:n,animation:o}),r.createElement(t,{ref:c,style:l?void 0:p(n),onTransitionEnd:e=>{"height"===e.propertyName&&(d(c.current,n),s?.(n))},className:i},a)}function g(e){let{collapsed:t,...n}=e;const[o,s]=(0,r.useState)(!t),[i,l]=(0,r.useState)(t);return(0,r.useLayoutEffect)((()=>{t||s(!0)}),[t]),(0,r.useLayoutEffect)((()=>{o&&l(t)}),[o,t]),o?r.createElement(m,(0,a.Z)({},n,{collapsed:i})):null}function h(e){let{lazy:t,...n}=e;const a=t?g:m;return r.createElement(a,n)}},9689:(e,t,n)=>{"use strict";n.d(t,{nT:()=>m,pl:()=>p});var a=n(7294),r=n(2389),o=n(12),s=n(902),i=n(6668);const l=(0,o.WA)("docusaurus.announcement.dismiss"),c=(0,o.WA)("docusaurus.announcement.id"),u=()=>"true"===l.get(),d=e=>l.set(String(e)),f=a.createContext(null);function p(e){let{children:t}=e;const n=function(){const{announcementBar:e}=(0,i.L)(),t=(0,r.Z)(),[n,o]=(0,a.useState)((()=>!!t&&u()));(0,a.useEffect)((()=>{o(u())}),[]);const s=(0,a.useCallback)((()=>{d(!0),o(!0)}),[]);return(0,a.useEffect)((()=>{if(!e)return;const{id:t}=e;let n=c.get();"annoucement-bar"===n&&(n="announcement-bar");const a=t!==n;c.set(t),a&&d(!1),!a&&u()||o(!1)}),[e]),(0,a.useMemo)((()=>({isActive:!!e&&!n,close:s})),[e,n,s])}();return a.createElement(f.Provider,{value:n},t)}function m(){const e=(0,a.useContext)(f);if(!e)throw new s.i6("AnnouncementBarProvider");return e}},2949:(e,t,n)=>{"use strict";n.d(t,{I:()=>h,S:()=>g});var a=n(7294),r=n(412),o=n(902),s=n(12),i=n(6668);const l=a.createContext(void 0),c="theme",u=(0,s.WA)(c),d={light:"light",dark:"dark"},f=e=>e===d.dark?d.dark:d.light,p=e=>r.Z.canUseDOM?f(document.documentElement.getAttribute("data-theme")):f(e),m=e=>{u.set(f(e))};function g(e){let{children:t}=e;const n=function(){const{colorMode:{defaultMode:e,disableSwitch:t,respectPrefersColorScheme:n}}=(0,i.L)(),[r,o]=(0,a.useState)(p(e));(0,a.useEffect)((()=>{t&&u.del()}),[t]);const s=(0,a.useCallback)((function(t,a){void 0===a&&(a={});const{persist:r=!0}=a;t?(o(t),r&&m(t)):(o(n?window.matchMedia("(prefers-color-scheme: dark)").matches?d.dark:d.light:e),u.del())}),[n,e]);(0,a.useEffect)((()=>{document.documentElement.setAttribute("data-theme",f(r))}),[r]),(0,a.useEffect)((()=>{if(t)return;const e=e=>{if(e.key!==c)return;const t=u.get();null!==t&&s(f(t))};return window.addEventListener("storage",e),()=>window.removeEventListener("storage",e)}),[t,s]);const l=(0,a.useRef)(!1);return(0,a.useEffect)((()=>{if(t&&!n)return;const e=window.matchMedia("(prefers-color-scheme: dark)"),a=()=>{window.matchMedia("print").matches||l.current?l.current=window.matchMedia("print").matches:s(null)};return e.addListener(a),()=>e.removeListener(a)}),[s,t,n]),(0,a.useMemo)((()=>({colorMode:r,setColorMode:s,get isDarkTheme(){return r===d.dark},setLightTheme(){s(d.light)},setDarkTheme(){s(d.dark)}})),[r,s])}();return a.createElement(l.Provider,{value:n},t)}function h(){const e=(0,a.useContext)(l);if(null==e)throw new o.i6("ColorModeProvider","Please see https://docusaurus.io/docs/api/themes/configuration#use-color-mode.");return e}},373:(e,t,n)=>{"use strict";n.d(t,{J:()=>v,L5:()=>h});var a=n(7294),r=n(143),o=n(9935),s=n(6668),i=n(2802),l=n(902),c=n(12);const u=e=>`docs-preferred-version-${e}`,d={save:(e,t,n)=>{(0,c.WA)(u(e),{persistence:t}).set(n)},read:(e,t)=>(0,c.WA)(u(e),{persistence:t}).get(),clear:(e,t)=>{(0,c.WA)(u(e),{persistence:t}).del()}},f=e=>Object.fromEntries(e.map((e=>[e,{preferredVersionName:null}])));const p=a.createContext(null);function m(){const e=(0,r._r)(),t=(0,s.L)().docs.versionPersistence,n=(0,a.useMemo)((()=>Object.keys(e)),[e]),[o,i]=(0,a.useState)((()=>f(n)));(0,a.useEffect)((()=>{i(function(e){let{pluginIds:t,versionPersistence:n,allDocsData:a}=e;function r(e){const t=d.read(e,n);return a[e].versions.some((e=>e.name===t))?{preferredVersionName:t}:(d.clear(e,n),{preferredVersionName:null})}return Object.fromEntries(t.map((e=>[e,r(e)])))}({allDocsData:e,versionPersistence:t,pluginIds:n}))}),[e,t,n]);return[o,(0,a.useMemo)((()=>({savePreferredVersion:function(e,n){d.save(e,t,n),i((t=>({...t,[e]:{preferredVersionName:n}})))}})),[t])]}function g(e){let{children:t}=e;const n=m();return a.createElement(p.Provider,{value:n},t)}function h(e){let{children:t}=e;return i.cE?a.createElement(g,null,t):a.createElement(a.Fragment,null,t)}function b(){const e=(0,a.useContext)(p);if(!e)throw new l.i6("DocsPreferredVersionContextProvider");return e}function v(e){void 0===e&&(e=o.m);const t=(0,r.zh)(e),[n,s]=b(),{preferredVersionName:i}=n[e];return{preferredVersion:t.versions.find((e=>e.name===i))??null,savePreferredVersionName:(0,a.useCallback)((t=>{s.savePreferredVersion(e,t)}),[s,e])}}},1116:(e,t,n)=>{"use strict";n.d(t,{V:()=>l,b:()=>i});var a=n(7294),r=n(902);const o=Symbol("EmptyContext"),s=a.createContext(o);function i(e){let{children:t,name:n,items:r}=e;const o=(0,a.useMemo)((()=>n&&r?{name:n,items:r}:null),[n,r]);return a.createElement(s.Provider,{value:o},t)}function l(){const e=(0,a.useContext)(s);if(e===o)throw new r.i6("DocsSidebarProvider");return e}},2961:(e,t,n)=>{"use strict";n.d(t,{M:()=>f,e:()=>p});var a=n(7294),r=n(3102),o=n(7524),s=n(6550),i=(n(1688),n(902));function l(e){!function(e){const t=(0,s.k6)(),n=(0,i.zX)(e);(0,a.useEffect)((()=>t.block(((e,t)=>n(e,t)))),[t,n])}(((t,n)=>{if("POP"===n)return e(t,n)}))}var c=n(6668);const u=a.createContext(void 0);function d(){const e=function(){const e=(0,r.HY)(),{items:t}=(0,c.L)().navbar;return 0===t.length&&!e.component}(),t=(0,o.i)(),n=!e&&"mobile"===t,[s,i]=(0,a.useState)(!1);l((()=>{if(s)return i(!1),!1}));const u=(0,a.useCallback)((()=>{i((e=>!e))}),[]);return(0,a.useEffect)((()=>{"desktop"===t&&i(!1)}),[t]),(0,a.useMemo)((()=>({disabled:e,shouldRender:n,toggle:u,shown:s})),[e,n,u,s])}function f(e){let{children:t}=e;const n=d();return a.createElement(u.Provider,{value:n},t)}function p(){const e=a.useContext(u);if(void 0===e)throw new i.i6("NavbarMobileSidebarProvider");return e}},3102:(e,t,n)=>{"use strict";n.d(t,{HY:()=>i,Zo:()=>l,n2:()=>s});var a=n(7294),r=n(902);const o=a.createContext(null);function s(e){let{children:t}=e;const n=(0,a.useState)({component:null,props:null});return a.createElement(o.Provider,{value:n},t)}function i(){const e=(0,a.useContext)(o);if(!e)throw new r.i6("NavbarSecondaryMenuContentProvider");return e[0]}function l(e){let{component:t,props:n}=e;const s=(0,a.useContext)(o);if(!s)throw new r.i6("NavbarSecondaryMenuContentProvider");const[,i]=s,l=(0,r.Ql)(n);return(0,a.useEffect)((()=>{i({component:t,props:l})}),[i,t,l]),(0,a.useEffect)((()=>()=>i({component:null,props:null})),[i]),null}},9727:(e,t,n)=>{"use strict";n.d(t,{h:()=>r,t:()=>o});var a=n(7294);const r="navigation-with-keyboard";function o(){(0,a.useEffect)((()=>{function e(e){"keydown"===e.type&&"Tab"===e.key&&document.body.classList.add(r),"mousedown"===e.type&&document.body.classList.remove(r)}return document.addEventListener("keydown",e),document.addEventListener("mousedown",e),()=>{document.body.classList.remove(r),document.removeEventListener("keydown",e),document.removeEventListener("mousedown",e)}}),[])}},7524:(e,t,n)=>{"use strict";n.d(t,{i:()=>c});var a=n(7294),r=n(412);const o={desktop:"desktop",mobile:"mobile",ssr:"ssr"},s=996;function i(){return r.Z.canUseDOM?window.innerWidth>s?o.desktop:o.mobile:o.ssr}const l=!1;function c(){const[e,t]=(0,a.useState)((()=>l?"ssr":i()));return(0,a.useEffect)((()=>{function e(){t(i())}const n=l?window.setTimeout(e,1e3):void 0;return window.addEventListener("resize",e),()=>{window.removeEventListener("resize",e),clearTimeout(n)}}),[]),e}},5281:(e,t,n)=>{"use strict";n.d(t,{k:()=>a});const a={page:{blogListPage:"blog-list-page",blogPostPage:"blog-post-page",blogTagsListPage:"blog-tags-list-page",blogTagPostListPage:"blog-tags-post-list-page",docsDocPage:"docs-doc-page",docsTagsListPage:"docs-tags-list-page",docsTagDocListPage:"docs-tags-doc-list-page",mdxPage:"mdx-page"},wrapper:{main:"main-wrapper",blogPages:"blog-wrapper",docsPages:"docs-wrapper",mdxPages:"mdx-wrapper"},common:{editThisPage:"theme-edit-this-page",lastUpdated:"theme-last-updated",backToTopButton:"theme-back-to-top-button",codeBlock:"theme-code-block",admonition:"theme-admonition",admonitionType:e=>`theme-admonition-${e}`},layout:{},docs:{docVersionBanner:"theme-doc-version-banner",docVersionBadge:"theme-doc-version-badge",docBreadcrumbs:"theme-doc-breadcrumbs",docMarkdown:"theme-doc-markdown",docTocMobile:"theme-doc-toc-mobile",docTocDesktop:"theme-doc-toc-desktop",docFooter:"theme-doc-footer",docFooterTagsRow:"theme-doc-footer-tags-row",docFooterEditMetaRow:"theme-doc-footer-edit-meta-row",docSidebarContainer:"theme-doc-sidebar-container",docSidebarMenu:"theme-doc-sidebar-menu",docSidebarItemCategory:"theme-doc-sidebar-item-category",docSidebarItemLink:"theme-doc-sidebar-item-link",docSidebarItemCategoryLevel:e=>`theme-doc-sidebar-item-category-level-${e}`,docSidebarItemLinkLevel:e=>`theme-doc-sidebar-item-link-level-${e}`},blog:{}}},1442:(e,t,n)=>{"use strict";function a(){return window.matchMedia("(prefers-reduced-motion: reduce)").matches}n.d(t,{n:()=>a})},2802:(e,t,n)=>{"use strict";n.d(t,{Wl:()=>f,_F:()=>g,cE:()=>d,hI:()=>w,lO:()=>v,vY:()=>x,oz:()=>y,s1:()=>b});var a=n(7294),r=n(6550),o=n(8790),s=n(143),i=n(373),l=n(1116);function c(e){return Array.from(new Set(e))}var u=n(8596);const d=!!s._r;function f(e){if(e.href)return e.href;for(const t of e.items){if("link"===t.type)return t.href;if("category"===t.type){const e=f(t);if(e)return e}}}const p=(e,t)=>void 0!==e&&(0,u.Mg)(e,t),m=(e,t)=>e.some((e=>g(e,t)));function g(e,t){return"link"===e.type?p(e.href,t):"category"===e.type&&(p(e.href,t)||m(e.items,t))}function h(e){let{sidebarItems:t,pathname:n,onlyCategories:a=!1}=e;const r=[];return function e(t){for(const o of t)if("category"===o.type&&((0,u.Mg)(o.href,n)||e(o.items))||"link"===o.type&&(0,u.Mg)(o.href,n)){return a&&"category"!==o.type||r.unshift(o),!0}return!1}(t),r}function b(){const e=(0,l.V)(),{pathname:t}=(0,r.TH)(),n=(0,s.gA)()?.pluginData.breadcrumbs;return!1!==n&&e?h({sidebarItems:e.items,pathname:t}):null}function v(e){const{activeVersion:t}=(0,s.Iw)(e),{preferredVersion:n}=(0,i.J)(e),r=(0,s.yW)(e);return(0,a.useMemo)((()=>c([t,n,r].filter(Boolean))),[t,n,r])}function y(e,t){const n=v(t);return(0,a.useMemo)((()=>{const t=n.flatMap((e=>e.sidebars?Object.entries(e.sidebars):[])),a=t.find((t=>t[0]===e));if(!a)throw new Error(`Can't find any sidebar with id "${e}" in version${n.length>1?"s":""} ${n.map((e=>e.name)).join(", ")}".\nAvailable sidebar ids are:\n- ${t.map((e=>e[0])).join("\n- ")}`);return a[1]}),[e,n])}function x(e,t){const n=v(t);return(0,a.useMemo)((()=>{const t=n.flatMap((e=>e.docs)),a=t.find((t=>t.id===e));if(!a){if(n.flatMap((e=>e.draftIds)).includes(e))return null;throw new Error(`Couldn't find any doc with id "${e}" in version${n.length>1?"s":""} "${n.map((e=>e.name)).join(", ")}".\nAvailable doc ids are:\n- ${c(t.map((e=>e.id))).join("\n- ")}`)}return a}),[e,n])}function w(e){let{route:t,versionMetadata:n}=e;const a=(0,r.TH)(),s=t.routes,i=s.find((e=>(0,r.LX)(a.pathname,e)));if(!i)return null;const l=i.sidebar,c=l?n.docsSidebars[l]:void 0;return{docElement:(0,o.H)(s),sidebarName:l,sidebarItems:c}}},1944:(e,t,n)=>{"use strict";n.d(t,{FG:()=>f,d:()=>u,VC:()=>p});var a=n(7294),r=n(6010),o=n(5742),s=n(226);function i(){const e=a.useContext(s._);if(!e)throw new Error("Unexpected: no Docusaurus route context found");return e}var l=n(4996),c=n(2263);function u(e){let{title:t,description:n,keywords:r,image:s,children:i}=e;const u=function(e){const{siteConfig:t}=(0,c.Z)(),{title:n,titleDelimiter:a}=t;return e?.trim().length?`${e.trim()} ${a} ${n}`:n}(t),{withBaseUrl:d}=(0,l.C)(),f=s?d(s,{absolute:!0}):void 0;return a.createElement(o.Z,null,t&&a.createElement("title",null,u),t&&a.createElement("meta",{property:"og:title",content:u}),n&&a.createElement("meta",{name:"description",content:n}),n&&a.createElement("meta",{property:"og:description",content:n}),r&&a.createElement("meta",{name:"keywords",content:Array.isArray(r)?r.join(","):r}),f&&a.createElement("meta",{property:"og:image",content:f}),f&&a.createElement("meta",{name:"twitter:image",content:f}),i)}const d=a.createContext(void 0);function f(e){let{className:t,children:n}=e;const s=a.useContext(d),i=(0,r.Z)(s,t);return a.createElement(d.Provider,{value:i},a.createElement(o.Z,null,a.createElement("html",{className:i})),n)}function p(e){let{children:t}=e;const n=i(),o=`plugin-${n.plugin.name.replace(/docusaurus-(?:plugin|theme)-(?:content-)?/gi,"")}`;const s=`plugin-id-${n.plugin.id}`;return a.createElement(f,{className:(0,r.Z)(o,s)},t)}},902:(e,t,n)=>{"use strict";n.d(t,{D9:()=>s,Qc:()=>c,Ql:()=>l,i6:()=>i,zX:()=>o});var a=n(7294);const r=n(412).Z.canUseDOM?a.useLayoutEffect:a.useEffect;function o(e){const t=(0,a.useRef)(e);return r((()=>{t.current=e}),[e]),(0,a.useCallback)((function(){return t.current(...arguments)}),[])}function s(e){const t=(0,a.useRef)();return r((()=>{t.current=e})),t.current}class i extends Error{constructor(e,t){super(),this.name="ReactContextError",this.message=`Hook ${this.stack?.split("\n")[1]?.match(/at (?:\w+\.)?(?<name>\w+)/)?.groups.name??""} is called outside the <${e}>. ${t??""}`}}function l(e){const t=Object.entries(e);return t.sort(((e,t)=>e[0].localeCompare(t[0]))),(0,a.useMemo)((()=>e),t.flat())}function c(e){return t=>{let{children:n}=t;return a.createElement(a.Fragment,null,e.reduceRight(((e,t)=>a.createElement(t,null,e)),n))}}},8596:(e,t,n)=>{"use strict";n.d(t,{Mg:()=>s,Ns:()=>i});var a=n(7294),r=n(723),o=n(2263);function s(e,t){const n=e=>(!e||e.endsWith("/")?e:`${e}/`)?.toLowerCase();return n(e)===n(t)}function i(){const{baseUrl:e}=(0,o.Z)().siteConfig;return(0,a.useMemo)((()=>function(e){let{baseUrl:t,routes:n}=e;function a(e){return e.path===t&&!0===e.exact}function r(e){return e.path===t&&!e.exact}return function e(t){if(0===t.length)return;return t.find(a)||e(t.filter(r).flatMap((e=>e.routes??[])))}(n)}({routes:r.Z,baseUrl:e})),[e])}},2466:(e,t,n)=>{"use strict";n.d(t,{Ct:()=>f,OC:()=>l,RF:()=>d});var a=n(7294),r=n(412),o=n(2389),s=n(902);const i=a.createContext(void 0);function l(e){let{children:t}=e;const n=function(){const e=(0,a.useRef)(!0);return(0,a.useMemo)((()=>({scrollEventsEnabledRef:e,enableScrollEvents:()=>{e.current=!0},disableScrollEvents:()=>{e.current=!1}})),[])}();return a.createElement(i.Provider,{value:n},t)}function c(){const e=(0,a.useContext)(i);if(null==e)throw new s.i6("ScrollControllerProvider");return e}const u=()=>r.Z.canUseDOM?{scrollX:window.pageXOffset,scrollY:window.pageYOffset}:null;function d(e,t){void 0===t&&(t=[]);const{scrollEventsEnabledRef:n}=c(),r=(0,a.useRef)(u()),o=(0,s.zX)(e);(0,a.useEffect)((()=>{const e=()=>{if(!n.current)return;const e=u();o(e,r.current),r.current=e},t={passive:!0};return e(),window.addEventListener("scroll",e,t),()=>window.removeEventListener("scroll",e,t)}),[o,n,...t])}function f(){const e=(0,a.useRef)(null),t=(0,o.Z)()&&"smooth"===getComputedStyle(document.documentElement).scrollBehavior;return{startScroll:n=>{e.current=t?function(e){return window.scrollTo({top:e,behavior:"smooth"}),()=>{}}(n):function(e){let t=null;const n=document.documentElement.scrollTop>e;return function a(){const r=document.documentElement.scrollTop;(n&&r>e||!n&&r<e)&&(t=requestAnimationFrame(a),window.scrollTo(0,Math.floor(.85*(r-e))+e))}(),()=>t&&cancelAnimationFrame(t)}(n)},cancelScroll:()=>e.current?.()}}},3320:(e,t,n)=>{"use strict";n.d(t,{HX:()=>a,os:()=>r});n(2263);const a="default";function r(e,t){return`docs-${e}-${t}`}},12:(e,t,n)=>{"use strict";n.d(t,{WA:()=>l});n(7294),n(1688);const a="localStorage";function r(e){let{key:t,oldValue:n,newValue:a,storage:r}=e;if(n===a)return;const o=document.createEvent("StorageEvent");o.initStorageEvent("storage",!1,!1,t,n,a,window.location.href,r),window.dispatchEvent(o)}function o(e){if(void 0===e&&(e=a),"undefined"==typeof window)throw new Error("Browser storage is not available on Node.js/Docusaurus SSR process.");if("none"===e)return null;try{return window[e]}catch(n){return t=n,s||(console.warn("Docusaurus browser storage is not available.\nPossible reasons: running Docusaurus in an iframe, in an incognito browser session, or using too strict browser privacy settings.",t),s=!0),null}var t}let s=!1;const i={get:()=>null,set:()=>{},del:()=>{},listen:()=>()=>{}};function l(e,t){if("undefined"==typeof window)return function(e){function t(){throw new Error(`Illegal storage API usage for storage key "${e}".\nDocusaurus storage APIs are not supposed to be called on the server-rendering process.\nPlease only call storage APIs in effects and event handlers.`)}return{get:t,set:t,del:t,listen:t}}(e);const n=o(t?.persistence);return null===n?i:{get:()=>{try{return n.getItem(e)}catch(t){return console.error(`Docusaurus storage error, can't get key=${e}`,t),null}},set:t=>{try{const a=n.getItem(e);n.setItem(e,t),r({key:e,oldValue:a,newValue:t,storage:n})}catch(a){console.error(`Docusaurus storage error, can't set ${e}=${t}`,a)}},del:()=>{try{const t=n.getItem(e);n.removeItem(e),r({key:e,oldValue:t,newValue:null,storage:n})}catch(t){console.error(`Docusaurus storage error, can't delete key=${e}`,t)}},listen:t=>{try{const a=a=>{a.storageArea===n&&a.key===e&&t(a)};return window.addEventListener("storage",a),()=>window.removeEventListener("storage",a)}catch(a){return console.error(`Docusaurus storage error, can't listen for changes of key=${e}`,a),()=>{}}}}}},4711:(e,t,n)=>{"use strict";n.d(t,{l:()=>s});var a=n(2263),r=n(6550),o=n(8780);function s(){const{siteConfig:{baseUrl:e,url:t,trailingSlash:n},i18n:{defaultLocale:s,currentLocale:i}}=(0,a.Z)(),{pathname:l}=(0,r.TH)(),c=(0,o.applyTrailingSlash)(l,{trailingSlash:n,baseUrl:e}),u=i===s?e:e.replace(`/${i}/`,"/"),d=c.replace(e,"");return{createUrl:function(e){let{locale:n,fullyQualified:a}=e;return`${a?t:""}${function(e){return e===s?`${u}`:`${u}${e}/`}(n)}${d}`}}}},5936:(e,t,n)=>{"use strict";n.d(t,{S:()=>s});var a=n(7294),r=n(6550),o=n(902);function s(e){const t=(0,r.TH)(),n=(0,o.D9)(t),s=(0,o.zX)(e);(0,a.useEffect)((()=>{n&&t!==n&&s({location:t,previousLocation:n})}),[s,t,n])}},6668:(e,t,n)=>{"use strict";n.d(t,{L:()=>r});var a=n(2263);function r(){return(0,a.Z)().siteConfig.themeConfig}},8802:(e,t)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(e,t){const{trailingSlash:n,baseUrl:a}=t;if(e.startsWith("#"))return e;if(void 0===n)return e;const[r]=e.split(/[#?]/),o="/"===r||r===a?r:(s=r,n?function(e){return e.endsWith("/")?e:`${e}/`}(s):function(e){return e.endsWith("/")?e.slice(0,-1):e}(s));var s;return e.replace(r,o)}},4143:(e,t)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.getErrorCausalChain=void 0,t.getErrorCausalChain=function e(t){return t.cause?[t,...e(t.cause)]:[t]}},8780:function(e,t,n){"use strict";var a=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.getErrorCausalChain=t.applyTrailingSlash=t.blogPostContainerID=void 0,t.blogPostContainerID="__blog-post-container";var r=n(8802);Object.defineProperty(t,"applyTrailingSlash",{enumerable:!0,get:function(){return a(r).default}});var o=n(4143);Object.defineProperty(t,"getErrorCausalChain",{enumerable:!0,get:function(){return o.getErrorCausalChain}})},6010:(e,t,n)=>{"use strict";function a(e){var t,n,r="";if("string"==typeof e||"number"==typeof e)r+=e;else if("object"==typeof e)if(Array.isArray(e))for(t=0;t<e.length;t++)e[t]&&(n=a(e[t]))&&(r&&(r+=" "),r+=n);else for(t in e)e[t]&&(r&&(r+=" "),r+=t);return r}n.d(t,{Z:()=>r});const r=function(){for(var e,t,n=0,r="";n<arguments.length;)(e=arguments[n++])&&(t=a(e))&&(r&&(r+=" "),r+=t);return r}},9318:(e,t,n)=>{"use strict";n.d(t,{lX:()=>x,q_:()=>C,ob:()=>p,PP:()=>T,Ep:()=>f});var a=n(7462);function r(e){return"/"===e.charAt(0)}function o(e,t){for(var n=t,a=n+1,r=e.length;a<r;n+=1,a+=1)e[n]=e[a];e.pop()}const s=function(e,t){void 0===t&&(t="");var n,a=e&&e.split("/")||[],s=t&&t.split("/")||[],i=e&&r(e),l=t&&r(t),c=i||l;if(e&&r(e)?s=a:a.length&&(s.pop(),s=s.concat(a)),!s.length)return"/";if(s.length){var u=s[s.length-1];n="."===u||".."===u||""===u}else n=!1;for(var d=0,f=s.length;f>=0;f--){var p=s[f];"."===p?o(s,f):".."===p?(o(s,f),d++):d&&(o(s,f),d--)}if(!c)for(;d--;d)s.unshift("..");!c||""===s[0]||s[0]&&r(s[0])||s.unshift("");var m=s.join("/");return n&&"/"!==m.substr(-1)&&(m+="/"),m};var i=n(8776);function l(e){return"/"===e.charAt(0)?e:"/"+e}function c(e){return"/"===e.charAt(0)?e.substr(1):e}function u(e,t){return function(e,t){return 0===e.toLowerCase().indexOf(t.toLowerCase())&&-1!=="/?#".indexOf(e.charAt(t.length))}(e,t)?e.substr(t.length):e}function d(e){return"/"===e.charAt(e.length-1)?e.slice(0,-1):e}function f(e){var t=e.pathname,n=e.search,a=e.hash,r=t||"/";return n&&"?"!==n&&(r+="?"===n.charAt(0)?n:"?"+n),a&&"#"!==a&&(r+="#"===a.charAt(0)?a:"#"+a),r}function p(e,t,n,r){var o;"string"==typeof e?(o=function(e){var t=e||"/",n="",a="",r=t.indexOf("#");-1!==r&&(a=t.substr(r),t=t.substr(0,r));var o=t.indexOf("?");return-1!==o&&(n=t.substr(o),t=t.substr(0,o)),{pathname:t,search:"?"===n?"":n,hash:"#"===a?"":a}}(e),o.state=t):(void 0===(o=(0,a.Z)({},e)).pathname&&(o.pathname=""),o.search?"?"!==o.search.charAt(0)&&(o.search="?"+o.search):o.search="",o.hash?"#"!==o.hash.charAt(0)&&(o.hash="#"+o.hash):o.hash="",void 0!==t&&void 0===o.state&&(o.state=t));try{o.pathname=decodeURI(o.pathname)}catch(i){throw i instanceof URIError?new URIError('Pathname "'+o.pathname+'" could not be decoded. This is likely caused by an invalid percent-encoding.'):i}return n&&(o.key=n),r?o.pathname?"/"!==o.pathname.charAt(0)&&(o.pathname=s(o.pathname,r.pathname)):o.pathname=r.pathname:o.pathname||(o.pathname="/"),o}function m(){var e=null;var t=[];return{setPrompt:function(t){return e=t,function(){e===t&&(e=null)}},confirmTransitionTo:function(t,n,a,r){if(null!=e){var o="function"==typeof e?e(t,n):e;"string"==typeof o?"function"==typeof a?a(o,r):r(!0):r(!1!==o)}else r(!0)},appendListener:function(e){var n=!0;function a(){n&&e.apply(void 0,arguments)}return t.push(a),function(){n=!1,t=t.filter((function(e){return e!==a}))}},notifyListeners:function(){for(var e=arguments.length,n=new Array(e),a=0;a<e;a++)n[a]=arguments[a];t.forEach((function(e){return e.apply(void 0,n)}))}}}var g=!("undefined"==typeof window||!window.document||!window.document.createElement);function h(e,t){t(window.confirm(e))}var b="popstate",v="hashchange";function y(){try{return window.history.state||{}}catch(e){return{}}}function x(e){void 0===e&&(e={}),g||(0,i.Z)(!1);var t,n=window.history,r=(-1===(t=window.navigator.userAgent).indexOf("Android 2.")&&-1===t.indexOf("Android 4.0")||-1===t.indexOf("Mobile Safari")||-1!==t.indexOf("Chrome")||-1!==t.indexOf("Windows Phone"))&&window.history&&"pushState"in window.history,o=!(-1===window.navigator.userAgent.indexOf("Trident")),s=e,c=s.forceRefresh,x=void 0!==c&&c,w=s.getUserConfirmation,S=void 0===w?h:w,E=s.keyLength,k=void 0===E?6:E,_=e.basename?d(l(e.basename)):"";function C(e){var t=e||{},n=t.key,a=t.state,r=window.location,o=r.pathname+r.search+r.hash;return _&&(o=u(o,_)),p(o,a,n)}function q(){return Math.random().toString(36).substr(2,k)}var T=m();function A(e){(0,a.Z)(z,e),z.length=n.length,T.notifyListeners(z.location,z.action)}function L(e){(function(e){return void 0===e.state&&-1===navigator.userAgent.indexOf("CriOS")})(e)||P(C(e.state))}function N(){P(C(y()))}var O=!1;function P(e){if(O)O=!1,A();else{T.confirmTransitionTo(e,"POP",S,(function(t){t?A({action:"POP",location:e}):function(e){var t=z.location,n=R.indexOf(t.key);-1===n&&(n=0);var a=R.indexOf(e.key);-1===a&&(a=0);var r=n-a;r&&(O=!0,D(r))}(e)}))}}var I=C(y()),R=[I.key];function M(e){return _+f(e)}function D(e){n.go(e)}var F=0;function B(e){1===(F+=e)&&1===e?(window.addEventListener(b,L),o&&window.addEventListener(v,N)):0===F&&(window.removeEventListener(b,L),o&&window.removeEventListener(v,N))}var j=!1;var z={length:n.length,action:"POP",location:I,createHref:M,push:function(e,t){var a="PUSH",o=p(e,t,q(),z.location);T.confirmTransitionTo(o,a,S,(function(e){if(e){var t=M(o),s=o.key,i=o.state;if(r)if(n.pushState({key:s,state:i},null,t),x)window.location.href=t;else{var l=R.indexOf(z.location.key),c=R.slice(0,l+1);c.push(o.key),R=c,A({action:a,location:o})}else window.location.href=t}}))},replace:function(e,t){var a="REPLACE",o=p(e,t,q(),z.location);T.confirmTransitionTo(o,a,S,(function(e){if(e){var t=M(o),s=o.key,i=o.state;if(r)if(n.replaceState({key:s,state:i},null,t),x)window.location.replace(t);else{var l=R.indexOf(z.location.key);-1!==l&&(R[l]=o.key),A({action:a,location:o})}else window.location.replace(t)}}))},go:D,goBack:function(){D(-1)},goForward:function(){D(1)},block:function(e){void 0===e&&(e=!1);var t=T.setPrompt(e);return j||(B(1),j=!0),function(){return j&&(j=!1,B(-1)),t()}},listen:function(e){var t=T.appendListener(e);return B(1),function(){B(-1),t()}}};return z}var w="hashchange",S={hashbang:{encodePath:function(e){return"!"===e.charAt(0)?e:"!/"+c(e)},decodePath:function(e){return"!"===e.charAt(0)?e.substr(1):e}},noslash:{encodePath:c,decodePath:l},slash:{encodePath:l,decodePath:l}};function E(e){var t=e.indexOf("#");return-1===t?e:e.slice(0,t)}function k(){var e=window.location.href,t=e.indexOf("#");return-1===t?"":e.substring(t+1)}function _(e){window.location.replace(E(window.location.href)+"#"+e)}function C(e){void 0===e&&(e={}),g||(0,i.Z)(!1);var t=window.history,n=(window.navigator.userAgent.indexOf("Firefox"),e),r=n.getUserConfirmation,o=void 0===r?h:r,s=n.hashType,c=void 0===s?"slash":s,b=e.basename?d(l(e.basename)):"",v=S[c],y=v.encodePath,x=v.decodePath;function C(){var e=x(k());return b&&(e=u(e,b)),p(e)}var q=m();function T(e){(0,a.Z)(j,e),j.length=t.length,q.notifyListeners(j.location,j.action)}var A=!1,L=null;function N(){var e,t,n=k(),a=y(n);if(n!==a)_(a);else{var r=C(),s=j.location;if(!A&&(t=r,(e=s).pathname===t.pathname&&e.search===t.search&&e.hash===t.hash))return;if(L===f(r))return;L=null,function(e){if(A)A=!1,T();else{var t="POP";q.confirmTransitionTo(e,t,o,(function(n){n?T({action:t,location:e}):function(e){var t=j.location,n=R.lastIndexOf(f(t));-1===n&&(n=0);var a=R.lastIndexOf(f(e));-1===a&&(a=0);var r=n-a;r&&(A=!0,M(r))}(e)}))}}(r)}}var O=k(),P=y(O);O!==P&&_(P);var I=C(),R=[f(I)];function M(e){t.go(e)}var D=0;function F(e){1===(D+=e)&&1===e?window.addEventListener(w,N):0===D&&window.removeEventListener(w,N)}var B=!1;var j={length:t.length,action:"POP",location:I,createHref:function(e){var t=document.querySelector("base"),n="";return t&&t.getAttribute("href")&&(n=E(window.location.href)),n+"#"+y(b+f(e))},push:function(e,t){var n="PUSH",a=p(e,void 0,void 0,j.location);q.confirmTransitionTo(a,n,o,(function(e){if(e){var t=f(a),r=y(b+t);if(k()!==r){L=t,function(e){window.location.hash=e}(r);var o=R.lastIndexOf(f(j.location)),s=R.slice(0,o+1);s.push(t),R=s,T({action:n,location:a})}else T()}}))},replace:function(e,t){var n="REPLACE",a=p(e,void 0,void 0,j.location);q.confirmTransitionTo(a,n,o,(function(e){if(e){var t=f(a),r=y(b+t);k()!==r&&(L=t,_(r));var o=R.indexOf(f(j.location));-1!==o&&(R[o]=t),T({action:n,location:a})}}))},go:M,goBack:function(){M(-1)},goForward:function(){M(1)},block:function(e){void 0===e&&(e=!1);var t=q.setPrompt(e);return B||(F(1),B=!0),function(){return B&&(B=!1,F(-1)),t()}},listen:function(e){var t=q.appendListener(e);return F(1),function(){F(-1),t()}}};return j}function q(e,t,n){return Math.min(Math.max(e,t),n)}function T(e){void 0===e&&(e={});var t=e,n=t.getUserConfirmation,r=t.initialEntries,o=void 0===r?["/"]:r,s=t.initialIndex,i=void 0===s?0:s,l=t.keyLength,c=void 0===l?6:l,u=m();function d(e){(0,a.Z)(x,e),x.length=x.entries.length,u.notifyListeners(x.location,x.action)}function g(){return Math.random().toString(36).substr(2,c)}var h=q(i,0,o.length-1),b=o.map((function(e){return p(e,void 0,"string"==typeof e?g():e.key||g())})),v=f;function y(e){var t=q(x.index+e,0,x.entries.length-1),a=x.entries[t];u.confirmTransitionTo(a,"POP",n,(function(e){e?d({action:"POP",location:a,index:t}):d()}))}var x={length:b.length,action:"POP",location:b[h],index:h,entries:b,createHref:v,push:function(e,t){var a="PUSH",r=p(e,t,g(),x.location);u.confirmTransitionTo(r,a,n,(function(e){if(e){var t=x.index+1,n=x.entries.slice(0);n.length>t?n.splice(t,n.length-t,r):n.push(r),d({action:a,location:r,index:t,entries:n})}}))},replace:function(e,t){var a="REPLACE",r=p(e,t,g(),x.location);u.confirmTransitionTo(r,a,n,(function(e){e&&(x.entries[x.index]=r,d({action:a,location:r}))}))},go:y,goBack:function(){y(-1)},goForward:function(){y(1)},canGo:function(e){var t=x.index+e;return t>=0&&t<x.entries.length},block:function(e){return void 0===e&&(e=!1),u.setPrompt(e)},listen:function(e){return u.appendListener(e)}};return x}},8679:(e,t,n)=>{"use strict";var a=n(9864),r={childContextTypes:!0,contextType:!0,contextTypes:!0,defaultProps:!0,displayName:!0,getDefaultProps:!0,getDerivedStateFromError:!0,getDerivedStateFromProps:!0,mixins:!0,propTypes:!0,type:!0},o={name:!0,length:!0,prototype:!0,caller:!0,callee:!0,arguments:!0,arity:!0},s={$$typeof:!0,compare:!0,defaultProps:!0,displayName:!0,propTypes:!0,type:!0},i={};function l(e){return a.isMemo(e)?s:i[e.$$typeof]||r}i[a.ForwardRef]={$$typeof:!0,render:!0,defaultProps:!0,displayName:!0,propTypes:!0},i[a.Memo]=s;var c=Object.defineProperty,u=Object.getOwnPropertyNames,d=Object.getOwnPropertySymbols,f=Object.getOwnPropertyDescriptor,p=Object.getPrototypeOf,m=Object.prototype;e.exports=function e(t,n,a){if("string"!=typeof n){if(m){var r=p(n);r&&r!==m&&e(t,r,a)}var s=u(n);d&&(s=s.concat(d(n)));for(var i=l(t),g=l(n),h=0;h<s.length;++h){var b=s[h];if(!(o[b]||a&&a[b]||g&&g[b]||i&&i[b])){var v=f(n,b);try{c(t,b,v)}catch(y){}}}}return t}},1143:e=>{"use strict";e.exports=function(e,t,n,a,r,o,s,i){if(!e){var l;if(void 0===t)l=new Error("Minified exception occurred; use the non-minified dev environment for the full error message and additional helpful warnings.");else{var c=[n,a,r,o,s,i],u=0;(l=new Error(t.replace(/%s/g,(function(){return c[u++]})))).name="Invariant Violation"}throw l.framesToPop=1,l}}},5826:e=>{e.exports=Array.isArray||function(e){return"[object Array]"==Object.prototype.toString.call(e)}},2497:(e,t,n)=>{"use strict";n.r(t)},2295:(e,t,n)=>{"use strict";n.r(t)},4865:function(e,t,n){var a,r;a=function(){var e,t,n={version:"0.2.0"},a=n.settings={minimum:.08,easing:"ease",positionUsing:"",speed:200,trickle:!0,trickleRate:.02,trickleSpeed:800,showSpinner:!0,barSelector:'[role="bar"]',spinnerSelector:'[role="spinner"]',parent:"body",template:'<div class="bar" role="bar"><div class="peg"></div></div><div class="spinner" role="spinner"><div class="spinner-icon"></div></div>'};function r(e,t,n){return e<t?t:e>n?n:e}function o(e){return 100*(-1+e)}function s(e,t,n){var r;return(r="translate3d"===a.positionUsing?{transform:"translate3d("+o(e)+"%,0,0)"}:"translate"===a.positionUsing?{transform:"translate("+o(e)+"%,0)"}:{"margin-left":o(e)+"%"}).transition="all "+t+"ms "+n,r}n.configure=function(e){var t,n;for(t in e)void 0!==(n=e[t])&&e.hasOwnProperty(t)&&(a[t]=n);return this},n.status=null,n.set=function(e){var t=n.isStarted();e=r(e,a.minimum,1),n.status=1===e?null:e;var o=n.render(!t),c=o.querySelector(a.barSelector),u=a.speed,d=a.easing;return o.offsetWidth,i((function(t){""===a.positionUsing&&(a.positionUsing=n.getPositioningCSS()),l(c,s(e,u,d)),1===e?(l(o,{transition:"none",opacity:1}),o.offsetWidth,setTimeout((function(){l(o,{transition:"all "+u+"ms linear",opacity:0}),setTimeout((function(){n.remove(),t()}),u)}),u)):setTimeout(t,u)})),this},n.isStarted=function(){return"number"==typeof n.status},n.start=function(){n.status||n.set(0);var e=function(){setTimeout((function(){n.status&&(n.trickle(),e())}),a.trickleSpeed)};return a.trickle&&e(),this},n.done=function(e){return e||n.status?n.inc(.3+.5*Math.random()).set(1):this},n.inc=function(e){var t=n.status;return t?("number"!=typeof e&&(e=(1-t)*r(Math.random()*t,.1,.95)),t=r(t+e,0,.994),n.set(t)):n.start()},n.trickle=function(){return n.inc(Math.random()*a.trickleRate)},e=0,t=0,n.promise=function(a){return a&&"resolved"!==a.state()?(0===t&&n.start(),e++,t++,a.always((function(){0==--t?(e=0,n.done()):n.set((e-t)/e)})),this):this},n.render=function(e){if(n.isRendered())return document.getElementById("nprogress");u(document.documentElement,"nprogress-busy");var t=document.createElement("div");t.id="nprogress",t.innerHTML=a.template;var r,s=t.querySelector(a.barSelector),i=e?"-100":o(n.status||0),c=document.querySelector(a.parent);return l(s,{transition:"all 0 linear",transform:"translate3d("+i+"%,0,0)"}),a.showSpinner||(r=t.querySelector(a.spinnerSelector))&&p(r),c!=document.body&&u(c,"nprogress-custom-parent"),c.appendChild(t),t},n.remove=function(){d(document.documentElement,"nprogress-busy"),d(document.querySelector(a.parent),"nprogress-custom-parent");var e=document.getElementById("nprogress");e&&p(e)},n.isRendered=function(){return!!document.getElementById("nprogress")},n.getPositioningCSS=function(){var e=document.body.style,t="WebkitTransform"in e?"Webkit":"MozTransform"in e?"Moz":"msTransform"in e?"ms":"OTransform"in e?"O":"";return t+"Perspective"in e?"translate3d":t+"Transform"in e?"translate":"margin"};var i=function(){var e=[];function t(){var n=e.shift();n&&n(t)}return function(n){e.push(n),1==e.length&&t()}}(),l=function(){var e=["Webkit","O","Moz","ms"],t={};function n(e){return e.replace(/^-ms-/,"ms-").replace(/-([\da-z])/gi,(function(e,t){return t.toUpperCase()}))}function a(t){var n=document.body.style;if(t in n)return t;for(var a,r=e.length,o=t.charAt(0).toUpperCase()+t.slice(1);r--;)if((a=e[r]+o)in n)return a;return t}function r(e){return e=n(e),t[e]||(t[e]=a(e))}function o(e,t,n){t=r(t),e.style[t]=n}return function(e,t){var n,a,r=arguments;if(2==r.length)for(n in t)void 0!==(a=t[n])&&t.hasOwnProperty(n)&&o(e,n,a);else o(e,r[1],r[2])}}();function c(e,t){return("string"==typeof e?e:f(e)).indexOf(" "+t+" ")>=0}function u(e,t){var n=f(e),a=n+t;c(n,t)||(e.className=a.substring(1))}function d(e,t){var n,a=f(e);c(e,t)&&(n=a.replace(" "+t+" "," "),e.className=n.substring(1,n.length-1))}function f(e){return(" "+(e.className||"")+" ").replace(/\s+/gi," ")}function p(e){e&&e.parentNode&&e.parentNode.removeChild(e)}return n},void 0===(r="function"==typeof a?a.call(t,n,t,e):a)||(e.exports=r)},7418:e=>{"use strict";var t=Object.getOwnPropertySymbols,n=Object.prototype.hasOwnProperty,a=Object.prototype.propertyIsEnumerable;e.exports=function(){try{if(!Object.assign)return!1;var e=new String("abc");if(e[5]="de","5"===Object.getOwnPropertyNames(e)[0])return!1;for(var t={},n=0;n<10;n++)t["_"+String.fromCharCode(n)]=n;if("0123456789"!==Object.getOwnPropertyNames(t).map((function(e){return t[e]})).join(""))return!1;var a={};return"abcdefghijklmnopqrst".split("").forEach((function(e){a[e]=e})),"abcdefghijklmnopqrst"===Object.keys(Object.assign({},a)).join("")}catch(r){return!1}}()?Object.assign:function(e,r){for(var o,s,i=function(e){if(null==e)throw new TypeError("Object.assign cannot be called with null or undefined");return Object(e)}(e),l=1;l<arguments.length;l++){for(var c in o=Object(arguments[l]))n.call(o,c)&&(i[c]=o[c]);if(t){s=t(o);for(var u=0;u<s.length;u++)a.call(o,s[u])&&(i[s[u]]=o[s[u]])}}return i}},7410:(e,t,n)=>{"use strict";n.d(t,{Z:()=>o});var a=function(){var e=/(?:^|\s)lang(?:uage)?-([\w-]+)(?=\s|$)/i,t=0,n={},a={util:{encode:function e(t){return t instanceof r?new r(t.type,e(t.content),t.alias):Array.isArray(t)?t.map(e):t.replace(/&/g,"&").replace(/</g,"<").replace(/\u00a0/g," ")},type:function(e){return Object.prototype.toString.call(e).slice(8,-1)},objId:function(e){return e.__id||Object.defineProperty(e,"__id",{value:++t}),e.__id},clone:function e(t,n){var r,o;switch(n=n||{},a.util.type(t)){case"Object":if(o=a.util.objId(t),n[o])return n[o];for(var s in r={},n[o]=r,t)t.hasOwnProperty(s)&&(r[s]=e(t[s],n));return r;case"Array":return o=a.util.objId(t),n[o]?n[o]:(r=[],n[o]=r,t.forEach((function(t,a){r[a]=e(t,n)})),r);default:return t}},getLanguage:function(t){for(;t;){var n=e.exec(t.className);if(n)return n[1].toLowerCase();t=t.parentElement}return"none"},setLanguage:function(t,n){t.className=t.className.replace(RegExp(e,"gi"),""),t.classList.add("language-"+n)},isActive:function(e,t,n){for(var a="no-"+t;e;){var r=e.classList;if(r.contains(t))return!0;if(r.contains(a))return!1;e=e.parentElement}return!!n}},languages:{plain:n,plaintext:n,text:n,txt:n,extend:function(e,t){var n=a.util.clone(a.languages[e]);for(var r in t)n[r]=t[r];return n},insertBefore:function(e,t,n,r){var o=(r=r||a.languages)[e],s={};for(var i in o)if(o.hasOwnProperty(i)){if(i==t)for(var l in n)n.hasOwnProperty(l)&&(s[l]=n[l]);n.hasOwnProperty(i)||(s[i]=o[i])}var c=r[e];return r[e]=s,a.languages.DFS(a.languages,(function(t,n){n===c&&t!=e&&(this[t]=s)})),s},DFS:function e(t,n,r,o){o=o||{};var s=a.util.objId;for(var i in t)if(t.hasOwnProperty(i)){n.call(t,i,t[i],r||i);var l=t[i],c=a.util.type(l);"Object"!==c||o[s(l)]?"Array"!==c||o[s(l)]||(o[s(l)]=!0,e(l,n,i,o)):(o[s(l)]=!0,e(l,n,null,o))}}},plugins:{},highlight:function(e,t,n){var o={code:e,grammar:t,language:n};return a.hooks.run("before-tokenize",o),o.tokens=a.tokenize(o.code,o.grammar),a.hooks.run("after-tokenize",o),r.stringify(a.util.encode(o.tokens),o.language)},tokenize:function(e,t){var n=t.rest;if(n){for(var a in n)t[a]=n[a];delete t.rest}var r=new i;return l(r,r.head,e),s(e,r,t,r.head,0),function(e){var t=[],n=e.head.next;for(;n!==e.tail;)t.push(n.value),n=n.next;return t}(r)},hooks:{all:{},add:function(e,t){var n=a.hooks.all;n[e]=n[e]||[],n[e].push(t)},run:function(e,t){var n=a.hooks.all[e];if(n&&n.length)for(var r,o=0;r=n[o++];)r(t)}},Token:r};function r(e,t,n,a){this.type=e,this.content=t,this.alias=n,this.length=0|(a||"").length}function o(e,t,n,a){e.lastIndex=t;var r=e.exec(n);if(r&&a&&r[1]){var o=r[1].length;r.index+=o,r[0]=r[0].slice(o)}return r}function s(e,t,n,i,u,d){for(var f in n)if(n.hasOwnProperty(f)&&n[f]){var p=n[f];p=Array.isArray(p)?p:[p];for(var m=0;m<p.length;++m){if(d&&d.cause==f+","+m)return;var g=p[m],h=g.inside,b=!!g.lookbehind,v=!!g.greedy,y=g.alias;if(v&&!g.pattern.global){var x=g.pattern.toString().match(/[imsuy]*$/)[0];g.pattern=RegExp(g.pattern.source,x+"g")}for(var w=g.pattern||g,S=i.next,E=u;S!==t.tail&&!(d&&E>=d.reach);E+=S.value.length,S=S.next){var k=S.value;if(t.length>e.length)return;if(!(k instanceof r)){var _,C=1;if(v){if(!(_=o(w,E,e,b))||_.index>=e.length)break;var q=_.index,T=_.index+_[0].length,A=E;for(A+=S.value.length;q>=A;)A+=(S=S.next).value.length;if(E=A-=S.value.length,S.value instanceof r)continue;for(var L=S;L!==t.tail&&(A<T||"string"==typeof L.value);L=L.next)C++,A+=L.value.length;C--,k=e.slice(E,A),_.index-=E}else if(!(_=o(w,0,k,b)))continue;q=_.index;var N=_[0],O=k.slice(0,q),P=k.slice(q+N.length),I=E+k.length;d&&I>d.reach&&(d.reach=I);var R=S.prev;if(O&&(R=l(t,R,O),E+=O.length),c(t,R,C),S=l(t,R,new r(f,h?a.tokenize(N,h):N,y,N)),P&&l(t,S,P),C>1){var M={cause:f+","+m,reach:I};s(e,t,n,S.prev,E,M),d&&M.reach>d.reach&&(d.reach=M.reach)}}}}}}function i(){var e={value:null,prev:null,next:null},t={value:null,prev:e,next:null};e.next=t,this.head=e,this.tail=t,this.length=0}function l(e,t,n){var a=t.next,r={value:n,prev:t,next:a};return t.next=r,a.prev=r,e.length++,r}function c(e,t,n){for(var a=t.next,r=0;r<n&&a!==e.tail;r++)a=a.next;t.next=a,a.prev=t,e.length-=r}return r.stringify=function e(t,n){if("string"==typeof t)return t;if(Array.isArray(t)){var r="";return t.forEach((function(t){r+=e(t,n)})),r}var o={type:t.type,content:e(t.content,n),tag:"span",classes:["token",t.type],attributes:{},language:n},s=t.alias;s&&(Array.isArray(s)?Array.prototype.push.apply(o.classes,s):o.classes.push(s)),a.hooks.run("wrap",o);var i="";for(var l in o.attributes)i+=" "+l+'="'+(o.attributes[l]||"").replace(/"/g,""")+'"';return"<"+o.tag+' class="'+o.classes.join(" ")+'"'+i+">"+o.content+"</"+o.tag+">"},a}(),r=a;a.default=a,r.languages.markup={comment:{pattern:/<!--(?:(?!<!--)[\s\S])*?-->/,greedy:!0},prolog:{pattern:/<\?[\s\S]+?\?>/,greedy:!0},doctype:{pattern:/<!DOCTYPE(?:[^>"'[\]]|"[^"]*"|'[^']*')+(?:\[(?:[^<"'\]]|"[^"]*"|'[^']*'|<(?!!--)|<!--(?:[^-]|-(?!->))*-->)*\]\s*)?>/i,greedy:!0,inside:{"internal-subset":{pattern:/(^[^\[]*\[)[\s\S]+(?=\]>$)/,lookbehind:!0,greedy:!0,inside:null},string:{pattern:/"[^"]*"|'[^']*'/,greedy:!0},punctuation:/^<!|>$|[[\]]/,"doctype-tag":/^DOCTYPE/i,name:/[^\s<>'"]+/}},cdata:{pattern:/<!\[CDATA\[[\s\S]*?\]\]>/i,greedy:!0},tag:{pattern:/<\/?(?!\d)[^\s>\/=$<%]+(?:\s(?:\s*[^\s>\/=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))|(?=[\s/>])))+)?\s*\/?>/,greedy:!0,inside:{tag:{pattern:/^<\/?[^\s>\/]+/,inside:{punctuation:/^<\/?/,namespace:/^[^\s>\/:]+:/}},"special-attr":[],"attr-value":{pattern:/=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+)/,inside:{punctuation:[{pattern:/^=/,alias:"attr-equals"},/"|'/]}},punctuation:/\/?>/,"attr-name":{pattern:/[^\s>\/]+/,inside:{namespace:/^[^\s>\/:]+:/}}}},entity:[{pattern:/&[\da-z]{1,8};/i,alias:"named-entity"},/&#x?[\da-f]{1,8};/i]},r.languages.markup.tag.inside["attr-value"].inside.entity=r.languages.markup.entity,r.languages.markup.doctype.inside["internal-subset"].inside=r.languages.markup,r.hooks.add("wrap",(function(e){"entity"===e.type&&(e.attributes.title=e.content.replace(/&/,"&"))})),Object.defineProperty(r.languages.markup.tag,"addInlined",{value:function(e,t){var n={};n["language-"+t]={pattern:/(^<!\[CDATA\[)[\s\S]+?(?=\]\]>$)/i,lookbehind:!0,inside:r.languages[t]},n.cdata=/^<!\[CDATA\[|\]\]>$/i;var a={"included-cdata":{pattern:/<!\[CDATA\[[\s\S]*?\]\]>/i,inside:n}};a["language-"+t]={pattern:/[\s\S]+/,inside:r.languages[t]};var o={};o[e]={pattern:RegExp(/(<__[^>]*>)(?:<!\[CDATA\[(?:[^\]]|\](?!\]>))*\]\]>|(?!<!\[CDATA\[)[\s\S])*?(?=<\/__>)/.source.replace(/__/g,(function(){return e})),"i"),lookbehind:!0,greedy:!0,inside:a},r.languages.insertBefore("markup","cdata",o)}}),Object.defineProperty(r.languages.markup.tag,"addAttribute",{value:function(e,t){r.languages.markup.tag.inside["special-attr"].push({pattern:RegExp(/(^|["'\s])/.source+"(?:"+e+")"+/\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))/.source,"i"),lookbehind:!0,inside:{"attr-name":/^[^\s=]+/,"attr-value":{pattern:/=[\s\S]+/,inside:{value:{pattern:/(^=\s*(["']|(?!["'])))\S[\s\S]*(?=\2$)/,lookbehind:!0,alias:[t,"language-"+t],inside:r.languages[t]},punctuation:[{pattern:/^=/,alias:"attr-equals"},/"|'/]}}}})}}),r.languages.html=r.languages.markup,r.languages.mathml=r.languages.markup,r.languages.svg=r.languages.markup,r.languages.xml=r.languages.extend("markup",{}),r.languages.ssml=r.languages.xml,r.languages.atom=r.languages.xml,r.languages.rss=r.languages.xml,function(e){var t="\\b(?:BASH|BASHOPTS|BASH_ALIASES|BASH_ARGC|BASH_ARGV|BASH_CMDS|BASH_COMPLETION_COMPAT_DIR|BASH_LINENO|BASH_REMATCH|BASH_SOURCE|BASH_VERSINFO|BASH_VERSION|COLORTERM|COLUMNS|COMP_WORDBREAKS|DBUS_SESSION_BUS_ADDRESS|DEFAULTS_PATH|DESKTOP_SESSION|DIRSTACK|DISPLAY|EUID|GDMSESSION|GDM_LANG|GNOME_KEYRING_CONTROL|GNOME_KEYRING_PID|GPG_AGENT_INFO|GROUPS|HISTCONTROL|HISTFILE|HISTFILESIZE|HISTSIZE|HOME|HOSTNAME|HOSTTYPE|IFS|INSTANCE|JOB|LANG|LANGUAGE|LC_ADDRESS|LC_ALL|LC_IDENTIFICATION|LC_MEASUREMENT|LC_MONETARY|LC_NAME|LC_NUMERIC|LC_PAPER|LC_TELEPHONE|LC_TIME|LESSCLOSE|LESSOPEN|LINES|LOGNAME|LS_COLORS|MACHTYPE|MAILCHECK|MANDATORY_PATH|NO_AT_BRIDGE|OLDPWD|OPTERR|OPTIND|ORBIT_SOCKETDIR|OSTYPE|PAPERSIZE|PATH|PIPESTATUS|PPID|PS1|PS2|PS3|PS4|PWD|RANDOM|REPLY|SECONDS|SELINUX_INIT|SESSION|SESSIONTYPE|SESSION_MANAGER|SHELL|SHELLOPTS|SHLVL|SSH_AUTH_SOCK|TERM|UID|UPSTART_EVENTS|UPSTART_INSTANCE|UPSTART_JOB|UPSTART_SESSION|USER|WINDOWID|XAUTHORITY|XDG_CONFIG_DIRS|XDG_CURRENT_DESKTOP|XDG_DATA_DIRS|XDG_GREETER_DATA_DIR|XDG_MENU_PREFIX|XDG_RUNTIME_DIR|XDG_SEAT|XDG_SEAT_PATH|XDG_SESSION_DESKTOP|XDG_SESSION_ID|XDG_SESSION_PATH|XDG_SESSION_TYPE|XDG_VTNR|XMODIFIERS)\\b",n={pattern:/(^(["']?)\w+\2)[ \t]+\S.*/,lookbehind:!0,alias:"punctuation",inside:null},a={bash:n,environment:{pattern:RegExp("\\$"+t),alias:"constant"},variable:[{pattern:/\$?\(\([\s\S]+?\)\)/,greedy:!0,inside:{variable:[{pattern:/(^\$\(\([\s\S]+)\)\)/,lookbehind:!0},/^\$\(\(/],number:/\b0x[\dA-Fa-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:[Ee]-?\d+)?/,operator:/--|\+\+|\*\*=?|<<=?|>>=?|&&|\|\||[=!+\-*/%<>^&|]=?|[?~:]/,punctuation:/\(\(?|\)\)?|,|;/}},{pattern:/\$\((?:\([^)]+\)|[^()])+\)|`[^`]+`/,greedy:!0,inside:{variable:/^\$\(|^`|\)$|`$/}},{pattern:/\$\{[^}]+\}/,greedy:!0,inside:{operator:/:[-=?+]?|[!\/]|##?|%%?|\^\^?|,,?/,punctuation:/[\[\]]/,environment:{pattern:RegExp("(\\{)"+t),lookbehind:!0,alias:"constant"}}},/\$(?:\w+|[#?*!@$])/],entity:/\\(?:[abceEfnrtv\\"]|O?[0-7]{1,3}|U[0-9a-fA-F]{8}|u[0-9a-fA-F]{4}|x[0-9a-fA-F]{1,2})/};e.languages.bash={shebang:{pattern:/^#!\s*\/.*/,alias:"important"},comment:{pattern:/(^|[^"{\\$])#.*/,lookbehind:!0},"function-name":[{pattern:/(\bfunction\s+)[\w-]+(?=(?:\s*\(?:\s*\))?\s*\{)/,lookbehind:!0,alias:"function"},{pattern:/\b[\w-]+(?=\s*\(\s*\)\s*\{)/,alias:"function"}],"for-or-select":{pattern:/(\b(?:for|select)\s+)\w+(?=\s+in\s)/,alias:"variable",lookbehind:!0},"assign-left":{pattern:/(^|[\s;|&]|[<>]\()\w+(?=\+?=)/,inside:{environment:{pattern:RegExp("(^|[\\s;|&]|[<>]\\()"+t),lookbehind:!0,alias:"constant"}},alias:"variable",lookbehind:!0},string:[{pattern:/((?:^|[^<])<<-?\s*)(\w+)\s[\s\S]*?(?:\r?\n|\r)\2/,lookbehind:!0,greedy:!0,inside:a},{pattern:/((?:^|[^<])<<-?\s*)(["'])(\w+)\2\s[\s\S]*?(?:\r?\n|\r)\3/,lookbehind:!0,greedy:!0,inside:{bash:n}},{pattern:/(^|[^\\](?:\\\\)*)"(?:\\[\s\S]|\$\([^)]+\)|\$(?!\()|`[^`]+`|[^"\\`$])*"/,lookbehind:!0,greedy:!0,inside:a},{pattern:/(^|[^$\\])'[^']*'/,lookbehind:!0,greedy:!0},{pattern:/\$'(?:[^'\\]|\\[\s\S])*'/,greedy:!0,inside:{entity:a.entity}}],environment:{pattern:RegExp("\\$?"+t),alias:"constant"},variable:a.variable,function:{pattern:/(^|[\s;|&]|[<>]\()(?:add|apropos|apt|apt-cache|apt-get|aptitude|aspell|automysqlbackup|awk|basename|bash|bc|bconsole|bg|bzip2|cal|cat|cfdisk|chgrp|chkconfig|chmod|chown|chroot|cksum|clear|cmp|column|comm|composer|cp|cron|crontab|csplit|curl|cut|date|dc|dd|ddrescue|debootstrap|df|diff|diff3|dig|dir|dircolors|dirname|dirs|dmesg|docker|docker-compose|du|egrep|eject|env|ethtool|expand|expect|expr|fdformat|fdisk|fg|fgrep|file|find|fmt|fold|format|free|fsck|ftp|fuser|gawk|git|gparted|grep|groupadd|groupdel|groupmod|groups|grub-mkconfig|gzip|halt|head|hg|history|host|hostname|htop|iconv|id|ifconfig|ifdown|ifup|import|install|ip|jobs|join|kill|killall|less|link|ln|locate|logname|logrotate|look|lpc|lpr|lprint|lprintd|lprintq|lprm|ls|lsof|lynx|make|man|mc|mdadm|mkconfig|mkdir|mke2fs|mkfifo|mkfs|mkisofs|mknod|mkswap|mmv|more|most|mount|mtools|mtr|mutt|mv|nano|nc|netstat|nice|nl|node|nohup|notify-send|npm|nslookup|op|open|parted|passwd|paste|pathchk|ping|pkill|pnpm|podman|podman-compose|popd|pr|printcap|printenv|ps|pushd|pv|quota|quotacheck|quotactl|ram|rar|rcp|reboot|remsync|rename|renice|rev|rm|rmdir|rpm|rsync|scp|screen|sdiff|sed|sendmail|seq|service|sftp|sh|shellcheck|shuf|shutdown|sleep|slocate|sort|split|ssh|stat|strace|su|sudo|sum|suspend|swapon|sync|tac|tail|tar|tee|time|timeout|top|touch|tr|traceroute|tsort|tty|umount|uname|unexpand|uniq|units|unrar|unshar|unzip|update-grub|uptime|useradd|userdel|usermod|users|uudecode|uuencode|v|vcpkg|vdir|vi|vim|virsh|vmstat|wait|watch|wc|wget|whereis|which|who|whoami|write|xargs|xdg-open|yarn|yes|zenity|zip|zsh|zypper)(?=$|[)\s;|&])/,lookbehind:!0},keyword:{pattern:/(^|[\s;|&]|[<>]\()(?:case|do|done|elif|else|esac|fi|for|function|if|in|select|then|until|while)(?=$|[)\s;|&])/,lookbehind:!0},builtin:{pattern:/(^|[\s;|&]|[<>]\()(?:\.|:|alias|bind|break|builtin|caller|cd|command|continue|declare|echo|enable|eval|exec|exit|export|getopts|hash|help|let|local|logout|mapfile|printf|pwd|read|readarray|readonly|return|set|shift|shopt|source|test|times|trap|type|typeset|ulimit|umask|unalias|unset)(?=$|[)\s;|&])/,lookbehind:!0,alias:"class-name"},boolean:{pattern:/(^|[\s;|&]|[<>]\()(?:false|true)(?=$|[)\s;|&])/,lookbehind:!0},"file-descriptor":{pattern:/\B&\d\b/,alias:"important"},operator:{pattern:/\d?<>|>\||\+=|=[=~]?|!=?|<<[<-]?|[&\d]?>>|\d[<>]&?|[<>][&=]?|&[>&]?|\|[&|]?/,inside:{"file-descriptor":{pattern:/^\d/,alias:"important"}}},punctuation:/\$?\(\(?|\)\)?|\.\.|[{}[\];\\]/,number:{pattern:/(^|\s)(?:[1-9]\d*|0)(?:[.,]\d+)?\b/,lookbehind:!0}},n.inside=e.languages.bash;for(var r=["comment","function-name","for-or-select","assign-left","string","environment","function","keyword","builtin","boolean","file-descriptor","operator","punctuation","number"],o=a.variable[1].inside,s=0;s<r.length;s++)o[r[s]]=e.languages.bash[r[s]];e.languages.shell=e.languages.bash}(r),r.languages.clike={comment:[{pattern:/(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/,lookbehind:!0,greedy:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0,greedy:!0}],string:{pattern:/(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},"class-name":{pattern:/(\b(?:class|extends|implements|instanceof|interface|new|trait)\s+|\bcatch\s+\()[\w.\\]+/i,lookbehind:!0,inside:{punctuation:/[.\\]/}},keyword:/\b(?:break|catch|continue|do|else|finally|for|function|if|in|instanceof|new|null|return|throw|try|while)\b/,boolean:/\b(?:false|true)\b/,function:/\b\w+(?=\()/,number:/\b0x[\da-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?/i,operator:/[<>]=?|[!=]=?=?|--?|\+\+?|&&?|\|\|?|[?*/~^%]/,punctuation:/[{}[\];(),.:]/},r.languages.c=r.languages.extend("clike",{comment:{pattern:/\/\/(?:[^\r\n\\]|\\(?:\r\n?|\n|(?![\r\n])))*|\/\*[\s\S]*?(?:\*\/|$)/,greedy:!0},string:{pattern:/"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"/,greedy:!0},"class-name":{pattern:/(\b(?:enum|struct)\s+(?:__attribute__\s*\(\([\s\S]*?\)\)\s*)?)\w+|\b[a-z]\w*_t\b/,lookbehind:!0},keyword:/\b(?:_Alignas|_Alignof|_Atomic|_Bool|_Complex|_Generic|_Imaginary|_Noreturn|_Static_assert|_Thread_local|__attribute__|asm|auto|break|case|char|const|continue|default|do|double|else|enum|extern|float|for|goto|if|inline|int|long|register|return|short|signed|sizeof|static|struct|switch|typedef|typeof|union|unsigned|void|volatile|while)\b/,function:/\b[a-z_]\w*(?=\s*\()/i,number:/(?:\b0x(?:[\da-f]+(?:\.[\da-f]*)?|\.[\da-f]+)(?:p[+-]?\d+)?|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?)[ful]{0,4}/i,operator:/>>=?|<<=?|->|([-+&|:])\1|[?:~]|[-+*/%&|^!=<>]=?/}),r.languages.insertBefore("c","string",{char:{pattern:/'(?:\\(?:\r\n|[\s\S])|[^'\\\r\n]){0,32}'/,greedy:!0}}),r.languages.insertBefore("c","string",{macro:{pattern:/(^[\t ]*)#\s*[a-z](?:[^\r\n\\/]|\/(?!\*)|\/\*(?:[^*]|\*(?!\/))*\*\/|\\(?:\r\n|[\s\S]))*/im,lookbehind:!0,greedy:!0,alias:"property",inside:{string:[{pattern:/^(#\s*include\s*)<[^>]+>/,lookbehind:!0},r.languages.c.string],char:r.languages.c.char,comment:r.languages.c.comment,"macro-name":[{pattern:/(^#\s*define\s+)\w+\b(?!\()/i,lookbehind:!0},{pattern:/(^#\s*define\s+)\w+\b(?=\()/i,lookbehind:!0,alias:"function"}],directive:{pattern:/^(#\s*)[a-z]+/,lookbehind:!0,alias:"keyword"},"directive-hash":/^#/,punctuation:/##|\\(?=[\r\n])/,expression:{pattern:/\S[\s\S]*/,inside:r.languages.c}}}}),r.languages.insertBefore("c","function",{constant:/\b(?:EOF|NULL|SEEK_CUR|SEEK_END|SEEK_SET|__DATE__|__FILE__|__LINE__|__TIMESTAMP__|__TIME__|__func__|stderr|stdin|stdout)\b/}),delete r.languages.c.boolean,function(e){var t=/\b(?:alignas|alignof|asm|auto|bool|break|case|catch|char|char16_t|char32_t|char8_t|class|co_await|co_return|co_yield|compl|concept|const|const_cast|consteval|constexpr|constinit|continue|decltype|default|delete|do|double|dynamic_cast|else|enum|explicit|export|extern|final|float|for|friend|goto|if|import|inline|int|int16_t|int32_t|int64_t|int8_t|long|module|mutable|namespace|new|noexcept|nullptr|operator|override|private|protected|public|register|reinterpret_cast|requires|return|short|signed|sizeof|static|static_assert|static_cast|struct|switch|template|this|thread_local|throw|try|typedef|typeid|typename|uint16_t|uint32_t|uint64_t|uint8_t|union|unsigned|using|virtual|void|volatile|wchar_t|while)\b/,n=/\b(?!<keyword>)\w+(?:\s*\.\s*\w+)*\b/.source.replace(/<keyword>/g,(function(){return t.source}));e.languages.cpp=e.languages.extend("c",{"class-name":[{pattern:RegExp(/(\b(?:class|concept|enum|struct|typename)\s+)(?!<keyword>)\w+/.source.replace(/<keyword>/g,(function(){return t.source}))),lookbehind:!0},/\b[A-Z]\w*(?=\s*::\s*\w+\s*\()/,/\b[A-Z_]\w*(?=\s*::\s*~\w+\s*\()/i,/\b\w+(?=\s*<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>\s*::\s*\w+\s*\()/],keyword:t,number:{pattern:/(?:\b0b[01']+|\b0x(?:[\da-f']+(?:\.[\da-f']*)?|\.[\da-f']+)(?:p[+-]?[\d']+)?|(?:\b[\d']+(?:\.[\d']*)?|\B\.[\d']+)(?:e[+-]?[\d']+)?)[ful]{0,4}/i,greedy:!0},operator:/>>=?|<<=?|->|--|\+\+|&&|\|\||[?:~]|<=>|[-+*/%&|^!=<>]=?|\b(?:and|and_eq|bitand|bitor|not|not_eq|or|or_eq|xor|xor_eq)\b/,boolean:/\b(?:false|true)\b/}),e.languages.insertBefore("cpp","string",{module:{pattern:RegExp(/(\b(?:import|module)\s+)/.source+"(?:"+/"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"|<[^<>\r\n]*>/.source+"|"+/<mod-name>(?:\s*:\s*<mod-name>)?|:\s*<mod-name>/.source.replace(/<mod-name>/g,(function(){return n}))+")"),lookbehind:!0,greedy:!0,inside:{string:/^[<"][\s\S]+/,operator:/:/,punctuation:/\./}},"raw-string":{pattern:/R"([^()\\ ]{0,16})\([\s\S]*?\)\1"/,alias:"string",greedy:!0}}),e.languages.insertBefore("cpp","keyword",{"generic-function":{pattern:/\b(?!operator\b)[a-z_]\w*\s*<(?:[^<>]|<[^<>]*>)*>(?=\s*\()/i,inside:{function:/^\w+/,generic:{pattern:/<[\s\S]+/,alias:"class-name",inside:e.languages.cpp}}}}),e.languages.insertBefore("cpp","operator",{"double-colon":{pattern:/::/,alias:"punctuation"}}),e.languages.insertBefore("cpp","class-name",{"base-clause":{pattern:/(\b(?:class|struct)\s+\w+\s*:\s*)[^;{}"'\s]+(?:\s+[^;{}"'\s]+)*(?=\s*[;{])/,lookbehind:!0,greedy:!0,inside:e.languages.extend("cpp",{})}}),e.languages.insertBefore("inside","double-colon",{"class-name":/\b[a-z_]\w*\b(?!\s*::)/i},e.languages.cpp["base-clause"])}(r),function(e){var t=/(?:"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"|'(?:\\(?:\r\n|[\s\S])|[^'\\\r\n])*')/;e.languages.css={comment:/\/\*[\s\S]*?\*\//,atrule:{pattern:/@[\w-](?:[^;{\s]|\s+(?![\s{]))*(?:;|(?=\s*\{))/,inside:{rule:/^@[\w-]+/,"selector-function-argument":{pattern:/(\bselector\s*\(\s*(?![\s)]))(?:[^()\s]|\s+(?![\s)])|\((?:[^()]|\([^()]*\))*\))+(?=\s*\))/,lookbehind:!0,alias:"selector"},keyword:{pattern:/(^|[^\w-])(?:and|not|only|or)(?![\w-])/,lookbehind:!0}}},url:{pattern:RegExp("\\burl\\((?:"+t.source+"|"+/(?:[^\\\r\n()"']|\\[\s\S])*/.source+")\\)","i"),greedy:!0,inside:{function:/^url/i,punctuation:/^\(|\)$/,string:{pattern:RegExp("^"+t.source+"$"),alias:"url"}}},selector:{pattern:RegExp("(^|[{}\\s])[^{}\\s](?:[^{};\"'\\s]|\\s+(?![\\s{])|"+t.source+")*(?=\\s*\\{)"),lookbehind:!0},string:{pattern:t,greedy:!0},property:{pattern:/(^|[^-\w\xA0-\uFFFF])(?!\s)[-_a-z\xA0-\uFFFF](?:(?!\s)[-\w\xA0-\uFFFF])*(?=\s*:)/i,lookbehind:!0},important:/!important\b/i,function:{pattern:/(^|[^-a-z0-9])[-a-z0-9]+(?=\()/i,lookbehind:!0},punctuation:/[(){};:,]/},e.languages.css.atrule.inside.rest=e.languages.css;var n=e.languages.markup;n&&(n.tag.addInlined("style","css"),n.tag.addAttribute("style","css"))}(r),function(e){var t,n=/("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/;e.languages.css.selector={pattern:e.languages.css.selector.pattern,lookbehind:!0,inside:t={"pseudo-element":/:(?:after|before|first-letter|first-line|selection)|::[-\w]+/,"pseudo-class":/:[-\w]+/,class:/\.[-\w]+/,id:/#[-\w]+/,attribute:{pattern:RegExp("\\[(?:[^[\\]\"']|"+n.source+")*\\]"),greedy:!0,inside:{punctuation:/^\[|\]$/,"case-sensitivity":{pattern:/(\s)[si]$/i,lookbehind:!0,alias:"keyword"},namespace:{pattern:/^(\s*)(?:(?!\s)[-*\w\xA0-\uFFFF])*\|(?!=)/,lookbehind:!0,inside:{punctuation:/\|$/}},"attr-name":{pattern:/^(\s*)(?:(?!\s)[-\w\xA0-\uFFFF])+/,lookbehind:!0},"attr-value":[n,{pattern:/(=\s*)(?:(?!\s)[-\w\xA0-\uFFFF])+(?=\s*$)/,lookbehind:!0}],operator:/[|~*^$]?=/}},"n-th":[{pattern:/(\(\s*)[+-]?\d*[\dn](?:\s*[+-]\s*\d+)?(?=\s*\))/,lookbehind:!0,inside:{number:/[\dn]+/,operator:/[+-]/}},{pattern:/(\(\s*)(?:even|odd)(?=\s*\))/i,lookbehind:!0}],combinator:/>|\+|~|\|\|/,punctuation:/[(),]/}},e.languages.css.atrule.inside["selector-function-argument"].inside=t,e.languages.insertBefore("css","property",{variable:{pattern:/(^|[^-\w\xA0-\uFFFF])--(?!\s)[-_a-z\xA0-\uFFFF](?:(?!\s)[-\w\xA0-\uFFFF])*/i,lookbehind:!0}});var a={pattern:/(\b\d+)(?:%|[a-z]+(?![\w-]))/,lookbehind:!0},r={pattern:/(^|[^\w.-])-?(?:\d+(?:\.\d+)?|\.\d+)/,lookbehind:!0};e.languages.insertBefore("css","function",{operator:{pattern:/(\s)[+\-*\/](?=\s)/,lookbehind:!0},hexcode:{pattern:/\B#[\da-f]{3,8}\b/i,alias:"color"},color:[{pattern:/(^|[^\w-])(?:AliceBlue|AntiqueWhite|Aqua|Aquamarine|Azure|Beige|Bisque|Black|BlanchedAlmond|Blue|BlueViolet|Brown|BurlyWood|CadetBlue|Chartreuse|Chocolate|Coral|CornflowerBlue|Cornsilk|Crimson|Cyan|DarkBlue|DarkCyan|DarkGoldenRod|DarkGr[ae]y|DarkGreen|DarkKhaki|DarkMagenta|DarkOliveGreen|DarkOrange|DarkOrchid|DarkRed|DarkSalmon|DarkSeaGreen|DarkSlateBlue|DarkSlateGr[ae]y|DarkTurquoise|DarkViolet|DeepPink|DeepSkyBlue|DimGr[ae]y|DodgerBlue|FireBrick|FloralWhite|ForestGreen|Fuchsia|Gainsboro|GhostWhite|Gold|GoldenRod|Gr[ae]y|Green|GreenYellow|HoneyDew|HotPink|IndianRed|Indigo|Ivory|Khaki|Lavender|LavenderBlush|LawnGreen|LemonChiffon|LightBlue|LightCoral|LightCyan|LightGoldenRodYellow|LightGr[ae]y|LightGreen|LightPink|LightSalmon|LightSeaGreen|LightSkyBlue|LightSlateGr[ae]y|LightSteelBlue|LightYellow|Lime|LimeGreen|Linen|Magenta|Maroon|MediumAquaMarine|MediumBlue|MediumOrchid|MediumPurple|MediumSeaGreen|MediumSlateBlue|MediumSpringGreen|MediumTurquoise|MediumVioletRed|MidnightBlue|MintCream|MistyRose|Moccasin|NavajoWhite|Navy|OldLace|Olive|OliveDrab|Orange|OrangeRed|Orchid|PaleGoldenRod|PaleGreen|PaleTurquoise|PaleVioletRed|PapayaWhip|PeachPuff|Peru|Pink|Plum|PowderBlue|Purple|Red|RosyBrown|RoyalBlue|SaddleBrown|Salmon|SandyBrown|SeaGreen|SeaShell|Sienna|Silver|SkyBlue|SlateBlue|SlateGr[ae]y|Snow|SpringGreen|SteelBlue|Tan|Teal|Thistle|Tomato|Transparent|Turquoise|Violet|Wheat|White|WhiteSmoke|Yellow|YellowGreen)(?![\w-])/i,lookbehind:!0},{pattern:/\b(?:hsl|rgb)\(\s*\d{1,3}\s*,\s*\d{1,3}%?\s*,\s*\d{1,3}%?\s*\)\B|\b(?:hsl|rgb)a\(\s*\d{1,3}\s*,\s*\d{1,3}%?\s*,\s*\d{1,3}%?\s*,\s*(?:0|0?\.\d+|1)\s*\)\B/i,inside:{unit:a,number:r,function:/[\w-]+(?=\()/,punctuation:/[(),]/}}],entity:/\\[\da-f]{1,8}/i,unit:a,number:r})}(r),r.languages.javascript=r.languages.extend("clike",{"class-name":[r.languages.clike["class-name"],{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$A-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\.(?:constructor|prototype))/,lookbehind:!0}],keyword:[{pattern:/((?:^|\})\s*)catch\b/,lookbehind:!0},{pattern:/(^|[^.]|\.\.\.\s*)\b(?:as|assert(?=\s*\{)|async(?=\s*(?:function\b|\(|[$\w\xA0-\uFFFF]|$))|await|break|case|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally(?=\s*(?:\{|$))|for|from(?=\s*(?:['"]|$))|function|(?:get|set)(?=\s*(?:[#\[$\w\xA0-\uFFFF]|$))|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)\b/,lookbehind:!0}],function:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*(?:\.\s*(?:apply|bind|call)\s*)?\()/,number:{pattern:RegExp(/(^|[^\w$])/.source+"(?:"+/NaN|Infinity/.source+"|"+/0[bB][01]+(?:_[01]+)*n?/.source+"|"+/0[oO][0-7]+(?:_[0-7]+)*n?/.source+"|"+/0[xX][\dA-Fa-f]+(?:_[\dA-Fa-f]+)*n?/.source+"|"+/\d+(?:_\d+)*n/.source+"|"+/(?:\d+(?:_\d+)*(?:\.(?:\d+(?:_\d+)*)?)?|\.\d+(?:_\d+)*)(?:[Ee][+-]?\d+(?:_\d+)*)?/.source+")"+/(?![\w$])/.source),lookbehind:!0},operator:/--|\+\+|\*\*=?|=>|&&=?|\|\|=?|[!=]==|<<=?|>>>?=?|[-+*/%&|^!=<>]=?|\.{3}|\?\?=?|\?\.?|[~:]/}),r.languages.javascript["class-name"][0].pattern=/(\b(?:class|extends|implements|instanceof|interface|new)\s+)[\w.\\]+/,r.languages.insertBefore("javascript","keyword",{regex:{pattern:/((?:^|[^$\w\xA0-\uFFFF."'\])\s]|\b(?:return|yield))\s*)\/(?:\[(?:[^\]\\\r\n]|\\.)*\]|\\.|[^/\\\[\r\n])+\/[dgimyus]{0,7}(?=(?:\s|\/\*(?:[^*]|\*(?!\/))*\*\/)*(?:$|[\r\n,.;:})\]]|\/\/))/,lookbehind:!0,greedy:!0,inside:{"regex-source":{pattern:/^(\/)[\s\S]+(?=\/[a-z]*$)/,lookbehind:!0,alias:"language-regex",inside:r.languages.regex},"regex-delimiter":/^\/|\/$/,"regex-flags":/^[a-z]+$/}},"function-variable":{pattern:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*[=:]\s*(?:async\s*)?(?:\bfunction\b|(?:\((?:[^()]|\([^()]*\))*\)|(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)\s*=>))/,alias:"function"},parameter:[{pattern:/(function(?:\s+(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)?\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\))/,lookbehind:!0,inside:r.languages.javascript},{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$a-z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*=>)/i,lookbehind:!0,inside:r.languages.javascript},{pattern:/(\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*=>)/,lookbehind:!0,inside:r.languages.javascript},{pattern:/((?:\b|\s|^)(?!(?:as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)(?![$\w\xA0-\uFFFF]))(?:(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s*)\(\s*|\]\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*\{)/,lookbehind:!0,inside:r.languages.javascript}],constant:/\b[A-Z](?:[A-Z_]|\dx?)*\b/}),r.languages.insertBefore("javascript","string",{hashbang:{pattern:/^#!.*/,greedy:!0,alias:"comment"},"template-string":{pattern:/`(?:\\[\s\S]|\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}|(?!\$\{)[^\\`])*`/,greedy:!0,inside:{"template-punctuation":{pattern:/^`|`$/,alias:"string"},interpolation:{pattern:/((?:^|[^\\])(?:\\{2})*)\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}/,lookbehind:!0,inside:{"interpolation-punctuation":{pattern:/^\$\{|\}$/,alias:"punctuation"},rest:r.languages.javascript}},string:/[\s\S]+/}},"string-property":{pattern:/((?:^|[,{])[ \t]*)(["'])(?:\\(?:\r\n|[\s\S])|(?!\2)[^\\\r\n])*\2(?=\s*:)/m,lookbehind:!0,greedy:!0,alias:"property"}}),r.languages.insertBefore("javascript","operator",{"literal-property":{pattern:/((?:^|[,{])[ \t]*)(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*:)/m,lookbehind:!0,alias:"property"}}),r.languages.markup&&(r.languages.markup.tag.addInlined("script","javascript"),r.languages.markup.tag.addAttribute(/on(?:abort|blur|change|click|composition(?:end|start|update)|dblclick|error|focus(?:in|out)?|key(?:down|up)|load|mouse(?:down|enter|leave|move|out|over|up)|reset|resize|scroll|select|slotchange|submit|unload|wheel)/.source,"javascript")),r.languages.js=r.languages.javascript,function(e){var t=/#(?!\{).+/,n={pattern:/#\{[^}]+\}/,alias:"variable"};e.languages.coffeescript=e.languages.extend("javascript",{comment:t,string:[{pattern:/'(?:\\[\s\S]|[^\\'])*'/,greedy:!0},{pattern:/"(?:\\[\s\S]|[^\\"])*"/,greedy:!0,inside:{interpolation:n}}],keyword:/\b(?:and|break|by|catch|class|continue|debugger|delete|do|each|else|extend|extends|false|finally|for|if|in|instanceof|is|isnt|let|loop|namespace|new|no|not|null|of|off|on|or|own|return|super|switch|then|this|throw|true|try|typeof|undefined|unless|until|when|while|window|with|yes|yield)\b/,"class-member":{pattern:/@(?!\d)\w+/,alias:"variable"}}),e.languages.insertBefore("coffeescript","comment",{"multiline-comment":{pattern:/###[\s\S]+?###/,alias:"comment"},"block-regex":{pattern:/\/{3}[\s\S]*?\/{3}/,alias:"regex",inside:{comment:t,interpolation:n}}}),e.languages.insertBefore("coffeescript","string",{"inline-javascript":{pattern:/`(?:\\[\s\S]|[^\\`])*`/,inside:{delimiter:{pattern:/^`|`$/,alias:"punctuation"},script:{pattern:/[\s\S]+/,alias:"language-javascript",inside:e.languages.javascript}}},"multiline-string":[{pattern:/'''[\s\S]*?'''/,greedy:!0,alias:"string"},{pattern:/"""[\s\S]*?"""/,greedy:!0,alias:"string",inside:{interpolation:n}}]}),e.languages.insertBefore("coffeescript","keyword",{property:/(?!\d)\w+(?=\s*:(?!:))/}),delete e.languages.coffeescript["template-string"],e.languages.coffee=e.languages.coffeescript}(r),function(e){var t=/[*&][^\s[\]{},]+/,n=/!(?:<[\w\-%#;/?:@&=+$,.!~*'()[\]]+>|(?:[a-zA-Z\d-]*!)?[\w\-%#;/?:@&=+$.~*'()]+)?/,a="(?:"+n.source+"(?:[ \t]+"+t.source+")?|"+t.source+"(?:[ \t]+"+n.source+")?)",r=/(?:[^\s\x00-\x08\x0e-\x1f!"#%&'*,\-:>?@[\]`{|}\x7f-\x84\x86-\x9f\ud800-\udfff\ufffe\uffff]|[?:-]<PLAIN>)(?:[ \t]*(?:(?![#:])<PLAIN>|:<PLAIN>))*/.source.replace(/<PLAIN>/g,(function(){return/[^\s\x00-\x08\x0e-\x1f,[\]{}\x7f-\x84\x86-\x9f\ud800-\udfff\ufffe\uffff]/.source})),o=/"(?:[^"\\\r\n]|\\.)*"|'(?:[^'\\\r\n]|\\.)*'/.source;function s(e,t){t=(t||"").replace(/m/g,"")+"m";var n=/([:\-,[{]\s*(?:\s<<prop>>[ \t]+)?)(?:<<value>>)(?=[ \t]*(?:$|,|\]|\}|(?:[\r\n]\s*)?#))/.source.replace(/<<prop>>/g,(function(){return a})).replace(/<<value>>/g,(function(){return e}));return RegExp(n,t)}e.languages.yaml={scalar:{pattern:RegExp(/([\-:]\s*(?:\s<<prop>>[ \t]+)?[|>])[ \t]*(?:((?:\r?\n|\r)[ \t]+)\S[^\r\n]*(?:\2[^\r\n]+)*)/.source.replace(/<<prop>>/g,(function(){return a}))),lookbehind:!0,alias:"string"},comment:/#.*/,key:{pattern:RegExp(/((?:^|[:\-,[{\r\n?])[ \t]*(?:<<prop>>[ \t]+)?)<<key>>(?=\s*:\s)/.source.replace(/<<prop>>/g,(function(){return a})).replace(/<<key>>/g,(function(){return"(?:"+r+"|"+o+")"}))),lookbehind:!0,greedy:!0,alias:"atrule"},directive:{pattern:/(^[ \t]*)%.+/m,lookbehind:!0,alias:"important"},datetime:{pattern:s(/\d{4}-\d\d?-\d\d?(?:[tT]|[ \t]+)\d\d?:\d{2}:\d{2}(?:\.\d*)?(?:[ \t]*(?:Z|[-+]\d\d?(?::\d{2})?))?|\d{4}-\d{2}-\d{2}|\d\d?:\d{2}(?::\d{2}(?:\.\d*)?)?/.source),lookbehind:!0,alias:"number"},boolean:{pattern:s(/false|true/.source,"i"),lookbehind:!0,alias:"important"},null:{pattern:s(/null|~/.source,"i"),lookbehind:!0,alias:"important"},string:{pattern:s(o),lookbehind:!0,greedy:!0},number:{pattern:s(/[+-]?(?:0x[\da-f]+|0o[0-7]+|(?:\d+(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?|\.inf|\.nan)/.source,"i"),lookbehind:!0},tag:n,important:t,punctuation:/---|[:[\]{}\-,|>?]|\.\.\./},e.languages.yml=e.languages.yaml}(r),function(e){var t=/(?:\\.|[^\\\n\r]|(?:\n|\r\n?)(?![\r\n]))/.source;function n(e){return e=e.replace(/<inner>/g,(function(){return t})),RegExp(/((?:^|[^\\])(?:\\{2})*)/.source+"(?:"+e+")")}var a=/(?:\\.|``(?:[^`\r\n]|`(?!`))+``|`[^`\r\n]+`|[^\\|\r\n`])+/.source,r=/\|?__(?:\|__)+\|?(?:(?:\n|\r\n?)|(?![\s\S]))/.source.replace(/__/g,(function(){return a})),o=/\|?[ \t]*:?-{3,}:?[ \t]*(?:\|[ \t]*:?-{3,}:?[ \t]*)+\|?(?:\n|\r\n?)/.source;e.languages.markdown=e.languages.extend("markup",{}),e.languages.insertBefore("markdown","prolog",{"front-matter-block":{pattern:/(^(?:\s*[\r\n])?)---(?!.)[\s\S]*?[\r\n]---(?!.)/,lookbehind:!0,greedy:!0,inside:{punctuation:/^---|---$/,"front-matter":{pattern:/\S+(?:\s+\S+)*/,alias:["yaml","language-yaml"],inside:e.languages.yaml}}},blockquote:{pattern:/^>(?:[\t ]*>)*/m,alias:"punctuation"},table:{pattern:RegExp("^"+r+o+"(?:"+r+")*","m"),inside:{"table-data-rows":{pattern:RegExp("^("+r+o+")(?:"+r+")*$"),lookbehind:!0,inside:{"table-data":{pattern:RegExp(a),inside:e.languages.markdown},punctuation:/\|/}},"table-line":{pattern:RegExp("^("+r+")"+o+"$"),lookbehind:!0,inside:{punctuation:/\||:?-{3,}:?/}},"table-header-row":{pattern:RegExp("^"+r+"$"),inside:{"table-header":{pattern:RegExp(a),alias:"important",inside:e.languages.markdown},punctuation:/\|/}}}},code:[{pattern:/((?:^|\n)[ \t]*\n|(?:^|\r\n?)[ \t]*\r\n?)(?: {4}|\t).+(?:(?:\n|\r\n?)(?: {4}|\t).+)*/,lookbehind:!0,alias:"keyword"},{pattern:/^```[\s\S]*?^```$/m,greedy:!0,inside:{"code-block":{pattern:/^(```.*(?:\n|\r\n?))[\s\S]+?(?=(?:\n|\r\n?)^```$)/m,lookbehind:!0},"code-language":{pattern:/^(```).+/,lookbehind:!0},punctuation:/```/}}],title:[{pattern:/\S.*(?:\n|\r\n?)(?:==+|--+)(?=[ \t]*$)/m,alias:"important",inside:{punctuation:/==+$|--+$/}},{pattern:/(^\s*)#.+/m,lookbehind:!0,alias:"important",inside:{punctuation:/^#+|#+$/}}],hr:{pattern:/(^\s*)([*-])(?:[\t ]*\2){2,}(?=\s*$)/m,lookbehind:!0,alias:"punctuation"},list:{pattern:/(^\s*)(?:[*+-]|\d+\.)(?=[\t ].)/m,lookbehind:!0,alias:"punctuation"},"url-reference":{pattern:/!?\[[^\]]+\]:[\t ]+(?:\S+|<(?:\\.|[^>\\])+>)(?:[\t ]+(?:"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|\((?:\\.|[^)\\])*\)))?/,inside:{variable:{pattern:/^(!?\[)[^\]]+/,lookbehind:!0},string:/(?:"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|\((?:\\.|[^)\\])*\))$/,punctuation:/^[\[\]!:]|[<>]/},alias:"url"},bold:{pattern:n(/\b__(?:(?!_)<inner>|_(?:(?!_)<inner>)+_)+__\b|\*\*(?:(?!\*)<inner>|\*(?:(?!\*)<inner>)+\*)+\*\*/.source),lookbehind:!0,greedy:!0,inside:{content:{pattern:/(^..)[\s\S]+(?=..$)/,lookbehind:!0,inside:{}},punctuation:/\*\*|__/}},italic:{pattern:n(/\b_(?:(?!_)<inner>|__(?:(?!_)<inner>)+__)+_\b|\*(?:(?!\*)<inner>|\*\*(?:(?!\*)<inner>)+\*\*)+\*/.source),lookbehind:!0,greedy:!0,inside:{content:{pattern:/(^.)[\s\S]+(?=.$)/,lookbehind:!0,inside:{}},punctuation:/[*_]/}},strike:{pattern:n(/(~~?)(?:(?!~)<inner>)+\2/.source),lookbehind:!0,greedy:!0,inside:{content:{pattern:/(^~~?)[\s\S]+(?=\1$)/,lookbehind:!0,inside:{}},punctuation:/~~?/}},"code-snippet":{pattern:/(^|[^\\`])(?:``[^`\r\n]+(?:`[^`\r\n]+)*``(?!`)|`[^`\r\n]+`(?!`))/,lookbehind:!0,greedy:!0,alias:["code","keyword"]},url:{pattern:n(/!?\[(?:(?!\])<inner>)+\](?:\([^\s)]+(?:[\t ]+"(?:\\.|[^"\\])*")?\)|[ \t]?\[(?:(?!\])<inner>)+\])/.source),lookbehind:!0,greedy:!0,inside:{operator:/^!/,content:{pattern:/(^\[)[^\]]+(?=\])/,lookbehind:!0,inside:{}},variable:{pattern:/(^\][ \t]?\[)[^\]]+(?=\]$)/,lookbehind:!0},url:{pattern:/(^\]\()[^\s)]+/,lookbehind:!0},string:{pattern:/(^[ \t]+)"(?:\\.|[^"\\])*"(?=\)$)/,lookbehind:!0}}}}),["url","bold","italic","strike"].forEach((function(t){["url","bold","italic","strike","code-snippet"].forEach((function(n){t!==n&&(e.languages.markdown[t].inside.content.inside[n]=e.languages.markdown[n])}))})),e.hooks.add("after-tokenize",(function(e){"markdown"!==e.language&&"md"!==e.language||function e(t){if(t&&"string"!=typeof t)for(var n=0,a=t.length;n<a;n++){var r=t[n];if("code"===r.type){var o=r.content[1],s=r.content[3];if(o&&s&&"code-language"===o.type&&"code-block"===s.type&&"string"==typeof o.content){var i=o.content.replace(/\b#/g,"sharp").replace(/\b\+\+/g,"pp"),l="language-"+(i=(/[a-z][\w-]*/i.exec(i)||[""])[0].toLowerCase());s.alias?"string"==typeof s.alias?s.alias=[s.alias,l]:s.alias.push(l):s.alias=[l]}}else e(r.content)}}(e.tokens)})),e.hooks.add("wrap",(function(t){if("code-block"===t.type){for(var n="",a=0,r=t.classes.length;a<r;a++){var o=t.classes[a],c=/language-(.+)/.exec(o);if(c){n=c[1];break}}var u,d=e.languages[n];if(d)t.content=e.highlight((u=t.content,u.replace(s,"").replace(/&(\w{1,8}|#x?[\da-f]{1,8});/gi,(function(e,t){var n;if("#"===(t=t.toLowerCase())[0])return n="x"===t[1]?parseInt(t.slice(2),16):Number(t.slice(1)),l(n);var a=i[t];return a||e}))),d,n);else if(n&&"none"!==n&&e.plugins.autoloader){var f="md-"+(new Date).valueOf()+"-"+Math.floor(1e16*Math.random());t.attributes.id=f,e.plugins.autoloader.loadLanguages(n,(function(){var t=document.getElementById(f);t&&(t.innerHTML=e.highlight(t.textContent,e.languages[n],n))}))}}}));var s=RegExp(e.languages.markup.tag.pattern.source,"gi"),i={amp:"&",lt:"<",gt:">",quot:'"'},l=String.fromCodePoint||String.fromCharCode;e.languages.md=e.languages.markdown}(r),r.languages.graphql={comment:/#.*/,description:{pattern:/(?:"""(?:[^"]|(?!""")")*"""|"(?:\\.|[^\\"\r\n])*")(?=\s*[a-z_])/i,greedy:!0,alias:"string",inside:{"language-markdown":{pattern:/(^"(?:"")?)(?!\1)[\s\S]+(?=\1$)/,lookbehind:!0,inside:r.languages.markdown}}},string:{pattern:/"""(?:[^"]|(?!""")")*"""|"(?:\\.|[^\\"\r\n])*"/,greedy:!0},number:/(?:\B-|\b)\d+(?:\.\d+)?(?:e[+-]?\d+)?\b/i,boolean:/\b(?:false|true)\b/,variable:/\$[a-z_]\w*/i,directive:{pattern:/@[a-z_]\w*/i,alias:"function"},"attr-name":{pattern:/\b[a-z_]\w*(?=\s*(?:\((?:[^()"]|"(?:\\.|[^\\"\r\n])*")*\))?:)/i,greedy:!0},"atom-input":{pattern:/\b[A-Z]\w*Input\b/,alias:"class-name"},scalar:/\b(?:Boolean|Float|ID|Int|String)\b/,constant:/\b[A-Z][A-Z_\d]*\b/,"class-name":{pattern:/(\b(?:enum|implements|interface|on|scalar|type|union)\s+|&\s*|:\s*|\[)[A-Z_]\w*/,lookbehind:!0},fragment:{pattern:/(\bfragment\s+|\.{3}\s*(?!on\b))[a-zA-Z_]\w*/,lookbehind:!0,alias:"function"},"definition-mutation":{pattern:/(\bmutation\s+)[a-zA-Z_]\w*/,lookbehind:!0,alias:"function"},"definition-query":{pattern:/(\bquery\s+)[a-zA-Z_]\w*/,lookbehind:!0,alias:"function"},keyword:/\b(?:directive|enum|extend|fragment|implements|input|interface|mutation|on|query|repeatable|scalar|schema|subscription|type|union)\b/,operator:/[!=|&]|\.{3}/,"property-query":/\w+(?=\s*\()/,object:/\w+(?=\s*\{)/,punctuation:/[!(){}\[\]:=,]/,property:/\w+/},r.hooks.add("after-tokenize",(function(e){if("graphql"===e.language)for(var t=e.tokens.filter((function(e){return"string"!=typeof e&&"comment"!==e.type&&"scalar"!==e.type})),n=0;n<t.length;){var a=t[n++];if("keyword"===a.type&&"mutation"===a.content){var r=[];if(d(["definition-mutation","punctuation"])&&"("===u(1).content){n+=2;var o=f(/^\($/,/^\)$/);if(-1===o)continue;for(;n<o;n++){var s=u(0);"variable"===s.type&&(p(s,"variable-input"),r.push(s.content))}n=o+1}if(d(["punctuation","property-query"])&&"{"===u(0).content&&(n++,p(u(0),"property-mutation"),r.length>0)){var i=f(/^\{$/,/^\}$/);if(-1===i)continue;for(var l=n;l<i;l++){var c=t[l];"variable"===c.type&&r.indexOf(c.content)>=0&&p(c,"variable-input")}}}}function u(e){return t[n+e]}function d(e,t){t=t||0;for(var n=0;n<e.length;n++){var a=u(n+t);if(!a||a.type!==e[n])return!1}return!0}function f(e,a){for(var r=1,o=n;o<t.length;o++){var s=t[o],i=s.content;if("punctuation"===s.type&&"string"==typeof i)if(e.test(i))r++;else if(a.test(i)&&0===--r)return o}return-1}function p(e,t){var n=e.alias;n?Array.isArray(n)||(e.alias=n=[n]):e.alias=n=[],n.push(t)}})),r.languages.sql={comment:{pattern:/(^|[^\\])(?:\/\*[\s\S]*?\*\/|(?:--|\/\/|#).*)/,lookbehind:!0},variable:[{pattern:/@(["'`])(?:\\[\s\S]|(?!\1)[^\\])+\1/,greedy:!0},/@[\w.$]+/],string:{pattern:/(^|[^@\\])("|')(?:\\[\s\S]|(?!\2)[^\\]|\2\2)*\2/,greedy:!0,lookbehind:!0},identifier:{pattern:/(^|[^@\\])`(?:\\[\s\S]|[^`\\]|``)*`/,greedy:!0,lookbehind:!0,inside:{punctuation:/^`|`$/}},function:/\b(?:AVG|COUNT|FIRST|FORMAT|LAST|LCASE|LEN|MAX|MID|MIN|MOD|NOW|ROUND|SUM|UCASE)(?=\s*\()/i,keyword:/\b(?:ACTION|ADD|AFTER|ALGORITHM|ALL|ALTER|ANALYZE|ANY|APPLY|AS|ASC|AUTHORIZATION|AUTO_INCREMENT|BACKUP|BDB|BEGIN|BERKELEYDB|BIGINT|BINARY|BIT|BLOB|BOOL|BOOLEAN|BREAK|BROWSE|BTREE|BULK|BY|CALL|CASCADED?|CASE|CHAIN|CHAR(?:ACTER|SET)?|CHECK(?:POINT)?|CLOSE|CLUSTERED|COALESCE|COLLATE|COLUMNS?|COMMENT|COMMIT(?:TED)?|COMPUTE|CONNECT|CONSISTENT|CONSTRAINT|CONTAINS(?:TABLE)?|CONTINUE|CONVERT|CREATE|CROSS|CURRENT(?:_DATE|_TIME|_TIMESTAMP|_USER)?|CURSOR|CYCLE|DATA(?:BASES?)?|DATE(?:TIME)?|DAY|DBCC|DEALLOCATE|DEC|DECIMAL|DECLARE|DEFAULT|DEFINER|DELAYED|DELETE|DELIMITERS?|DENY|DESC|DESCRIBE|DETERMINISTIC|DISABLE|DISCARD|DISK|DISTINCT|DISTINCTROW|DISTRIBUTED|DO|DOUBLE|DROP|DUMMY|DUMP(?:FILE)?|DUPLICATE|ELSE(?:IF)?|ENABLE|ENCLOSED|END|ENGINE|ENUM|ERRLVL|ERRORS|ESCAPED?|EXCEPT|EXEC(?:UTE)?|EXISTS|EXIT|EXPLAIN|EXTENDED|FETCH|FIELDS|FILE|FILLFACTOR|FIRST|FIXED|FLOAT|FOLLOWING|FOR(?: EACH ROW)?|FORCE|FOREIGN|FREETEXT(?:TABLE)?|FROM|FULL|FUNCTION|GEOMETRY(?:COLLECTION)?|GLOBAL|GOTO|GRANT|GROUP|HANDLER|HASH|HAVING|HOLDLOCK|HOUR|IDENTITY(?:COL|_INSERT)?|IF|IGNORE|IMPORT|INDEX|INFILE|INNER|INNODB|INOUT|INSERT|INT|INTEGER|INTERSECT|INTERVAL|INTO|INVOKER|ISOLATION|ITERATE|JOIN|KEYS?|KILL|LANGUAGE|LAST|LEAVE|LEFT|LEVEL|LIMIT|LINENO|LINES|LINESTRING|LOAD|LOCAL|LOCK|LONG(?:BLOB|TEXT)|LOOP|MATCH(?:ED)?|MEDIUM(?:BLOB|INT|TEXT)|MERGE|MIDDLEINT|MINUTE|MODE|MODIFIES|MODIFY|MONTH|MULTI(?:LINESTRING|POINT|POLYGON)|NATIONAL|NATURAL|NCHAR|NEXT|NO|NONCLUSTERED|NULLIF|NUMERIC|OFF?|OFFSETS?|ON|OPEN(?:DATASOURCE|QUERY|ROWSET)?|OPTIMIZE|OPTION(?:ALLY)?|ORDER|OUT(?:ER|FILE)?|OVER|PARTIAL|PARTITION|PERCENT|PIVOT|PLAN|POINT|POLYGON|PRECEDING|PRECISION|PREPARE|PREV|PRIMARY|PRINT|PRIVILEGES|PROC(?:EDURE)?|PUBLIC|PURGE|QUICK|RAISERROR|READS?|REAL|RECONFIGURE|REFERENCES|RELEASE|RENAME|REPEAT(?:ABLE)?|REPLACE|REPLICATION|REQUIRE|RESIGNAL|RESTORE|RESTRICT|RETURN(?:ING|S)?|REVOKE|RIGHT|ROLLBACK|ROUTINE|ROW(?:COUNT|GUIDCOL|S)?|RTREE|RULE|SAVE(?:POINT)?|SCHEMA|SECOND|SELECT|SERIAL(?:IZABLE)?|SESSION(?:_USER)?|SET(?:USER)?|SHARE|SHOW|SHUTDOWN|SIMPLE|SMALLINT|SNAPSHOT|SOME|SONAME|SQL|START(?:ING)?|STATISTICS|STATUS|STRIPED|SYSTEM_USER|TABLES?|TABLESPACE|TEMP(?:ORARY|TABLE)?|TERMINATED|TEXT(?:SIZE)?|THEN|TIME(?:STAMP)?|TINY(?:BLOB|INT|TEXT)|TOP?|TRAN(?:SACTIONS?)?|TRIGGER|TRUNCATE|TSEQUAL|TYPES?|UNBOUNDED|UNCOMMITTED|UNDEFINED|UNION|UNIQUE|UNLOCK|UNPIVOT|UNSIGNED|UPDATE(?:TEXT)?|USAGE|USE|USER|USING|VALUES?|VAR(?:BINARY|CHAR|CHARACTER|YING)|VIEW|WAITFOR|WARNINGS|WHEN|WHERE|WHILE|WITH(?: ROLLUP|IN)?|WORK|WRITE(?:TEXT)?|YEAR)\b/i,boolean:/\b(?:FALSE|NULL|TRUE)\b/i,number:/\b0x[\da-f]+\b|\b\d+(?:\.\d*)?|\B\.\d+\b/i,operator:/[-+*\/=%^~]|&&?|\|\|?|!=?|<(?:=>?|<|>)?|>[>=]?|\b(?:AND|BETWEEN|DIV|ILIKE|IN|IS|LIKE|NOT|OR|REGEXP|RLIKE|SOUNDS LIKE|XOR)\b/i,punctuation:/[;[\]()`,.]/},function(e){var t=e.languages.javascript["template-string"],n=t.pattern.source,a=t.inside.interpolation,r=a.inside["interpolation-punctuation"],o=a.pattern.source;function s(t,a){if(e.languages[t])return{pattern:RegExp("((?:"+a+")\\s*)"+n),lookbehind:!0,greedy:!0,inside:{"template-punctuation":{pattern:/^`|`$/,alias:"string"},"embedded-code":{pattern:/[\s\S]+/,alias:t}}}}function i(e,t){return"___"+t.toUpperCase()+"_"+e+"___"}function l(t,n,a){var r={code:t,grammar:n,language:a};return e.hooks.run("before-tokenize",r),r.tokens=e.tokenize(r.code,r.grammar),e.hooks.run("after-tokenize",r),r.tokens}function c(t){var n={};n["interpolation-punctuation"]=r;var o=e.tokenize(t,n);if(3===o.length){var s=[1,1];s.push.apply(s,l(o[1],e.languages.javascript,"javascript")),o.splice.apply(o,s)}return new e.Token("interpolation",o,a.alias,t)}function u(t,n,a){var r=e.tokenize(t,{interpolation:{pattern:RegExp(o),lookbehind:!0}}),s=0,u={},d=l(r.map((function(e){if("string"==typeof e)return e;for(var n,r=e.content;-1!==t.indexOf(n=i(s++,a)););return u[n]=r,n})).join(""),n,a),f=Object.keys(u);return s=0,function e(t){for(var n=0;n<t.length;n++){if(s>=f.length)return;var a=t[n];if("string"==typeof a||"string"==typeof a.content){var r=f[s],o="string"==typeof a?a:a.content,i=o.indexOf(r);if(-1!==i){++s;var l=o.substring(0,i),d=c(u[r]),p=o.substring(i+r.length),m=[];if(l&&m.push(l),m.push(d),p){var g=[p];e(g),m.push.apply(m,g)}"string"==typeof a?(t.splice.apply(t,[n,1].concat(m)),n+=m.length-1):a.content=m}}else{var h=a.content;Array.isArray(h)?e(h):e([h])}}}(d),new e.Token(a,d,"language-"+a,t)}e.languages.javascript["template-string"]=[s("css",/\b(?:styled(?:\([^)]*\))?(?:\s*\.\s*\w+(?:\([^)]*\))*)*|css(?:\s*\.\s*(?:global|resolve))?|createGlobalStyle|keyframes)/.source),s("html",/\bhtml|\.\s*(?:inner|outer)HTML\s*\+?=/.source),s("svg",/\bsvg/.source),s("markdown",/\b(?:markdown|md)/.source),s("graphql",/\b(?:gql|graphql(?:\s*\.\s*experimental)?)/.source),s("sql",/\bsql/.source),t].filter(Boolean);var d={javascript:!0,js:!0,typescript:!0,ts:!0,jsx:!0,tsx:!0};function f(e){return"string"==typeof e?e:Array.isArray(e)?e.map(f).join(""):f(e.content)}e.hooks.add("after-tokenize",(function(t){t.language in d&&function t(n){for(var a=0,r=n.length;a<r;a++){var o=n[a];if("string"!=typeof o){var s=o.content;if(Array.isArray(s))if("template-string"===o.type){var i=s[1];if(3===s.length&&"string"!=typeof i&&"embedded-code"===i.type){var l=f(i),c=i.alias,d=Array.isArray(c)?c[0]:c,p=e.languages[d];if(!p)continue;s[1]=u(l,p,d)}}else t(s);else"string"!=typeof s&&t([s])}}}(t.tokens)}))}(r),function(e){e.languages.typescript=e.languages.extend("javascript",{"class-name":{pattern:/(\b(?:class|extends|implements|instanceof|interface|new|type)\s+)(?!keyof\b)(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?:\s*<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>)?/,lookbehind:!0,greedy:!0,inside:null},builtin:/\b(?:Array|Function|Promise|any|boolean|console|never|number|string|symbol|unknown)\b/}),e.languages.typescript.keyword.push(/\b(?:abstract|declare|is|keyof|readonly|require)\b/,/\b(?:asserts|infer|interface|module|namespace|type)\b(?=\s*(?:[{_$a-zA-Z\xA0-\uFFFF]|$))/,/\btype\b(?=\s*(?:[\{*]|$))/),delete e.languages.typescript.parameter,delete e.languages.typescript["literal-property"];var t=e.languages.extend("typescript",{});delete t["class-name"],e.languages.typescript["class-name"].inside=t,e.languages.insertBefore("typescript","function",{decorator:{pattern:/@[$\w\xA0-\uFFFF]+/,inside:{at:{pattern:/^@/,alias:"operator"},function:/^[\s\S]+/}},"generic-function":{pattern:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s*<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>(?=\s*\()/,greedy:!0,inside:{function:/^#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*/,generic:{pattern:/<[\s\S]+/,alias:"class-name",inside:t}}}}),e.languages.ts=e.languages.typescript}(r),function(e){function t(e,t){return RegExp(e.replace(/<ID>/g,(function(){return/(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*/.source})),t)}e.languages.insertBefore("javascript","function-variable",{"method-variable":{pattern:RegExp("(\\.\\s*)"+e.languages.javascript["function-variable"].pattern.source),lookbehind:!0,alias:["function-variable","method","function","property-access"]}}),e.languages.insertBefore("javascript","function",{method:{pattern:RegExp("(\\.\\s*)"+e.languages.javascript.function.source),lookbehind:!0,alias:["function","property-access"]}}),e.languages.insertBefore("javascript","constant",{"known-class-name":[{pattern:/\b(?:(?:Float(?:32|64)|(?:Int|Uint)(?:8|16|32)|Uint8Clamped)?Array|ArrayBuffer|BigInt|Boolean|DataView|Date|Error|Function|Intl|JSON|(?:Weak)?(?:Map|Set)|Math|Number|Object|Promise|Proxy|Reflect|RegExp|String|Symbol|WebAssembly)\b/,alias:"class-name"},{pattern:/\b(?:[A-Z]\w*)Error\b/,alias:"class-name"}]}),e.languages.insertBefore("javascript","keyword",{imports:{pattern:t(/(\bimport\b\s*)(?:<ID>(?:\s*,\s*(?:\*\s*as\s+<ID>|\{[^{}]*\}))?|\*\s*as\s+<ID>|\{[^{}]*\})(?=\s*\bfrom\b)/.source),lookbehind:!0,inside:e.languages.javascript},exports:{pattern:t(/(\bexport\b\s*)(?:\*(?:\s*as\s+<ID>)?(?=\s*\bfrom\b)|\{[^{}]*\})/.source),lookbehind:!0,inside:e.languages.javascript}}),e.languages.javascript.keyword.unshift({pattern:/\b(?:as|default|export|from|import)\b/,alias:"module"},{pattern:/\b(?:await|break|catch|continue|do|else|finally|for|if|return|switch|throw|try|while|yield)\b/,alias:"control-flow"},{pattern:/\bnull\b/,alias:["null","nil"]},{pattern:/\bundefined\b/,alias:"nil"}),e.languages.insertBefore("javascript","operator",{spread:{pattern:/\.{3}/,alias:"operator"},arrow:{pattern:/=>/,alias:"operator"}}),e.languages.insertBefore("javascript","punctuation",{"property-access":{pattern:t(/(\.\s*)#?<ID>/.source),lookbehind:!0},"maybe-class-name":{pattern:/(^|[^$\w\xA0-\uFFFF])[A-Z][$\w\xA0-\uFFFF]+/,lookbehind:!0},dom:{pattern:/\b(?:document|(?:local|session)Storage|location|navigator|performance|window)\b/,alias:"variable"},console:{pattern:/\bconsole(?=\s*\.)/,alias:"class-name"}});for(var n=["function","function-variable","method","method-variable","property-access"],a=0;a<n.length;a++){var r=n[a],o=e.languages.javascript[r];"RegExp"===e.util.type(o)&&(o=e.languages.javascript[r]={pattern:o});var s=o.inside||{};o.inside=s,s["maybe-class-name"]=/^[A-Z][\s\S]*/}}(r),function(e){var t=e.util.clone(e.languages.javascript),n=/(?:\s|\/\/.*(?!.)|\/\*(?:[^*]|\*(?!\/))\*\/)/.source,a=/(?:\{(?:\{(?:\{[^{}]*\}|[^{}])*\}|[^{}])*\})/.source,r=/(?:\{<S>*\.{3}(?:[^{}]|<BRACES>)*\})/.source;function o(e,t){return e=e.replace(/<S>/g,(function(){return n})).replace(/<BRACES>/g,(function(){return a})).replace(/<SPREAD>/g,(function(){return r})),RegExp(e,t)}r=o(r).source,e.languages.jsx=e.languages.extend("markup",t),e.languages.jsx.tag.pattern=o(/<\/?(?:[\w.:-]+(?:<S>+(?:[\w.:$-]+(?:=(?:"(?:\\[\s\S]|[^\\"])*"|'(?:\\[\s\S]|[^\\'])*'|[^\s{'"/>=]+|<BRACES>))?|<SPREAD>))*<S>*\/?)?>/.source),e.languages.jsx.tag.inside.tag.pattern=/^<\/?[^\s>\/]*/,e.languages.jsx.tag.inside["attr-value"].pattern=/=(?!\{)(?:"(?:\\[\s\S]|[^\\"])*"|'(?:\\[\s\S]|[^\\'])*'|[^\s'">]+)/,e.languages.jsx.tag.inside.tag.inside["class-name"]=/^[A-Z]\w*(?:\.[A-Z]\w*)*$/,e.languages.jsx.tag.inside.comment=t.comment,e.languages.insertBefore("inside","attr-name",{spread:{pattern:o(/<SPREAD>/.source),inside:e.languages.jsx}},e.languages.jsx.tag),e.languages.insertBefore("inside","special-attr",{script:{pattern:o(/=<BRACES>/.source),alias:"language-javascript",inside:{"script-punctuation":{pattern:/^=(?=\{)/,alias:"punctuation"},rest:e.languages.jsx}}},e.languages.jsx.tag);var s=function(e){return e?"string"==typeof e?e:"string"==typeof e.content?e.content:e.content.map(s).join(""):""},i=function(t){for(var n=[],a=0;a<t.length;a++){var r=t[a],o=!1;if("string"!=typeof r&&("tag"===r.type&&r.content[0]&&"tag"===r.content[0].type?"</"===r.content[0].content[0].content?n.length>0&&n[n.length-1].tagName===s(r.content[0].content[1])&&n.pop():"/>"===r.content[r.content.length-1].content||n.push({tagName:s(r.content[0].content[1]),openedBraces:0}):n.length>0&&"punctuation"===r.type&&"{"===r.content?n[n.length-1].openedBraces++:n.length>0&&n[n.length-1].openedBraces>0&&"punctuation"===r.type&&"}"===r.content?n[n.length-1].openedBraces--:o=!0),(o||"string"==typeof r)&&n.length>0&&0===n[n.length-1].openedBraces){var l=s(r);a<t.length-1&&("string"==typeof t[a+1]||"plain-text"===t[a+1].type)&&(l+=s(t[a+1]),t.splice(a+1,1)),a>0&&("string"==typeof t[a-1]||"plain-text"===t[a-1].type)&&(l=s(t[a-1])+l,t.splice(a-1,1),a--),t[a]=new e.Token("plain-text",l,null,l)}r.content&&"string"!=typeof r.content&&i(r.content)}};e.hooks.add("after-tokenize",(function(e){"jsx"!==e.language&&"tsx"!==e.language||i(e.tokens)}))}(r),function(e){e.languages.diff={coord:[/^(?:\*{3}|-{3}|\+{3}).*$/m,/^@@.*@@$/m,/^\d.*$/m]};var t={"deleted-sign":"-","deleted-arrow":"<","inserted-sign":"+","inserted-arrow":">",unchanged:" ",diff:"!"};Object.keys(t).forEach((function(n){var a=t[n],r=[];/^\w+$/.test(n)||r.push(/\w+/.exec(n)[0]),"diff"===n&&r.push("bold"),e.languages.diff[n]={pattern:RegExp("^(?:["+a+"].*(?:\r\n?|\n|(?![\\s\\S])))+","m"),alias:r,inside:{line:{pattern:/(.)(?=[\s\S]).*(?:\r\n?|\n)?/,lookbehind:!0},prefix:{pattern:/[\s\S]/,alias:/\w+/.exec(n)[0]}}}})),Object.defineProperty(e.languages.diff,"PREFIXES",{value:t})}(r),r.languages.git={comment:/^#.*/m,deleted:/^[-\u2013].*/m,inserted:/^\+.*/m,string:/("|')(?:\\.|(?!\1)[^\\\r\n])*\1/,command:{pattern:/^.*\$ git .*$/m,inside:{parameter:/\s--?\w+/}},coord:/^@@.*@@$/m,"commit-sha1":/^commit \w{40}$/m},r.languages.go=r.languages.extend("clike",{string:{pattern:/(^|[^\\])"(?:\\.|[^"\\\r\n])*"|`[^`]*`/,lookbehind:!0,greedy:!0},keyword:/\b(?:break|case|chan|const|continue|default|defer|else|fallthrough|for|func|go(?:to)?|if|import|interface|map|package|range|return|select|struct|switch|type|var)\b/,boolean:/\b(?:_|false|iota|nil|true)\b/,number:[/\b0(?:b[01_]+|o[0-7_]+)i?\b/i,/\b0x(?:[a-f\d_]+(?:\.[a-f\d_]*)?|\.[a-f\d_]+)(?:p[+-]?\d+(?:_\d+)*)?i?(?!\w)/i,/(?:\b\d[\d_]*(?:\.[\d_]*)?|\B\.\d[\d_]*)(?:e[+-]?[\d_]+)?i?(?!\w)/i],operator:/[*\/%^!=]=?|\+[=+]?|-[=-]?|\|[=|]?|&(?:=|&|\^=?)?|>(?:>=?|=)?|<(?:<=?|=|-)?|:=|\.\.\./,builtin:/\b(?:append|bool|byte|cap|close|complex|complex(?:64|128)|copy|delete|error|float(?:32|64)|u?int(?:8|16|32|64)?|imag|len|make|new|panic|print(?:ln)?|real|recover|rune|string|uintptr)\b/}),r.languages.insertBefore("go","string",{char:{pattern:/'(?:\\.|[^'\\\r\n]){0,10}'/,greedy:!0}}),delete r.languages.go["class-name"],function(e){function t(e,t){return"___"+e.toUpperCase()+t+"___"}Object.defineProperties(e.languages["markup-templating"]={},{buildPlaceholders:{value:function(n,a,r,o){if(n.language===a){var s=n.tokenStack=[];n.code=n.code.replace(r,(function(e){if("function"==typeof o&&!o(e))return e;for(var r,i=s.length;-1!==n.code.indexOf(r=t(a,i));)++i;return s[i]=e,r})),n.grammar=e.languages.markup}}},tokenizePlaceholders:{value:function(n,a){if(n.language===a&&n.tokenStack){n.grammar=e.languages[a];var r=0,o=Object.keys(n.tokenStack);!function s(i){for(var l=0;l<i.length&&!(r>=o.length);l++){var c=i[l];if("string"==typeof c||c.content&&"string"==typeof c.content){var u=o[r],d=n.tokenStack[u],f="string"==typeof c?c:c.content,p=t(a,u),m=f.indexOf(p);if(m>-1){++r;var g=f.substring(0,m),h=new e.Token(a,e.tokenize(d,n.grammar),"language-"+a,d),b=f.substring(m+p.length),v=[];g&&v.push.apply(v,s([g])),v.push(h),b&&v.push.apply(v,s([b])),"string"==typeof c?i.splice.apply(i,[l,1].concat(v)):c.content=v}}else c.content&&s(c.content)}return i}(n.tokens)}}}})}(r),function(e){e.languages.handlebars={comment:/\{\{![\s\S]*?\}\}/,delimiter:{pattern:/^\{\{\{?|\}\}\}?$/,alias:"punctuation"},string:/(["'])(?:\\.|(?!\1)[^\\\r\n])*\1/,number:/\b0x[\dA-Fa-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:[Ee][+-]?\d+)?/,boolean:/\b(?:false|true)\b/,block:{pattern:/^(\s*(?:~\s*)?)[#\/]\S+?(?=\s*(?:~\s*)?$|\s)/,lookbehind:!0,alias:"keyword"},brackets:{pattern:/\[[^\]]+\]/,inside:{punctuation:/\[|\]/,variable:/[\s\S]+/}},punctuation:/[!"#%&':()*+,.\/;<=>@\[\\\]^`{|}~]/,variable:/[^!"#%&'()*+,\/;<=>@\[\\\]^`{|}~\s]+/},e.hooks.add("before-tokenize",(function(t){e.languages["markup-templating"].buildPlaceholders(t,"handlebars",/\{\{\{[\s\S]+?\}\}\}|\{\{[\s\S]+?\}\}/g)})),e.hooks.add("after-tokenize",(function(t){e.languages["markup-templating"].tokenizePlaceholders(t,"handlebars")})),e.languages.hbs=e.languages.handlebars}(r),r.languages.json={property:{pattern:/(^|[^\\])"(?:\\.|[^\\"\r\n])*"(?=\s*:)/,lookbehind:!0,greedy:!0},string:{pattern:/(^|[^\\])"(?:\\.|[^\\"\r\n])*"(?!\s*:)/,lookbehind:!0,greedy:!0},comment:{pattern:/\/\/.*|\/\*[\s\S]*?(?:\*\/|$)/,greedy:!0},number:/-?\b\d+(?:\.\d+)?(?:e[+-]?\d+)?\b/i,punctuation:/[{}[\],]/,operator:/:/,boolean:/\b(?:false|true)\b/,null:{pattern:/\bnull\b/,alias:"keyword"}},r.languages.webmanifest=r.languages.json,r.languages.less=r.languages.extend("css",{comment:[/\/\*[\s\S]*?\*\//,{pattern:/(^|[^\\])\/\/.*/,lookbehind:!0}],atrule:{pattern:/@[\w-](?:\((?:[^(){}]|\([^(){}]*\))*\)|[^(){};\s]|\s+(?!\s))*?(?=\s*\{)/,inside:{punctuation:/[:()]/}},selector:{pattern:/(?:@\{[\w-]+\}|[^{};\s@])(?:@\{[\w-]+\}|\((?:[^(){}]|\([^(){}]*\))*\)|[^(){};@\s]|\s+(?!\s))*?(?=\s*\{)/,inside:{variable:/@+[\w-]+/}},property:/(?:@\{[\w-]+\}|[\w-])+(?:\+_?)?(?=\s*:)/,operator:/[+\-*\/]/}),r.languages.insertBefore("less","property",{variable:[{pattern:/@[\w-]+\s*:/,inside:{punctuation:/:/}},/@@?[\w-]+/],"mixin-usage":{pattern:/([{;]\s*)[.#](?!\d)[\w-].*?(?=[(;])/,lookbehind:!0,alias:"function"}}),r.languages.makefile={comment:{pattern:/(^|[^\\])#(?:\\(?:\r\n|[\s\S])|[^\\\r\n])*/,lookbehind:!0},string:{pattern:/(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},"builtin-target":{pattern:/\.[A-Z][^:#=\s]+(?=\s*:(?!=))/,alias:"builtin"},target:{pattern:/^(?:[^:=\s]|[ \t]+(?![\s:]))+(?=\s*:(?!=))/m,alias:"symbol",inside:{variable:/\$+(?:(?!\$)[^(){}:#=\s]+|(?=[({]))/}},variable:/\$+(?:(?!\$)[^(){}:#=\s]+|\([@*%<^+?][DF]\)|(?=[({]))/,keyword:/-include\b|\b(?:define|else|endef|endif|export|ifn?def|ifn?eq|include|override|private|sinclude|undefine|unexport|vpath)\b/,function:{pattern:/(\()(?:abspath|addsuffix|and|basename|call|dir|error|eval|file|filter(?:-out)?|findstring|firstword|flavor|foreach|guile|if|info|join|lastword|load|notdir|or|origin|patsubst|realpath|shell|sort|strip|subst|suffix|value|warning|wildcard|word(?:list|s)?)(?=[ \t])/,lookbehind:!0},operator:/(?:::|[?:+!])?=|[|@]/,punctuation:/[:;(){}]/},r.languages.objectivec=r.languages.extend("c",{string:{pattern:/@?"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"/,greedy:!0},keyword:/\b(?:asm|auto|break|case|char|const|continue|default|do|double|else|enum|extern|float|for|goto|if|in|inline|int|long|register|return|self|short|signed|sizeof|static|struct|super|switch|typedef|typeof|union|unsigned|void|volatile|while)\b|(?:@interface|@end|@implementation|@protocol|@class|@public|@protected|@private|@property|@try|@catch|@finally|@throw|@synthesize|@dynamic|@selector)\b/,operator:/-[->]?|\+\+?|!=?|<<?=?|>>?=?|==?|&&?|\|\|?|[~^%?*\/@]/}),delete r.languages.objectivec["class-name"],r.languages.objc=r.languages.objectivec,r.languages.ocaml={comment:{pattern:/\(\*[\s\S]*?\*\)/,greedy:!0},char:{pattern:/'(?:[^\\\r\n']|\\(?:.|[ox]?[0-9a-f]{1,3}))'/i,greedy:!0},string:[{pattern:/"(?:\\(?:[\s\S]|\r\n)|[^\\\r\n"])*"/,greedy:!0},{pattern:/\{([a-z_]*)\|[\s\S]*?\|\1\}/,greedy:!0}],number:[/\b(?:0b[01][01_]*|0o[0-7][0-7_]*)\b/i,/\b0x[a-f0-9][a-f0-9_]*(?:\.[a-f0-9_]*)?(?:p[+-]?\d[\d_]*)?(?!\w)/i,/\b\d[\d_]*(?:\.[\d_]*)?(?:e[+-]?\d[\d_]*)?(?!\w)/i],directive:{pattern:/\B#\w+/,alias:"property"},label:{pattern:/\B~\w+/,alias:"property"},"type-variable":{pattern:/\B'\w+/,alias:"function"},variant:{pattern:/`\w+/,alias:"symbol"},keyword:/\b(?:as|assert|begin|class|constraint|do|done|downto|else|end|exception|external|for|fun|function|functor|if|in|include|inherit|initializer|lazy|let|match|method|module|mutable|new|nonrec|object|of|open|private|rec|sig|struct|then|to|try|type|val|value|virtual|when|where|while|with)\b/,boolean:/\b(?:false|true)\b/,"operator-like-punctuation":{pattern:/\[[<>|]|[>|]\]|\{<|>\}/,alias:"punctuation"},operator:/\.[.~]|:[=>]|[=<>@^|&+\-*\/$%!?~][!$%&*+\-.\/:<=>?@^|~]*|\b(?:and|asr|land|lor|lsl|lsr|lxor|mod|or)\b/,punctuation:/;;|::|[(){}\[\].,:;#]|\b_\b/},r.languages.python={comment:{pattern:/(^|[^\\])#.*/,lookbehind:!0,greedy:!0},"string-interpolation":{pattern:/(?:f|fr|rf)(?:("""|''')[\s\S]*?\1|("|')(?:\\.|(?!\2)[^\\\r\n])*\2)/i,greedy:!0,inside:{interpolation:{pattern:/((?:^|[^{])(?:\{\{)*)\{(?!\{)(?:[^{}]|\{(?!\{)(?:[^{}]|\{(?!\{)(?:[^{}])+\})+\})+\}/,lookbehind:!0,inside:{"format-spec":{pattern:/(:)[^:(){}]+(?=\}$)/,lookbehind:!0},"conversion-option":{pattern:/![sra](?=[:}]$)/,alias:"punctuation"},rest:null}},string:/[\s\S]+/}},"triple-quoted-string":{pattern:/(?:[rub]|br|rb)?("""|''')[\s\S]*?\1/i,greedy:!0,alias:"string"},string:{pattern:/(?:[rub]|br|rb)?("|')(?:\\.|(?!\1)[^\\\r\n])*\1/i,greedy:!0},function:{pattern:/((?:^|\s)def[ \t]+)[a-zA-Z_]\w*(?=\s*\()/g,lookbehind:!0},"class-name":{pattern:/(\bclass\s+)\w+/i,lookbehind:!0},decorator:{pattern:/(^[\t ]*)@\w+(?:\.\w+)*/m,lookbehind:!0,alias:["annotation","punctuation"],inside:{punctuation:/\./}},keyword:/\b(?:_(?=\s*:)|and|as|assert|async|await|break|case|class|continue|def|del|elif|else|except|exec|finally|for|from|global|if|import|in|is|lambda|match|nonlocal|not|or|pass|print|raise|return|try|while|with|yield)\b/,builtin:/\b(?:__import__|abs|all|any|apply|ascii|basestring|bin|bool|buffer|bytearray|bytes|callable|chr|classmethod|cmp|coerce|compile|complex|delattr|dict|dir|divmod|enumerate|eval|execfile|file|filter|float|format|frozenset|getattr|globals|hasattr|hash|help|hex|id|input|int|intern|isinstance|issubclass|iter|len|list|locals|long|map|max|memoryview|min|next|object|oct|open|ord|pow|property|range|raw_input|reduce|reload|repr|reversed|round|set|setattr|slice|sorted|staticmethod|str|sum|super|tuple|type|unichr|unicode|vars|xrange|zip)\b/,boolean:/\b(?:False|None|True)\b/,number:/\b0(?:b(?:_?[01])+|o(?:_?[0-7])+|x(?:_?[a-f0-9])+)\b|(?:\b\d+(?:_\d+)*(?:\.(?:\d+(?:_\d+)*)?)?|\B\.\d+(?:_\d+)*)(?:e[+-]?\d+(?:_\d+)*)?j?(?!\w)/i,operator:/[-+%=]=?|!=|:=|\*\*?=?|\/\/?=?|<[<=>]?|>[=>]?|[&|^~]/,punctuation:/[{}[\];(),.:]/},r.languages.python["string-interpolation"].inside.interpolation.inside.rest=r.languages.python,r.languages.py=r.languages.python,r.languages.reason=r.languages.extend("clike",{string:{pattern:/"(?:\\(?:\r\n|[\s\S])|[^\\\r\n"])*"/,greedy:!0},"class-name":/\b[A-Z]\w*/,keyword:/\b(?:and|as|assert|begin|class|constraint|do|done|downto|else|end|exception|external|for|fun|function|functor|if|in|include|inherit|initializer|lazy|let|method|module|mutable|new|nonrec|object|of|open|or|private|rec|sig|struct|switch|then|to|try|type|val|virtual|when|while|with)\b/,operator:/\.{3}|:[:=]|\|>|->|=(?:==?|>)?|<=?|>=?|[|^?'#!~`]|[+\-*\/]\.?|\b(?:asr|land|lor|lsl|lsr|lxor|mod)\b/}),r.languages.insertBefore("reason","class-name",{char:{pattern:/'(?:\\x[\da-f]{2}|\\o[0-3][0-7][0-7]|\\\d{3}|\\.|[^'\\\r\n])'/,greedy:!0},constructor:/\b[A-Z]\w*\b(?!\s*\.)/,label:{pattern:/\b[a-z]\w*(?=::)/,alias:"symbol"}}),delete r.languages.reason.function,function(e){e.languages.sass=e.languages.extend("css",{comment:{pattern:/^([ \t]*)\/[\/*].*(?:(?:\r?\n|\r)\1[ \t].+)*/m,lookbehind:!0,greedy:!0}}),e.languages.insertBefore("sass","atrule",{"atrule-line":{pattern:/^(?:[ \t]*)[@+=].+/m,greedy:!0,inside:{atrule:/(?:@[\w-]+|[+=])/}}}),delete e.languages.sass.atrule;var t=/\$[-\w]+|#\{\$[-\w]+\}/,n=[/[+*\/%]|[=!]=|<=?|>=?|\b(?:and|not|or)\b/,{pattern:/(\s)-(?=\s)/,lookbehind:!0}];e.languages.insertBefore("sass","property",{"variable-line":{pattern:/^[ \t]*\$.+/m,greedy:!0,inside:{punctuation:/:/,variable:t,operator:n}},"property-line":{pattern:/^[ \t]*(?:[^:\s]+ *:.*|:[^:\s].*)/m,greedy:!0,inside:{property:[/[^:\s]+(?=\s*:)/,{pattern:/(:)[^:\s]+/,lookbehind:!0}],punctuation:/:/,variable:t,operator:n,important:e.languages.sass.important}}}),delete e.languages.sass.property,delete e.languages.sass.important,e.languages.insertBefore("sass","punctuation",{selector:{pattern:/^([ \t]*)\S(?:,[^,\r\n]+|[^,\r\n]*)(?:,[^,\r\n]+)*(?:,(?:\r?\n|\r)\1[ \t]+\S(?:,[^,\r\n]+|[^,\r\n]*)(?:,[^,\r\n]+)*)*/m,lookbehind:!0,greedy:!0}})}(r),r.languages.scss=r.languages.extend("css",{comment:{pattern:/(^|[^\\])(?:\/\*[\s\S]*?\*\/|\/\/.*)/,lookbehind:!0},atrule:{pattern:/@[\w-](?:\([^()]+\)|[^()\s]|\s+(?!\s))*?(?=\s+[{;])/,inside:{rule:/@[\w-]+/}},url:/(?:[-a-z]+-)?url(?=\()/i,selector:{pattern:/(?=\S)[^@;{}()]?(?:[^@;{}()\s]|\s+(?!\s)|#\{\$[-\w]+\})+(?=\s*\{(?:\}|\s|[^}][^:{}]*[:{][^}]))/,inside:{parent:{pattern:/&/,alias:"important"},placeholder:/%[-\w]+/,variable:/\$[-\w]+|#\{\$[-\w]+\}/}},property:{pattern:/(?:[-\w]|\$[-\w]|#\{\$[-\w]+\})+(?=\s*:)/,inside:{variable:/\$[-\w]+|#\{\$[-\w]+\}/}}}),r.languages.insertBefore("scss","atrule",{keyword:[/@(?:content|debug|each|else(?: if)?|extend|for|forward|function|if|import|include|mixin|return|use|warn|while)\b/i,{pattern:/( )(?:from|through)(?= )/,lookbehind:!0}]}),r.languages.insertBefore("scss","important",{variable:/\$[-\w]+|#\{\$[-\w]+\}/}),r.languages.insertBefore("scss","function",{"module-modifier":{pattern:/\b(?:as|hide|show|with)\b/i,alias:"keyword"},placeholder:{pattern:/%[-\w]+/,alias:"selector"},statement:{pattern:/\B!(?:default|optional)\b/i,alias:"keyword"},boolean:/\b(?:false|true)\b/,null:{pattern:/\bnull\b/,alias:"keyword"},operator:{pattern:/(\s)(?:[-+*\/%]|[=!]=|<=?|>=?|and|not|or)(?=\s)/,lookbehind:!0}}),r.languages.scss.atrule.inside.rest=r.languages.scss,function(e){var t={pattern:/(\b\d+)(?:%|[a-z]+)/,lookbehind:!0},n={pattern:/(^|[^\w.-])-?(?:\d+(?:\.\d+)?|\.\d+)/,lookbehind:!0},a={comment:{pattern:/(^|[^\\])(?:\/\*[\s\S]*?\*\/|\/\/.*)/,lookbehind:!0},url:{pattern:/\burl\((["']?).*?\1\)/i,greedy:!0},string:{pattern:/("|')(?:(?!\1)[^\\\r\n]|\\(?:\r\n|[\s\S]))*\1/,greedy:!0},interpolation:null,func:null,important:/\B!(?:important|optional)\b/i,keyword:{pattern:/(^|\s+)(?:(?:else|for|if|return|unless)(?=\s|$)|@[\w-]+)/,lookbehind:!0},hexcode:/#[\da-f]{3,6}/i,color:[/\b(?:AliceBlue|AntiqueWhite|Aqua|Aquamarine|Azure|Beige|Bisque|Black|BlanchedAlmond|Blue|BlueViolet|Brown|BurlyWood|CadetBlue|Chartreuse|Chocolate|Coral|CornflowerBlue|Cornsilk|Crimson|Cyan|DarkBlue|DarkCyan|DarkGoldenRod|DarkGr[ae]y|DarkGreen|DarkKhaki|DarkMagenta|DarkOliveGreen|DarkOrange|DarkOrchid|DarkRed|DarkSalmon|DarkSeaGreen|DarkSlateBlue|DarkSlateGr[ae]y|DarkTurquoise|DarkViolet|DeepPink|DeepSkyBlue|DimGr[ae]y|DodgerBlue|FireBrick|FloralWhite|ForestGreen|Fuchsia|Gainsboro|GhostWhite|Gold|GoldenRod|Gr[ae]y|Green|GreenYellow|HoneyDew|HotPink|IndianRed|Indigo|Ivory|Khaki|Lavender|LavenderBlush|LawnGreen|LemonChiffon|LightBlue|LightCoral|LightCyan|LightGoldenRodYellow|LightGr[ae]y|LightGreen|LightPink|LightSalmon|LightSeaGreen|LightSkyBlue|LightSlateGr[ae]y|LightSteelBlue|LightYellow|Lime|LimeGreen|Linen|Magenta|Maroon|MediumAquaMarine|MediumBlue|MediumOrchid|MediumPurple|MediumSeaGreen|MediumSlateBlue|MediumSpringGreen|MediumTurquoise|MediumVioletRed|MidnightBlue|MintCream|MistyRose|Moccasin|NavajoWhite|Navy|OldLace|Olive|OliveDrab|Orange|OrangeRed|Orchid|PaleGoldenRod|PaleGreen|PaleTurquoise|PaleVioletRed|PapayaWhip|PeachPuff|Peru|Pink|Plum|PowderBlue|Purple|Red|RosyBrown|RoyalBlue|SaddleBrown|Salmon|SandyBrown|SeaGreen|SeaShell|Sienna|Silver|SkyBlue|SlateBlue|SlateGr[ae]y|Snow|SpringGreen|SteelBlue|Tan|Teal|Thistle|Tomato|Transparent|Turquoise|Violet|Wheat|White|WhiteSmoke|Yellow|YellowGreen)\b/i,{pattern:/\b(?:hsl|rgb)\(\s*\d{1,3}\s*,\s*\d{1,3}%?\s*,\s*\d{1,3}%?\s*\)\B|\b(?:hsl|rgb)a\(\s*\d{1,3}\s*,\s*\d{1,3}%?\s*,\s*\d{1,3}%?\s*,\s*(?:0|0?\.\d+|1)\s*\)\B/i,inside:{unit:t,number:n,function:/[\w-]+(?=\()/,punctuation:/[(),]/}}],entity:/\\[\da-f]{1,8}/i,unit:t,boolean:/\b(?:false|true)\b/,operator:[/~|[+!\/%<>?=]=?|[-:]=|\*[*=]?|\.{2,3}|&&|\|\||\B-\B|\b(?:and|in|is(?: a| defined| not|nt)?|not|or)\b/],number:n,punctuation:/[{}()\[\];:,]/};a.interpolation={pattern:/\{[^\r\n}:]+\}/,alias:"variable",inside:{delimiter:{pattern:/^\{|\}$/,alias:"punctuation"},rest:a}},a.func={pattern:/[\w-]+\([^)]*\).*/,inside:{function:/^[^(]+/,rest:a}},e.languages.stylus={"atrule-declaration":{pattern:/(^[ \t]*)@.+/m,lookbehind:!0,inside:{atrule:/^@[\w-]+/,rest:a}},"variable-declaration":{pattern:/(^[ \t]*)[\w$-]+\s*.?=[ \t]*(?:\{[^{}]*\}|\S.*|$)/m,lookbehind:!0,inside:{variable:/^\S+/,rest:a}},statement:{pattern:/(^[ \t]*)(?:else|for|if|return|unless)[ \t].+/m,lookbehind:!0,inside:{keyword:/^\S+/,rest:a}},"property-declaration":{pattern:/((?:^|\{)([ \t]*))(?:[\w-]|\{[^}\r\n]+\})+(?:\s*:\s*|[ \t]+)(?!\s)[^{\r\n]*(?:;|[^{\r\n,]$(?!(?:\r?\n|\r)(?:\{|\2[ \t])))/m,lookbehind:!0,inside:{property:{pattern:/^[^\s:]+/,inside:{interpolation:a.interpolation}},rest:a}},selector:{pattern:/(^[ \t]*)(?:(?=\S)(?:[^{}\r\n:()]|::?[\w-]+(?:\([^)\r\n]*\)|(?![\w-]))|\{[^}\r\n]+\})+)(?:(?:\r?\n|\r)(?:\1(?:(?=\S)(?:[^{}\r\n:()]|::?[\w-]+(?:\([^)\r\n]*\)|(?![\w-]))|\{[^}\r\n]+\})+)))*(?:,$|\{|(?=(?:\r?\n|\r)(?:\{|\1[ \t])))/m,lookbehind:!0,inside:{interpolation:a.interpolation,comment:a.comment,punctuation:/[{},]/}},func:a.func,string:a.string,comment:{pattern:/(^|[^\\])(?:\/\*[\s\S]*?\*\/|\/\/.*)/,lookbehind:!0,greedy:!0},interpolation:a.interpolation,punctuation:/[{}()\[\];:.]/}}(r),function(e){var t=e.util.clone(e.languages.typescript);e.languages.tsx=e.languages.extend("jsx",t),delete e.languages.tsx.parameter,delete e.languages.tsx["literal-property"];var n=e.languages.tsx.tag;n.pattern=RegExp(/(^|[^\w$]|(?=<\/))/.source+"(?:"+n.pattern.source+")",n.pattern.flags),n.lookbehind=!0}(r),r.languages.wasm={comment:[/\(;[\s\S]*?;\)/,{pattern:/;;.*/,greedy:!0}],string:{pattern:/"(?:\\[\s\S]|[^"\\])*"/,greedy:!0},keyword:[{pattern:/\b(?:align|offset)=/,inside:{operator:/=/}},{pattern:/\b(?:(?:f32|f64|i32|i64)(?:\.(?:abs|add|and|ceil|clz|const|convert_[su]\/i(?:32|64)|copysign|ctz|demote\/f64|div(?:_[su])?|eqz?|extend_[su]\/i32|floor|ge(?:_[su])?|gt(?:_[su])?|le(?:_[su])?|load(?:(?:8|16|32)_[su])?|lt(?:_[su])?|max|min|mul|neg?|nearest|or|popcnt|promote\/f32|reinterpret\/[fi](?:32|64)|rem_[su]|rot[lr]|shl|shr_[su]|sqrt|store(?:8|16|32)?|sub|trunc(?:_[su]\/f(?:32|64))?|wrap\/i64|xor))?|memory\.(?:grow|size))\b/,inside:{punctuation:/\./}},/\b(?:anyfunc|block|br(?:_if|_table)?|call(?:_indirect)?|data|drop|elem|else|end|export|func|get_(?:global|local)|global|if|import|local|loop|memory|module|mut|nop|offset|param|result|return|select|set_(?:global|local)|start|table|tee_local|then|type|unreachable)\b/],variable:/\$[\w!#$%&'*+\-./:<=>?@\\^`|~]+/,number:/[+-]?\b(?:\d(?:_?\d)*(?:\.\d(?:_?\d)*)?(?:[eE][+-]?\d(?:_?\d)*)?|0x[\da-fA-F](?:_?[\da-fA-F])*(?:\.[\da-fA-F](?:_?[\da-fA-D])*)?(?:[pP][+-]?\d(?:_?\d)*)?)\b|\binf\b|\bnan(?::0x[\da-fA-F](?:_?[\da-fA-D])*)?\b/,punctuation:/[()]/};const o=r},767:()=>{!function(e){for(var t=/\/\*(?:[^*/]|\*(?!\/)|\/(?!\*)|<self>)*\*\//.source,n=0;n<2;n++)t=t.replace(/<self>/g,(function(){return t}));t=t.replace(/<self>/g,(function(){return/[^\s\S]/.source})),e.languages.rust={comment:[{pattern:RegExp(/(^|[^\\])/.source+t),lookbehind:!0,greedy:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0,greedy:!0}],string:{pattern:/b?"(?:\\[\s\S]|[^\\"])*"|b?r(#*)"(?:[^"]|"(?!\1))*"\1/,greedy:!0},char:{pattern:/b?'(?:\\(?:x[0-7][\da-fA-F]|u\{(?:[\da-fA-F]_*){1,6}\}|.)|[^\\\r\n\t'])'/,greedy:!0},attribute:{pattern:/#!?\[(?:[^\[\]"]|"(?:\\[\s\S]|[^\\"])*")*\]/,greedy:!0,alias:"attr-name",inside:{string:null}},"closure-params":{pattern:/([=(,:]\s*|\bmove\s*)\|[^|]*\||\|[^|]*\|(?=\s*(?:\{|->))/,lookbehind:!0,greedy:!0,inside:{"closure-punctuation":{pattern:/^\||\|$/,alias:"punctuation"},rest:null}},"lifetime-annotation":{pattern:/'\w+/,alias:"symbol"},"fragment-specifier":{pattern:/(\$\w+:)[a-z]+/,lookbehind:!0,alias:"punctuation"},variable:/\$\w+/,"function-definition":{pattern:/(\bfn\s+)\w+/,lookbehind:!0,alias:"function"},"type-definition":{pattern:/(\b(?:enum|struct|trait|type|union)\s+)\w+/,lookbehind:!0,alias:"class-name"},"module-declaration":[{pattern:/(\b(?:crate|mod)\s+)[a-z][a-z_\d]*/,lookbehind:!0,alias:"namespace"},{pattern:/(\b(?:crate|self|super)\s*)::\s*[a-z][a-z_\d]*\b(?:\s*::(?:\s*[a-z][a-z_\d]*\s*::)*)?/,lookbehind:!0,alias:"namespace",inside:{punctuation:/::/}}],keyword:[/\b(?:Self|abstract|as|async|await|become|box|break|const|continue|crate|do|dyn|else|enum|extern|final|fn|for|if|impl|in|let|loop|macro|match|mod|move|mut|override|priv|pub|ref|return|self|static|struct|super|trait|try|type|typeof|union|unsafe|unsized|use|virtual|where|while|yield)\b/,/\b(?:bool|char|f(?:32|64)|[ui](?:8|16|32|64|128|size)|str)\b/],function:/\b[a-z_]\w*(?=\s*(?:::\s*<|\())/,macro:{pattern:/\b\w+!/,alias:"property"},constant:/\b[A-Z_][A-Z_\d]+\b/,"class-name":/\b[A-Z]\w*\b/,namespace:{pattern:/(?:\b[a-z][a-z_\d]*\s*::\s*)*\b[a-z][a-z_\d]*\s*::(?!\s*<)/,inside:{punctuation:/::/}},number:/\b(?:0x[\dA-Fa-f](?:_?[\dA-Fa-f])*|0o[0-7](?:_?[0-7])*|0b[01](?:_?[01])*|(?:(?:\d(?:_?\d)*)?\.)?\d(?:_?\d)*(?:[Ee][+-]?\d+)?)(?:_?(?:f32|f64|[iu](?:8|16|32|64|size)?))?\b/,boolean:/\b(?:false|true)\b/,punctuation:/->|\.\.=|\.{1,3}|::|[{}[\];(),:]/,operator:/[-+*\/%!^]=?|=[=>]?|&[&=]?|\|[|=]?|<<?=?|>>?=?|[@?]/},e.languages.rust["closure-params"].inside.rest=e.languages.rust,e.languages.rust.attribute.inside.string=e.languages.rust.string}(Prism)},9930:()=>{!function(e){var t=/(?:[\w-]+|'[^'\n\r]*'|"(?:\\.|[^\\"\r\n])*")/.source;function n(e){return e.replace(/__/g,(function(){return t}))}e.languages.toml={comment:{pattern:/#.*/,greedy:!0},table:{pattern:RegExp(n(/(^[\t ]*\[\s*(?:\[\s*)?)__(?:\s*\.\s*__)*(?=\s*\])/.source),"m"),lookbehind:!0,greedy:!0,alias:"class-name"},key:{pattern:RegExp(n(/(^[\t ]*|[{,]\s*)__(?:\s*\.\s*__)*(?=\s*=)/.source),"m"),lookbehind:!0,greedy:!0,alias:"property"},string:{pattern:/"""(?:\\[\s\S]|[^\\])*?"""|'''[\s\S]*?'''|'[^'\n\r]*'|"(?:\\.|[^\\"\r\n])*"/,greedy:!0},date:[{pattern:/\b\d{4}-\d{2}-\d{2}(?:[T\s]\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})?)?\b/i,alias:"number"},{pattern:/\b\d{2}:\d{2}:\d{2}(?:\.\d+)?\b/,alias:"number"}],number:/(?:\b0(?:x[\da-zA-Z]+(?:_[\da-zA-Z]+)*|o[0-7]+(?:_[0-7]+)*|b[10]+(?:_[10]+)*))\b|[-+]?\b\d+(?:_\d+)*(?:\.\d+(?:_\d+)*)?(?:[eE][+-]?\d+(?:_\d+)*)?\b|[-+]?\b(?:inf|nan)\b/,boolean:/\b(?:false|true)\b/,punctuation:/[.,=[\]{}]/}}(Prism)},6045:(e,t,n)=>{var a={"./prism-rust":767,"./prism-toml":9930};function r(e){var t=o(e);return n(t)}function o(e){if(!n.o(a,e)){var t=new Error("Cannot find module '"+e+"'");throw t.code="MODULE_NOT_FOUND",t}return a[e]}r.keys=function(){return Object.keys(a)},r.resolve=o,e.exports=r,r.id=6045},2703:(e,t,n)=>{"use strict";var a=n(414);function r(){}function o(){}o.resetWarningCache=r,e.exports=function(){function e(e,t,n,r,o,s){if(s!==a){var i=new Error("Calling PropTypes validators directly is not supported by the `prop-types` package. Use PropTypes.checkPropTypes() to call them. Read more at http://fb.me/use-check-prop-types");throw i.name="Invariant Violation",i}}function t(){return e}e.isRequired=e;var n={array:e,bigint:e,bool:e,func:e,number:e,object:e,string:e,symbol:e,any:e,arrayOf:t,element:e,elementType:e,instanceOf:t,node:e,objectOf:t,oneOf:t,oneOfType:t,shape:t,exact:t,checkPropTypes:o,resetWarningCache:r};return n.PropTypes=n,n}},5697:(e,t,n)=>{e.exports=n(2703)()},414:e=>{"use strict";e.exports="SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED"},4448:(e,t,n)=>{"use strict";var a=n(7294),r=n(7418),o=n(3840);function s(e){for(var t="https://reactjs.org/docs/error-decoder.html?invariant="+e,n=1;n<arguments.length;n++)t+="&args[]="+encodeURIComponent(arguments[n]);return"Minified React error #"+e+"; visit "+t+" for the full message or use the non-minified dev environment for full errors and additional helpful warnings."}if(!a)throw Error(s(227));var i=new Set,l={};function c(e,t){u(e,t),u(e+"Capture",t)}function u(e,t){for(l[e]=t,e=0;e<t.length;e++)i.add(t[e])}var d=!("undefined"==typeof window||void 0===window.document||void 0===window.document.createElement),f=/^[:A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD][:A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD\-.0-9\u00B7\u0300-\u036F\u203F-\u2040]*$/,p=Object.prototype.hasOwnProperty,m={},g={};function h(e,t,n,a,r,o,s){this.acceptsBooleans=2===t||3===t||4===t,this.attributeName=a,this.attributeNamespace=r,this.mustUseProperty=n,this.propertyName=e,this.type=t,this.sanitizeURL=o,this.removeEmptyString=s}var b={};"children dangerouslySetInnerHTML defaultValue defaultChecked innerHTML suppressContentEditableWarning suppressHydrationWarning style".split(" ").forEach((function(e){b[e]=new h(e,0,!1,e,null,!1,!1)})),[["acceptCharset","accept-charset"],["className","class"],["htmlFor","for"],["httpEquiv","http-equiv"]].forEach((function(e){var t=e[0];b[t]=new h(t,1,!1,e[1],null,!1,!1)})),["contentEditable","draggable","spellCheck","value"].forEach((function(e){b[e]=new h(e,2,!1,e.toLowerCase(),null,!1,!1)})),["autoReverse","externalResourcesRequired","focusable","preserveAlpha"].forEach((function(e){b[e]=new h(e,2,!1,e,null,!1,!1)})),"allowFullScreen async autoFocus autoPlay controls default defer disabled disablePictureInPicture disableRemotePlayback formNoValidate hidden loop noModule noValidate open playsInline readOnly required reversed scoped seamless itemScope".split(" ").forEach((function(e){b[e]=new h(e,3,!1,e.toLowerCase(),null,!1,!1)})),["checked","multiple","muted","selected"].forEach((function(e){b[e]=new h(e,3,!0,e,null,!1,!1)})),["capture","download"].forEach((function(e){b[e]=new h(e,4,!1,e,null,!1,!1)})),["cols","rows","size","span"].forEach((function(e){b[e]=new h(e,6,!1,e,null,!1,!1)})),["rowSpan","start"].forEach((function(e){b[e]=new h(e,5,!1,e.toLowerCase(),null,!1,!1)}));var v=/[\-:]([a-z])/g;function y(e){return e[1].toUpperCase()}function x(e,t,n,a){var r=b.hasOwnProperty(t)?b[t]:null;(null!==r?0===r.type:!a&&(2<t.length&&("o"===t[0]||"O"===t[0])&&("n"===t[1]||"N"===t[1])))||(function(e,t,n,a){if(null==t||function(e,t,n,a){if(null!==n&&0===n.type)return!1;switch(typeof t){case"function":case"symbol":return!0;case"boolean":return!a&&(null!==n?!n.acceptsBooleans:"data-"!==(e=e.toLowerCase().slice(0,5))&&"aria-"!==e);default:return!1}}(e,t,n,a))return!0;if(a)return!1;if(null!==n)switch(n.type){case 3:return!t;case 4:return!1===t;case 5:return isNaN(t);case 6:return isNaN(t)||1>t}return!1}(t,n,r,a)&&(n=null),a||null===r?function(e){return!!p.call(g,e)||!p.call(m,e)&&(f.test(e)?g[e]=!0:(m[e]=!0,!1))}(t)&&(null===n?e.removeAttribute(t):e.setAttribute(t,""+n)):r.mustUseProperty?e[r.propertyName]=null===n?3!==r.type&&"":n:(t=r.attributeName,a=r.attributeNamespace,null===n?e.removeAttribute(t):(n=3===(r=r.type)||4===r&&!0===n?"":""+n,a?e.setAttributeNS(a,t,n):e.setAttribute(t,n))))}"accent-height alignment-baseline arabic-form baseline-shift cap-height clip-path clip-rule color-interpolation color-interpolation-filters color-profile color-rendering dominant-baseline enable-background fill-opacity fill-rule flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-name glyph-orientation-horizontal glyph-orientation-vertical horiz-adv-x horiz-origin-x image-rendering letter-spacing lighting-color marker-end marker-mid marker-start overline-position overline-thickness paint-order panose-1 pointer-events rendering-intent shape-rendering stop-color stop-opacity strikethrough-position strikethrough-thickness stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width text-anchor text-decoration text-rendering underline-position underline-thickness unicode-bidi unicode-range units-per-em v-alphabetic v-hanging v-ideographic v-mathematical vector-effect vert-adv-y vert-origin-x vert-origin-y word-spacing writing-mode xmlns:xlink x-height".split(" ").forEach((function(e){var t=e.replace(v,y);b[t]=new h(t,1,!1,e,null,!1,!1)})),"xlink:actuate xlink:arcrole xlink:role xlink:show xlink:title xlink:type".split(" ").forEach((function(e){var t=e.replace(v,y);b[t]=new h(t,1,!1,e,"http://www.w3.org/1999/xlink",!1,!1)})),["xml:base","xml:lang","xml:space"].forEach((function(e){var t=e.replace(v,y);b[t]=new h(t,1,!1,e,"http://www.w3.org/XML/1998/namespace",!1,!1)})),["tabIndex","crossOrigin"].forEach((function(e){b[e]=new h(e,1,!1,e.toLowerCase(),null,!1,!1)})),b.xlinkHref=new h("xlinkHref",1,!1,"xlink:href","http://www.w3.org/1999/xlink",!0,!1),["src","href","action","formAction"].forEach((function(e){b[e]=new h(e,1,!1,e.toLowerCase(),null,!0,!0)}));var w=a.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED,S=60103,E=60106,k=60107,_=60108,C=60114,q=60109,T=60110,A=60112,L=60113,N=60120,O=60115,P=60116,I=60121,R=60128,M=60129,D=60130,F=60131;if("function"==typeof Symbol&&Symbol.for){var B=Symbol.for;S=B("react.element"),E=B("react.portal"),k=B("react.fragment"),_=B("react.strict_mode"),C=B("react.profiler"),q=B("react.provider"),T=B("react.context"),A=B("react.forward_ref"),L=B("react.suspense"),N=B("react.suspense_list"),O=B("react.memo"),P=B("react.lazy"),I=B("react.block"),B("react.scope"),R=B("react.opaque.id"),M=B("react.debug_trace_mode"),D=B("react.offscreen"),F=B("react.legacy_hidden")}var j,z="function"==typeof Symbol&&Symbol.iterator;function $(e){return null===e||"object"!=typeof e?null:"function"==typeof(e=z&&e[z]||e["@@iterator"])?e:null}function U(e){if(void 0===j)try{throw Error()}catch(n){var t=n.stack.trim().match(/\n( *(at )?)/);j=t&&t[1]||""}return"\n"+j+e}var Z=!1;function H(e,t){if(!e||Z)return"";Z=!0;var n=Error.prepareStackTrace;Error.prepareStackTrace=void 0;try{if(t)if(t=function(){throw Error()},Object.defineProperty(t.prototype,"props",{set:function(){throw Error()}}),"object"==typeof Reflect&&Reflect.construct){try{Reflect.construct(t,[])}catch(l){var a=l}Reflect.construct(e,[],t)}else{try{t.call()}catch(l){a=l}e.call(t.prototype)}else{try{throw Error()}catch(l){a=l}e()}}catch(l){if(l&&a&&"string"==typeof l.stack){for(var r=l.stack.split("\n"),o=a.stack.split("\n"),s=r.length-1,i=o.length-1;1<=s&&0<=i&&r[s]!==o[i];)i--;for(;1<=s&&0<=i;s--,i--)if(r[s]!==o[i]){if(1!==s||1!==i)do{if(s--,0>--i||r[s]!==o[i])return"\n"+r[s].replace(" at new "," at ")}while(1<=s&&0<=i);break}}}finally{Z=!1,Error.prepareStackTrace=n}return(e=e?e.displayName||e.name:"")?U(e):""}function V(e){switch(e.tag){case 5:return U(e.type);case 16:return U("Lazy");case 13:return U("Suspense");case 19:return U("SuspenseList");case 0:case 2:case 15:return e=H(e.type,!1);case 11:return e=H(e.type.render,!1);case 22:return e=H(e.type._render,!1);case 1:return e=H(e.type,!0);default:return""}}function W(e){if(null==e)return null;if("function"==typeof e)return e.displayName||e.name||null;if("string"==typeof e)return e;switch(e){case k:return"Fragment";case E:return"Portal";case C:return"Profiler";case _:return"StrictMode";case L:return"Suspense";case N:return"SuspenseList"}if("object"==typeof e)switch(e.$$typeof){case T:return(e.displayName||"Context")+".Consumer";case q:return(e._context.displayName||"Context")+".Provider";case A:var t=e.render;return t=t.displayName||t.name||"",e.displayName||(""!==t?"ForwardRef("+t+")":"ForwardRef");case O:return W(e.type);case I:return W(e._render);case P:t=e._payload,e=e._init;try{return W(e(t))}catch(n){}}return null}function G(e){switch(typeof e){case"boolean":case"number":case"object":case"string":case"undefined":return e;default:return""}}function Y(e){var t=e.type;return(e=e.nodeName)&&"input"===e.toLowerCase()&&("checkbox"===t||"radio"===t)}function K(e){e._valueTracker||(e._valueTracker=function(e){var t=Y(e)?"checked":"value",n=Object.getOwnPropertyDescriptor(e.constructor.prototype,t),a=""+e[t];if(!e.hasOwnProperty(t)&&void 0!==n&&"function"==typeof n.get&&"function"==typeof n.set){var r=n.get,o=n.set;return Object.defineProperty(e,t,{configurable:!0,get:function(){return r.call(this)},set:function(e){a=""+e,o.call(this,e)}}),Object.defineProperty(e,t,{enumerable:n.enumerable}),{getValue:function(){return a},setValue:function(e){a=""+e},stopTracking:function(){e._valueTracker=null,delete e[t]}}}}(e))}function Q(e){if(!e)return!1;var t=e._valueTracker;if(!t)return!0;var n=t.getValue(),a="";return e&&(a=Y(e)?e.checked?"true":"false":e.value),(e=a)!==n&&(t.setValue(e),!0)}function X(e){if(void 0===(e=e||("undefined"!=typeof document?document:void 0)))return null;try{return e.activeElement||e.body}catch(t){return e.body}}function J(e,t){var n=t.checked;return r({},t,{defaultChecked:void 0,defaultValue:void 0,value:void 0,checked:null!=n?n:e._wrapperState.initialChecked})}function ee(e,t){var n=null==t.defaultValue?"":t.defaultValue,a=null!=t.checked?t.checked:t.defaultChecked;n=G(null!=t.value?t.value:n),e._wrapperState={initialChecked:a,initialValue:n,controlled:"checkbox"===t.type||"radio"===t.type?null!=t.checked:null!=t.value}}function te(e,t){null!=(t=t.checked)&&x(e,"checked",t,!1)}function ne(e,t){te(e,t);var n=G(t.value),a=t.type;if(null!=n)"number"===a?(0===n&&""===e.value||e.value!=n)&&(e.value=""+n):e.value!==""+n&&(e.value=""+n);else if("submit"===a||"reset"===a)return void e.removeAttribute("value");t.hasOwnProperty("value")?re(e,t.type,n):t.hasOwnProperty("defaultValue")&&re(e,t.type,G(t.defaultValue)),null==t.checked&&null!=t.defaultChecked&&(e.defaultChecked=!!t.defaultChecked)}function ae(e,t,n){if(t.hasOwnProperty("value")||t.hasOwnProperty("defaultValue")){var a=t.type;if(!("submit"!==a&&"reset"!==a||void 0!==t.value&&null!==t.value))return;t=""+e._wrapperState.initialValue,n||t===e.value||(e.value=t),e.defaultValue=t}""!==(n=e.name)&&(e.name=""),e.defaultChecked=!!e._wrapperState.initialChecked,""!==n&&(e.name=n)}function re(e,t,n){"number"===t&&X(e.ownerDocument)===e||(null==n?e.defaultValue=""+e._wrapperState.initialValue:e.defaultValue!==""+n&&(e.defaultValue=""+n))}function oe(e,t){return e=r({children:void 0},t),(t=function(e){var t="";return a.Children.forEach(e,(function(e){null!=e&&(t+=e)})),t}(t.children))&&(e.children=t),e}function se(e,t,n,a){if(e=e.options,t){t={};for(var r=0;r<n.length;r++)t["$"+n[r]]=!0;for(n=0;n<e.length;n++)r=t.hasOwnProperty("$"+e[n].value),e[n].selected!==r&&(e[n].selected=r),r&&a&&(e[n].defaultSelected=!0)}else{for(n=""+G(n),t=null,r=0;r<e.length;r++){if(e[r].value===n)return e[r].selected=!0,void(a&&(e[r].defaultSelected=!0));null!==t||e[r].disabled||(t=e[r])}null!==t&&(t.selected=!0)}}function ie(e,t){if(null!=t.dangerouslySetInnerHTML)throw Error(s(91));return r({},t,{value:void 0,defaultValue:void 0,children:""+e._wrapperState.initialValue})}function le(e,t){var n=t.value;if(null==n){if(n=t.children,t=t.defaultValue,null!=n){if(null!=t)throw Error(s(92));if(Array.isArray(n)){if(!(1>=n.length))throw Error(s(93));n=n[0]}t=n}null==t&&(t=""),n=t}e._wrapperState={initialValue:G(n)}}function ce(e,t){var n=G(t.value),a=G(t.defaultValue);null!=n&&((n=""+n)!==e.value&&(e.value=n),null==t.defaultValue&&e.defaultValue!==n&&(e.defaultValue=n)),null!=a&&(e.defaultValue=""+a)}function ue(e){var t=e.textContent;t===e._wrapperState.initialValue&&""!==t&&null!==t&&(e.value=t)}var de={html:"http://www.w3.org/1999/xhtml",mathml:"http://www.w3.org/1998/Math/MathML",svg:"http://www.w3.org/2000/svg"};function fe(e){switch(e){case"svg":return"http://www.w3.org/2000/svg";case"math":return"http://www.w3.org/1998/Math/MathML";default:return"http://www.w3.org/1999/xhtml"}}function pe(e,t){return null==e||"http://www.w3.org/1999/xhtml"===e?fe(t):"http://www.w3.org/2000/svg"===e&&"foreignObject"===t?"http://www.w3.org/1999/xhtml":e}var me,ge,he=(ge=function(e,t){if(e.namespaceURI!==de.svg||"innerHTML"in e)e.innerHTML=t;else{for((me=me||document.createElement("div")).innerHTML="<svg>"+t.valueOf().toString()+"</svg>",t=me.firstChild;e.firstChild;)e.removeChild(e.firstChild);for(;t.firstChild;)e.appendChild(t.firstChild)}},"undefined"!=typeof MSApp&&MSApp.execUnsafeLocalFunction?function(e,t,n,a){MSApp.execUnsafeLocalFunction((function(){return ge(e,t)}))}:ge);function be(e,t){if(t){var n=e.firstChild;if(n&&n===e.lastChild&&3===n.nodeType)return void(n.nodeValue=t)}e.textContent=t}var ve={animationIterationCount:!0,borderImageOutset:!0,borderImageSlice:!0,borderImageWidth:!0,boxFlex:!0,boxFlexGroup:!0,boxOrdinalGroup:!0,columnCount:!0,columns:!0,flex:!0,flexGrow:!0,flexPositive:!0,flexShrink:!0,flexNegative:!0,flexOrder:!0,gridArea:!0,gridRow:!0,gridRowEnd:!0,gridRowSpan:!0,gridRowStart:!0,gridColumn:!0,gridColumnEnd:!0,gridColumnSpan:!0,gridColumnStart:!0,fontWeight:!0,lineClamp:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,tabSize:!0,widows:!0,zIndex:!0,zoom:!0,fillOpacity:!0,floodOpacity:!0,stopOpacity:!0,strokeDasharray:!0,strokeDashoffset:!0,strokeMiterlimit:!0,strokeOpacity:!0,strokeWidth:!0},ye=["Webkit","ms","Moz","O"];function xe(e,t,n){return null==t||"boolean"==typeof t||""===t?"":n||"number"!=typeof t||0===t||ve.hasOwnProperty(e)&&ve[e]?(""+t).trim():t+"px"}function we(e,t){for(var n in e=e.style,t)if(t.hasOwnProperty(n)){var a=0===n.indexOf("--"),r=xe(n,t[n],a);"float"===n&&(n="cssFloat"),a?e.setProperty(n,r):e[n]=r}}Object.keys(ve).forEach((function(e){ye.forEach((function(t){t=t+e.charAt(0).toUpperCase()+e.substring(1),ve[t]=ve[e]}))}));var Se=r({menuitem:!0},{area:!0,base:!0,br:!0,col:!0,embed:!0,hr:!0,img:!0,input:!0,keygen:!0,link:!0,meta:!0,param:!0,source:!0,track:!0,wbr:!0});function Ee(e,t){if(t){if(Se[e]&&(null!=t.children||null!=t.dangerouslySetInnerHTML))throw Error(s(137,e));if(null!=t.dangerouslySetInnerHTML){if(null!=t.children)throw Error(s(60));if("object"!=typeof t.dangerouslySetInnerHTML||!("__html"in t.dangerouslySetInnerHTML))throw Error(s(61))}if(null!=t.style&&"object"!=typeof t.style)throw Error(s(62))}}function ke(e,t){if(-1===e.indexOf("-"))return"string"==typeof t.is;switch(e){case"annotation-xml":case"color-profile":case"font-face":case"font-face-src":case"font-face-uri":case"font-face-format":case"font-face-name":case"missing-glyph":return!1;default:return!0}}function _e(e){return(e=e.target||e.srcElement||window).correspondingUseElement&&(e=e.correspondingUseElement),3===e.nodeType?e.parentNode:e}var Ce=null,qe=null,Te=null;function Ae(e){if(e=nr(e)){if("function"!=typeof Ce)throw Error(s(280));var t=e.stateNode;t&&(t=rr(t),Ce(e.stateNode,e.type,t))}}function Le(e){qe?Te?Te.push(e):Te=[e]:qe=e}function Ne(){if(qe){var e=qe,t=Te;if(Te=qe=null,Ae(e),t)for(e=0;e<t.length;e++)Ae(t[e])}}function Oe(e,t){return e(t)}function Pe(e,t,n,a,r){return e(t,n,a,r)}function Ie(){}var Re=Oe,Me=!1,De=!1;function Fe(){null===qe&&null===Te||(Ie(),Ne())}function Be(e,t){var n=e.stateNode;if(null===n)return null;var a=rr(n);if(null===a)return null;n=a[t];e:switch(t){case"onClick":case"onClickCapture":case"onDoubleClick":case"onDoubleClickCapture":case"onMouseDown":case"onMouseDownCapture":case"onMouseMove":case"onMouseMoveCapture":case"onMouseUp":case"onMouseUpCapture":case"onMouseEnter":(a=!a.disabled)||(a=!("button"===(e=e.type)||"input"===e||"select"===e||"textarea"===e)),e=!a;break e;default:e=!1}if(e)return null;if(n&&"function"!=typeof n)throw Error(s(231,t,typeof n));return n}var je=!1;if(d)try{var ze={};Object.defineProperty(ze,"passive",{get:function(){je=!0}}),window.addEventListener("test",ze,ze),window.removeEventListener("test",ze,ze)}catch(ge){je=!1}function $e(e,t,n,a,r,o,s,i,l){var c=Array.prototype.slice.call(arguments,3);try{t.apply(n,c)}catch(u){this.onError(u)}}var Ue=!1,Ze=null,He=!1,Ve=null,We={onError:function(e){Ue=!0,Ze=e}};function Ge(e,t,n,a,r,o,s,i,l){Ue=!1,Ze=null,$e.apply(We,arguments)}function Ye(e){var t=e,n=e;if(e.alternate)for(;t.return;)t=t.return;else{e=t;do{0!=(1026&(t=e).flags)&&(n=t.return),e=t.return}while(e)}return 3===t.tag?n:null}function Ke(e){if(13===e.tag){var t=e.memoizedState;if(null===t&&(null!==(e=e.alternate)&&(t=e.memoizedState)),null!==t)return t.dehydrated}return null}function Qe(e){if(Ye(e)!==e)throw Error(s(188))}function Xe(e){if(e=function(e){var t=e.alternate;if(!t){if(null===(t=Ye(e)))throw Error(s(188));return t!==e?null:e}for(var n=e,a=t;;){var r=n.return;if(null===r)break;var o=r.alternate;if(null===o){if(null!==(a=r.return)){n=a;continue}break}if(r.child===o.child){for(o=r.child;o;){if(o===n)return Qe(r),e;if(o===a)return Qe(r),t;o=o.sibling}throw Error(s(188))}if(n.return!==a.return)n=r,a=o;else{for(var i=!1,l=r.child;l;){if(l===n){i=!0,n=r,a=o;break}if(l===a){i=!0,a=r,n=o;break}l=l.sibling}if(!i){for(l=o.child;l;){if(l===n){i=!0,n=o,a=r;break}if(l===a){i=!0,a=o,n=r;break}l=l.sibling}if(!i)throw Error(s(189))}}if(n.alternate!==a)throw Error(s(190))}if(3!==n.tag)throw Error(s(188));return n.stateNode.current===n?e:t}(e),!e)return null;for(var t=e;;){if(5===t.tag||6===t.tag)return t;if(t.child)t.child.return=t,t=t.child;else{if(t===e)break;for(;!t.sibling;){if(!t.return||t.return===e)return null;t=t.return}t.sibling.return=t.return,t=t.sibling}}return null}function Je(e,t){for(var n=e.alternate;null!==t;){if(t===e||t===n)return!0;t=t.return}return!1}var et,tt,nt,at,rt=!1,ot=[],st=null,it=null,lt=null,ct=new Map,ut=new Map,dt=[],ft="mousedown mouseup touchcancel touchend touchstart auxclick dblclick pointercancel pointerdown pointerup dragend dragstart drop compositionend compositionstart keydown keypress keyup input textInput copy cut paste click change contextmenu reset submit".split(" ");function pt(e,t,n,a,r){return{blockedOn:e,domEventName:t,eventSystemFlags:16|n,nativeEvent:r,targetContainers:[a]}}function mt(e,t){switch(e){case"focusin":case"focusout":st=null;break;case"dragenter":case"dragleave":it=null;break;case"mouseover":case"mouseout":lt=null;break;case"pointerover":case"pointerout":ct.delete(t.pointerId);break;case"gotpointercapture":case"lostpointercapture":ut.delete(t.pointerId)}}function gt(e,t,n,a,r,o){return null===e||e.nativeEvent!==o?(e=pt(t,n,a,r,o),null!==t&&(null!==(t=nr(t))&&tt(t)),e):(e.eventSystemFlags|=a,t=e.targetContainers,null!==r&&-1===t.indexOf(r)&&t.push(r),e)}function ht(e){var t=tr(e.target);if(null!==t){var n=Ye(t);if(null!==n)if(13===(t=n.tag)){if(null!==(t=Ke(n)))return e.blockedOn=t,void at(e.lanePriority,(function(){o.unstable_runWithPriority(e.priority,(function(){nt(n)}))}))}else if(3===t&&n.stateNode.hydrate)return void(e.blockedOn=3===n.tag?n.stateNode.containerInfo:null)}e.blockedOn=null}function bt(e){if(null!==e.blockedOn)return!1;for(var t=e.targetContainers;0<t.length;){var n=Xt(e.domEventName,e.eventSystemFlags,t[0],e.nativeEvent);if(null!==n)return null!==(t=nr(n))&&tt(t),e.blockedOn=n,!1;t.shift()}return!0}function vt(e,t,n){bt(e)&&n.delete(t)}function yt(){for(rt=!1;0<ot.length;){var e=ot[0];if(null!==e.blockedOn){null!==(e=nr(e.blockedOn))&&et(e);break}for(var t=e.targetContainers;0<t.length;){var n=Xt(e.domEventName,e.eventSystemFlags,t[0],e.nativeEvent);if(null!==n){e.blockedOn=n;break}t.shift()}null===e.blockedOn&&ot.shift()}null!==st&&bt(st)&&(st=null),null!==it&&bt(it)&&(it=null),null!==lt&&bt(lt)&&(lt=null),ct.forEach(vt),ut.forEach(vt)}function xt(e,t){e.blockedOn===t&&(e.blockedOn=null,rt||(rt=!0,o.unstable_scheduleCallback(o.unstable_NormalPriority,yt)))}function wt(e){function t(t){return xt(t,e)}if(0<ot.length){xt(ot[0],e);for(var n=1;n<ot.length;n++){var a=ot[n];a.blockedOn===e&&(a.blockedOn=null)}}for(null!==st&&xt(st,e),null!==it&&xt(it,e),null!==lt&&xt(lt,e),ct.forEach(t),ut.forEach(t),n=0;n<dt.length;n++)(a=dt[n]).blockedOn===e&&(a.blockedOn=null);for(;0<dt.length&&null===(n=dt[0]).blockedOn;)ht(n),null===n.blockedOn&&dt.shift()}function St(e,t){var n={};return n[e.toLowerCase()]=t.toLowerCase(),n["Webkit"+e]="webkit"+t,n["Moz"+e]="moz"+t,n}var Et={animationend:St("Animation","AnimationEnd"),animationiteration:St("Animation","AnimationIteration"),animationstart:St("Animation","AnimationStart"),transitionend:St("Transition","TransitionEnd")},kt={},_t={};function Ct(e){if(kt[e])return kt[e];if(!Et[e])return e;var t,n=Et[e];for(t in n)if(n.hasOwnProperty(t)&&t in _t)return kt[e]=n[t];return e}d&&(_t=document.createElement("div").style,"AnimationEvent"in window||(delete Et.animationend.animation,delete Et.animationiteration.animation,delete Et.animationstart.animation),"TransitionEvent"in window||delete Et.transitionend.transition);var qt=Ct("animationend"),Tt=Ct("animationiteration"),At=Ct("animationstart"),Lt=Ct("transitionend"),Nt=new Map,Ot=new Map,Pt=["abort","abort",qt,"animationEnd",Tt,"animationIteration",At,"animationStart","canplay","canPlay","canplaythrough","canPlayThrough","durationchange","durationChange","emptied","emptied","encrypted","encrypted","ended","ended","error","error","gotpointercapture","gotPointerCapture","load","load","loadeddata","loadedData","loadedmetadata","loadedMetadata","loadstart","loadStart","lostpointercapture","lostPointerCapture","playing","playing","progress","progress","seeking","seeking","stalled","stalled","suspend","suspend","timeupdate","timeUpdate",Lt,"transitionEnd","waiting","waiting"];function It(e,t){for(var n=0;n<e.length;n+=2){var a=e[n],r=e[n+1];r="on"+(r[0].toUpperCase()+r.slice(1)),Ot.set(a,t),Nt.set(a,r),c(r,[a])}}(0,o.unstable_now)();var Rt=8;function Mt(e){if(0!=(1&e))return Rt=15,1;if(0!=(2&e))return Rt=14,2;if(0!=(4&e))return Rt=13,4;var t=24&e;return 0!==t?(Rt=12,t):0!=(32&e)?(Rt=11,32):0!==(t=192&e)?(Rt=10,t):0!=(256&e)?(Rt=9,256):0!==(t=3584&e)?(Rt=8,t):0!=(4096&e)?(Rt=7,4096):0!==(t=4186112&e)?(Rt=6,t):0!==(t=62914560&e)?(Rt=5,t):67108864&e?(Rt=4,67108864):0!=(134217728&e)?(Rt=3,134217728):0!==(t=805306368&e)?(Rt=2,t):0!=(1073741824&e)?(Rt=1,1073741824):(Rt=8,e)}function Dt(e,t){var n=e.pendingLanes;if(0===n)return Rt=0;var a=0,r=0,o=e.expiredLanes,s=e.suspendedLanes,i=e.pingedLanes;if(0!==o)a=o,r=Rt=15;else if(0!==(o=134217727&n)){var l=o&~s;0!==l?(a=Mt(l),r=Rt):0!==(i&=o)&&(a=Mt(i),r=Rt)}else 0!==(o=n&~s)?(a=Mt(o),r=Rt):0!==i&&(a=Mt(i),r=Rt);if(0===a)return 0;if(a=n&((0>(a=31-Ut(a))?0:1<<a)<<1)-1,0!==t&&t!==a&&0==(t&s)){if(Mt(t),r<=Rt)return t;Rt=r}if(0!==(t=e.entangledLanes))for(e=e.entanglements,t&=a;0<t;)r=1<<(n=31-Ut(t)),a|=e[n],t&=~r;return a}function Ft(e){return 0!==(e=-1073741825&e.pendingLanes)?e:1073741824&e?1073741824:0}function Bt(e,t){switch(e){case 15:return 1;case 14:return 2;case 12:return 0===(e=jt(24&~t))?Bt(10,t):e;case 10:return 0===(e=jt(192&~t))?Bt(8,t):e;case 8:return 0===(e=jt(3584&~t))&&(0===(e=jt(4186112&~t))&&(e=512)),e;case 2:return 0===(t=jt(805306368&~t))&&(t=268435456),t}throw Error(s(358,e))}function jt(e){return e&-e}function zt(e){for(var t=[],n=0;31>n;n++)t.push(e);return t}function $t(e,t,n){e.pendingLanes|=t;var a=t-1;e.suspendedLanes&=a,e.pingedLanes&=a,(e=e.eventTimes)[t=31-Ut(t)]=n}var Ut=Math.clz32?Math.clz32:function(e){return 0===e?32:31-(Zt(e)/Ht|0)|0},Zt=Math.log,Ht=Math.LN2;var Vt=o.unstable_UserBlockingPriority,Wt=o.unstable_runWithPriority,Gt=!0;function Yt(e,t,n,a){Me||Ie();var r=Qt,o=Me;Me=!0;try{Pe(r,e,t,n,a)}finally{(Me=o)||Fe()}}function Kt(e,t,n,a){Wt(Vt,Qt.bind(null,e,t,n,a))}function Qt(e,t,n,a){var r;if(Gt)if((r=0==(4&t))&&0<ot.length&&-1<ft.indexOf(e))e=pt(null,e,t,n,a),ot.push(e);else{var o=Xt(e,t,n,a);if(null===o)r&&mt(e,a);else{if(r){if(-1<ft.indexOf(e))return e=pt(o,e,t,n,a),void ot.push(e);if(function(e,t,n,a,r){switch(t){case"focusin":return st=gt(st,e,t,n,a,r),!0;case"dragenter":return it=gt(it,e,t,n,a,r),!0;case"mouseover":return lt=gt(lt,e,t,n,a,r),!0;case"pointerover":var o=r.pointerId;return ct.set(o,gt(ct.get(o)||null,e,t,n,a,r)),!0;case"gotpointercapture":return o=r.pointerId,ut.set(o,gt(ut.get(o)||null,e,t,n,a,r)),!0}return!1}(o,e,t,n,a))return;mt(e,a)}Ia(e,t,a,null,n)}}}function Xt(e,t,n,a){var r=_e(a);if(null!==(r=tr(r))){var o=Ye(r);if(null===o)r=null;else{var s=o.tag;if(13===s){if(null!==(r=Ke(o)))return r;r=null}else if(3===s){if(o.stateNode.hydrate)return 3===o.tag?o.stateNode.containerInfo:null;r=null}else o!==r&&(r=null)}}return Ia(e,t,a,r,n),null}var Jt=null,en=null,tn=null;function nn(){if(tn)return tn;var e,t,n=en,a=n.length,r="value"in Jt?Jt.value:Jt.textContent,o=r.length;for(e=0;e<a&&n[e]===r[e];e++);var s=a-e;for(t=1;t<=s&&n[a-t]===r[o-t];t++);return tn=r.slice(e,1<t?1-t:void 0)}function an(e){var t=e.keyCode;return"charCode"in e?0===(e=e.charCode)&&13===t&&(e=13):e=t,10===e&&(e=13),32<=e||13===e?e:0}function rn(){return!0}function on(){return!1}function sn(e){function t(t,n,a,r,o){for(var s in this._reactName=t,this._targetInst=a,this.type=n,this.nativeEvent=r,this.target=o,this.currentTarget=null,e)e.hasOwnProperty(s)&&(t=e[s],this[s]=t?t(r):r[s]);return this.isDefaultPrevented=(null!=r.defaultPrevented?r.defaultPrevented:!1===r.returnValue)?rn:on,this.isPropagationStopped=on,this}return r(t.prototype,{preventDefault:function(){this.defaultPrevented=!0;var e=this.nativeEvent;e&&(e.preventDefault?e.preventDefault():"unknown"!=typeof e.returnValue&&(e.returnValue=!1),this.isDefaultPrevented=rn)},stopPropagation:function(){var e=this.nativeEvent;e&&(e.stopPropagation?e.stopPropagation():"unknown"!=typeof e.cancelBubble&&(e.cancelBubble=!0),this.isPropagationStopped=rn)},persist:function(){},isPersistent:rn}),t}var ln,cn,un,dn={eventPhase:0,bubbles:0,cancelable:0,timeStamp:function(e){return e.timeStamp||Date.now()},defaultPrevented:0,isTrusted:0},fn=sn(dn),pn=r({},dn,{view:0,detail:0}),mn=sn(pn),gn=r({},pn,{screenX:0,screenY:0,clientX:0,clientY:0,pageX:0,pageY:0,ctrlKey:0,shiftKey:0,altKey:0,metaKey:0,getModifierState:qn,button:0,buttons:0,relatedTarget:function(e){return void 0===e.relatedTarget?e.fromElement===e.srcElement?e.toElement:e.fromElement:e.relatedTarget},movementX:function(e){return"movementX"in e?e.movementX:(e!==un&&(un&&"mousemove"===e.type?(ln=e.screenX-un.screenX,cn=e.screenY-un.screenY):cn=ln=0,un=e),ln)},movementY:function(e){return"movementY"in e?e.movementY:cn}}),hn=sn(gn),bn=sn(r({},gn,{dataTransfer:0})),vn=sn(r({},pn,{relatedTarget:0})),yn=sn(r({},dn,{animationName:0,elapsedTime:0,pseudoElement:0})),xn=r({},dn,{clipboardData:function(e){return"clipboardData"in e?e.clipboardData:window.clipboardData}}),wn=sn(xn),Sn=sn(r({},dn,{data:0})),En={Esc:"Escape",Spacebar:" ",Left:"ArrowLeft",Up:"ArrowUp",Right:"ArrowRight",Down:"ArrowDown",Del:"Delete",Win:"OS",Menu:"ContextMenu",Apps:"ContextMenu",Scroll:"ScrollLock",MozPrintableKey:"Unidentified"},kn={8:"Backspace",9:"Tab",12:"Clear",13:"Enter",16:"Shift",17:"Control",18:"Alt",19:"Pause",20:"CapsLock",27:"Escape",32:" ",33:"PageUp",34:"PageDown",35:"End",36:"Home",37:"ArrowLeft",38:"ArrowUp",39:"ArrowRight",40:"ArrowDown",45:"Insert",46:"Delete",112:"F1",113:"F2",114:"F3",115:"F4",116:"F5",117:"F6",118:"F7",119:"F8",120:"F9",121:"F10",122:"F11",123:"F12",144:"NumLock",145:"ScrollLock",224:"Meta"},_n={Alt:"altKey",Control:"ctrlKey",Meta:"metaKey",Shift:"shiftKey"};function Cn(e){var t=this.nativeEvent;return t.getModifierState?t.getModifierState(e):!!(e=_n[e])&&!!t[e]}function qn(){return Cn}var Tn=r({},pn,{key:function(e){if(e.key){var t=En[e.key]||e.key;if("Unidentified"!==t)return t}return"keypress"===e.type?13===(e=an(e))?"Enter":String.fromCharCode(e):"keydown"===e.type||"keyup"===e.type?kn[e.keyCode]||"Unidentified":""},code:0,location:0,ctrlKey:0,shiftKey:0,altKey:0,metaKey:0,repeat:0,locale:0,getModifierState:qn,charCode:function(e){return"keypress"===e.type?an(e):0},keyCode:function(e){return"keydown"===e.type||"keyup"===e.type?e.keyCode:0},which:function(e){return"keypress"===e.type?an(e):"keydown"===e.type||"keyup"===e.type?e.keyCode:0}}),An=sn(Tn),Ln=sn(r({},gn,{pointerId:0,width:0,height:0,pressure:0,tangentialPressure:0,tiltX:0,tiltY:0,twist:0,pointerType:0,isPrimary:0})),Nn=sn(r({},pn,{touches:0,targetTouches:0,changedTouches:0,altKey:0,metaKey:0,ctrlKey:0,shiftKey:0,getModifierState:qn})),On=sn(r({},dn,{propertyName:0,elapsedTime:0,pseudoElement:0})),Pn=r({},gn,{deltaX:function(e){return"deltaX"in e?e.deltaX:"wheelDeltaX"in e?-e.wheelDeltaX:0},deltaY:function(e){return"deltaY"in e?e.deltaY:"wheelDeltaY"in e?-e.wheelDeltaY:"wheelDelta"in e?-e.wheelDelta:0},deltaZ:0,deltaMode:0}),In=sn(Pn),Rn=[9,13,27,32],Mn=d&&"CompositionEvent"in window,Dn=null;d&&"documentMode"in document&&(Dn=document.documentMode);var Fn=d&&"TextEvent"in window&&!Dn,Bn=d&&(!Mn||Dn&&8<Dn&&11>=Dn),jn=String.fromCharCode(32),zn=!1;function $n(e,t){switch(e){case"keyup":return-1!==Rn.indexOf(t.keyCode);case"keydown":return 229!==t.keyCode;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function Un(e){return"object"==typeof(e=e.detail)&&"data"in e?e.data:null}var Zn=!1;var Hn={color:!0,date:!0,datetime:!0,"datetime-local":!0,email:!0,month:!0,number:!0,password:!0,range:!0,search:!0,tel:!0,text:!0,time:!0,url:!0,week:!0};function Vn(e){var t=e&&e.nodeName&&e.nodeName.toLowerCase();return"input"===t?!!Hn[e.type]:"textarea"===t}function Wn(e,t,n,a){Le(a),0<(t=Ma(t,"onChange")).length&&(n=new fn("onChange","change",null,n,a),e.push({event:n,listeners:t}))}var Gn=null,Yn=null;function Kn(e){Ta(e,0)}function Qn(e){if(Q(ar(e)))return e}function Xn(e,t){if("change"===e)return t}var Jn=!1;if(d){var ea;if(d){var ta="oninput"in document;if(!ta){var na=document.createElement("div");na.setAttribute("oninput","return;"),ta="function"==typeof na.oninput}ea=ta}else ea=!1;Jn=ea&&(!document.documentMode||9<document.documentMode)}function aa(){Gn&&(Gn.detachEvent("onpropertychange",ra),Yn=Gn=null)}function ra(e){if("value"===e.propertyName&&Qn(Yn)){var t=[];if(Wn(t,Yn,e,_e(e)),e=Kn,Me)e(t);else{Me=!0;try{Oe(e,t)}finally{Me=!1,Fe()}}}}function oa(e,t,n){"focusin"===e?(aa(),Yn=n,(Gn=t).attachEvent("onpropertychange",ra)):"focusout"===e&&aa()}function sa(e){if("selectionchange"===e||"keyup"===e||"keydown"===e)return Qn(Yn)}function ia(e,t){if("click"===e)return Qn(t)}function la(e,t){if("input"===e||"change"===e)return Qn(t)}var ca="function"==typeof Object.is?Object.is:function(e,t){return e===t&&(0!==e||1/e==1/t)||e!=e&&t!=t},ua=Object.prototype.hasOwnProperty;function da(e,t){if(ca(e,t))return!0;if("object"!=typeof e||null===e||"object"!=typeof t||null===t)return!1;var n=Object.keys(e),a=Object.keys(t);if(n.length!==a.length)return!1;for(a=0;a<n.length;a++)if(!ua.call(t,n[a])||!ca(e[n[a]],t[n[a]]))return!1;return!0}function fa(e){for(;e&&e.firstChild;)e=e.firstChild;return e}function pa(e,t){var n,a=fa(e);for(e=0;a;){if(3===a.nodeType){if(n=e+a.textContent.length,e<=t&&n>=t)return{node:a,offset:t-e};e=n}e:{for(;a;){if(a.nextSibling){a=a.nextSibling;break e}a=a.parentNode}a=void 0}a=fa(a)}}function ma(e,t){return!(!e||!t)&&(e===t||(!e||3!==e.nodeType)&&(t&&3===t.nodeType?ma(e,t.parentNode):"contains"in e?e.contains(t):!!e.compareDocumentPosition&&!!(16&e.compareDocumentPosition(t))))}function ga(){for(var e=window,t=X();t instanceof e.HTMLIFrameElement;){try{var n="string"==typeof t.contentWindow.location.href}catch(a){n=!1}if(!n)break;t=X((e=t.contentWindow).document)}return t}function ha(e){var t=e&&e.nodeName&&e.nodeName.toLowerCase();return t&&("input"===t&&("text"===e.type||"search"===e.type||"tel"===e.type||"url"===e.type||"password"===e.type)||"textarea"===t||"true"===e.contentEditable)}var ba=d&&"documentMode"in document&&11>=document.documentMode,va=null,ya=null,xa=null,wa=!1;function Sa(e,t,n){var a=n.window===n?n.document:9===n.nodeType?n:n.ownerDocument;wa||null==va||va!==X(a)||("selectionStart"in(a=va)&&ha(a)?a={start:a.selectionStart,end:a.selectionEnd}:a={anchorNode:(a=(a.ownerDocument&&a.ownerDocument.defaultView||window).getSelection()).anchorNode,anchorOffset:a.anchorOffset,focusNode:a.focusNode,focusOffset:a.focusOffset},xa&&da(xa,a)||(xa=a,0<(a=Ma(ya,"onSelect")).length&&(t=new fn("onSelect","select",null,t,n),e.push({event:t,listeners:a}),t.target=va)))}It("cancel cancel click click close close contextmenu contextMenu copy copy cut cut auxclick auxClick dblclick doubleClick dragend dragEnd dragstart dragStart drop drop focusin focus focusout blur input input invalid invalid keydown keyDown keypress keyPress keyup keyUp mousedown mouseDown mouseup mouseUp paste paste pause pause play play pointercancel pointerCancel pointerdown pointerDown pointerup pointerUp ratechange rateChange reset reset seeked seeked submit submit touchcancel touchCancel touchend touchEnd touchstart touchStart volumechange volumeChange".split(" "),0),It("drag drag dragenter dragEnter dragexit dragExit dragleave dragLeave dragover dragOver mousemove mouseMove mouseout mouseOut mouseover mouseOver pointermove pointerMove pointerout pointerOut pointerover pointerOver scroll scroll toggle toggle touchmove touchMove wheel wheel".split(" "),1),It(Pt,2);for(var Ea="change selectionchange textInput compositionstart compositionend compositionupdate".split(" "),ka=0;ka<Ea.length;ka++)Ot.set(Ea[ka],0);u("onMouseEnter",["mouseout","mouseover"]),u("onMouseLeave",["mouseout","mouseover"]),u("onPointerEnter",["pointerout","pointerover"]),u("onPointerLeave",["pointerout","pointerover"]),c("onChange","change click focusin focusout input keydown keyup selectionchange".split(" ")),c("onSelect","focusout contextmenu dragend focusin keydown keyup mousedown mouseup selectionchange".split(" ")),c("onBeforeInput",["compositionend","keypress","textInput","paste"]),c("onCompositionEnd","compositionend focusout keydown keypress keyup mousedown".split(" ")),c("onCompositionStart","compositionstart focusout keydown keypress keyup mousedown".split(" ")),c("onCompositionUpdate","compositionupdate focusout keydown keypress keyup mousedown".split(" "));var _a="abort canplay canplaythrough durationchange emptied encrypted ended error loadeddata loadedmetadata loadstart pause play playing progress ratechange seeked seeking stalled suspend timeupdate volumechange waiting".split(" "),Ca=new Set("cancel close invalid load scroll toggle".split(" ").concat(_a));function qa(e,t,n){var a=e.type||"unknown-event";e.currentTarget=n,function(e,t,n,a,r,o,i,l,c){if(Ge.apply(this,arguments),Ue){if(!Ue)throw Error(s(198));var u=Ze;Ue=!1,Ze=null,He||(He=!0,Ve=u)}}(a,t,void 0,e),e.currentTarget=null}function Ta(e,t){t=0!=(4&t);for(var n=0;n<e.length;n++){var a=e[n],r=a.event;a=a.listeners;e:{var o=void 0;if(t)for(var s=a.length-1;0<=s;s--){var i=a[s],l=i.instance,c=i.currentTarget;if(i=i.listener,l!==o&&r.isPropagationStopped())break e;qa(r,i,c),o=l}else for(s=0;s<a.length;s++){if(l=(i=a[s]).instance,c=i.currentTarget,i=i.listener,l!==o&&r.isPropagationStopped())break e;qa(r,i,c),o=l}}}if(He)throw e=Ve,He=!1,Ve=null,e}function Aa(e,t){var n=or(t),a=e+"__bubble";n.has(a)||(Pa(t,e,2,!1),n.add(a))}var La="_reactListening"+Math.random().toString(36).slice(2);function Na(e){e[La]||(e[La]=!0,i.forEach((function(t){Ca.has(t)||Oa(t,!1,e,null),Oa(t,!0,e,null)})))}function Oa(e,t,n,a){var r=4<arguments.length&&void 0!==arguments[4]?arguments[4]:0,o=n;if("selectionchange"===e&&9!==n.nodeType&&(o=n.ownerDocument),null!==a&&!t&&Ca.has(e)){if("scroll"!==e)return;r|=2,o=a}var s=or(o),i=e+"__"+(t?"capture":"bubble");s.has(i)||(t&&(r|=4),Pa(o,e,r,t),s.add(i))}function Pa(e,t,n,a){var r=Ot.get(t);switch(void 0===r?2:r){case 0:r=Yt;break;case 1:r=Kt;break;default:r=Qt}n=r.bind(null,t,n,e),r=void 0,!je||"touchstart"!==t&&"touchmove"!==t&&"wheel"!==t||(r=!0),a?void 0!==r?e.addEventListener(t,n,{capture:!0,passive:r}):e.addEventListener(t,n,!0):void 0!==r?e.addEventListener(t,n,{passive:r}):e.addEventListener(t,n,!1)}function Ia(e,t,n,a,r){var o=a;if(0==(1&t)&&0==(2&t)&&null!==a)e:for(;;){if(null===a)return;var s=a.tag;if(3===s||4===s){var i=a.stateNode.containerInfo;if(i===r||8===i.nodeType&&i.parentNode===r)break;if(4===s)for(s=a.return;null!==s;){var l=s.tag;if((3===l||4===l)&&((l=s.stateNode.containerInfo)===r||8===l.nodeType&&l.parentNode===r))return;s=s.return}for(;null!==i;){if(null===(s=tr(i)))return;if(5===(l=s.tag)||6===l){a=o=s;continue e}i=i.parentNode}}a=a.return}!function(e,t,n){if(De)return e(t,n);De=!0;try{return Re(e,t,n)}finally{De=!1,Fe()}}((function(){var a=o,r=_e(n),s=[];e:{var i=Nt.get(e);if(void 0!==i){var l=fn,c=e;switch(e){case"keypress":if(0===an(n))break e;case"keydown":case"keyup":l=An;break;case"focusin":c="focus",l=vn;break;case"focusout":c="blur",l=vn;break;case"beforeblur":case"afterblur":l=vn;break;case"click":if(2===n.button)break e;case"auxclick":case"dblclick":case"mousedown":case"mousemove":case"mouseup":case"mouseout":case"mouseover":case"contextmenu":l=hn;break;case"drag":case"dragend":case"dragenter":case"dragexit":case"dragleave":case"dragover":case"dragstart":case"drop":l=bn;break;case"touchcancel":case"touchend":case"touchmove":case"touchstart":l=Nn;break;case qt:case Tt:case At:l=yn;break;case Lt:l=On;break;case"scroll":l=mn;break;case"wheel":l=In;break;case"copy":case"cut":case"paste":l=wn;break;case"gotpointercapture":case"lostpointercapture":case"pointercancel":case"pointerdown":case"pointermove":case"pointerout":case"pointerover":case"pointerup":l=Ln}var u=0!=(4&t),d=!u&&"scroll"===e,f=u?null!==i?i+"Capture":null:i;u=[];for(var p,m=a;null!==m;){var g=(p=m).stateNode;if(5===p.tag&&null!==g&&(p=g,null!==f&&(null!=(g=Be(m,f))&&u.push(Ra(m,g,p)))),d)break;m=m.return}0<u.length&&(i=new l(i,c,null,n,r),s.push({event:i,listeners:u}))}}if(0==(7&t)){if(l="mouseout"===e||"pointerout"===e,(!(i="mouseover"===e||"pointerover"===e)||0!=(16&t)||!(c=n.relatedTarget||n.fromElement)||!tr(c)&&!c[Ja])&&(l||i)&&(i=r.window===r?r:(i=r.ownerDocument)?i.defaultView||i.parentWindow:window,l?(l=a,null!==(c=(c=n.relatedTarget||n.toElement)?tr(c):null)&&(c!==(d=Ye(c))||5!==c.tag&&6!==c.tag)&&(c=null)):(l=null,c=a),l!==c)){if(u=hn,g="onMouseLeave",f="onMouseEnter",m="mouse","pointerout"!==e&&"pointerover"!==e||(u=Ln,g="onPointerLeave",f="onPointerEnter",m="pointer"),d=null==l?i:ar(l),p=null==c?i:ar(c),(i=new u(g,m+"leave",l,n,r)).target=d,i.relatedTarget=p,g=null,tr(r)===a&&((u=new u(f,m+"enter",c,n,r)).target=p,u.relatedTarget=d,g=u),d=g,l&&c)e:{for(f=c,m=0,p=u=l;p;p=Da(p))m++;for(p=0,g=f;g;g=Da(g))p++;for(;0<m-p;)u=Da(u),m--;for(;0<p-m;)f=Da(f),p--;for(;m--;){if(u===f||null!==f&&u===f.alternate)break e;u=Da(u),f=Da(f)}u=null}else u=null;null!==l&&Fa(s,i,l,u,!1),null!==c&&null!==d&&Fa(s,d,c,u,!0)}if("select"===(l=(i=a?ar(a):window).nodeName&&i.nodeName.toLowerCase())||"input"===l&&"file"===i.type)var h=Xn;else if(Vn(i))if(Jn)h=la;else{h=sa;var b=oa}else(l=i.nodeName)&&"input"===l.toLowerCase()&&("checkbox"===i.type||"radio"===i.type)&&(h=ia);switch(h&&(h=h(e,a))?Wn(s,h,n,r):(b&&b(e,i,a),"focusout"===e&&(b=i._wrapperState)&&b.controlled&&"number"===i.type&&re(i,"number",i.value)),b=a?ar(a):window,e){case"focusin":(Vn(b)||"true"===b.contentEditable)&&(va=b,ya=a,xa=null);break;case"focusout":xa=ya=va=null;break;case"mousedown":wa=!0;break;case"contextmenu":case"mouseup":case"dragend":wa=!1,Sa(s,n,r);break;case"selectionchange":if(ba)break;case"keydown":case"keyup":Sa(s,n,r)}var v;if(Mn)e:{switch(e){case"compositionstart":var y="onCompositionStart";break e;case"compositionend":y="onCompositionEnd";break e;case"compositionupdate":y="onCompositionUpdate";break e}y=void 0}else Zn?$n(e,n)&&(y="onCompositionEnd"):"keydown"===e&&229===n.keyCode&&(y="onCompositionStart");y&&(Bn&&"ko"!==n.locale&&(Zn||"onCompositionStart"!==y?"onCompositionEnd"===y&&Zn&&(v=nn()):(en="value"in(Jt=r)?Jt.value:Jt.textContent,Zn=!0)),0<(b=Ma(a,y)).length&&(y=new Sn(y,e,null,n,r),s.push({event:y,listeners:b}),v?y.data=v:null!==(v=Un(n))&&(y.data=v))),(v=Fn?function(e,t){switch(e){case"compositionend":return Un(t);case"keypress":return 32!==t.which?null:(zn=!0,jn);case"textInput":return(e=t.data)===jn&&zn?null:e;default:return null}}(e,n):function(e,t){if(Zn)return"compositionend"===e||!Mn&&$n(e,t)?(e=nn(),tn=en=Jt=null,Zn=!1,e):null;switch(e){case"paste":default:return null;case"keypress":if(!(t.ctrlKey||t.altKey||t.metaKey)||t.ctrlKey&&t.altKey){if(t.char&&1<t.char.length)return t.char;if(t.which)return String.fromCharCode(t.which)}return null;case"compositionend":return Bn&&"ko"!==t.locale?null:t.data}}(e,n))&&(0<(a=Ma(a,"onBeforeInput")).length&&(r=new Sn("onBeforeInput","beforeinput",null,n,r),s.push({event:r,listeners:a}),r.data=v))}Ta(s,t)}))}function Ra(e,t,n){return{instance:e,listener:t,currentTarget:n}}function Ma(e,t){for(var n=t+"Capture",a=[];null!==e;){var r=e,o=r.stateNode;5===r.tag&&null!==o&&(r=o,null!=(o=Be(e,n))&&a.unshift(Ra(e,o,r)),null!=(o=Be(e,t))&&a.push(Ra(e,o,r))),e=e.return}return a}function Da(e){if(null===e)return null;do{e=e.return}while(e&&5!==e.tag);return e||null}function Fa(e,t,n,a,r){for(var o=t._reactName,s=[];null!==n&&n!==a;){var i=n,l=i.alternate,c=i.stateNode;if(null!==l&&l===a)break;5===i.tag&&null!==c&&(i=c,r?null!=(l=Be(n,o))&&s.unshift(Ra(n,l,i)):r||null!=(l=Be(n,o))&&s.push(Ra(n,l,i))),n=n.return}0!==s.length&&e.push({event:t,listeners:s})}function Ba(){}var ja=null,za=null;function $a(e,t){switch(e){case"button":case"input":case"select":case"textarea":return!!t.autoFocus}return!1}function Ua(e,t){return"textarea"===e||"option"===e||"noscript"===e||"string"==typeof t.children||"number"==typeof t.children||"object"==typeof t.dangerouslySetInnerHTML&&null!==t.dangerouslySetInnerHTML&&null!=t.dangerouslySetInnerHTML.__html}var Za="function"==typeof setTimeout?setTimeout:void 0,Ha="function"==typeof clearTimeout?clearTimeout:void 0;function Va(e){1===e.nodeType?e.textContent="":9===e.nodeType&&(null!=(e=e.body)&&(e.textContent=""))}function Wa(e){for(;null!=e;e=e.nextSibling){var t=e.nodeType;if(1===t||3===t)break}return e}function Ga(e){e=e.previousSibling;for(var t=0;e;){if(8===e.nodeType){var n=e.data;if("$"===n||"$!"===n||"$?"===n){if(0===t)return e;t--}else"/$"===n&&t++}e=e.previousSibling}return null}var Ya=0;var Ka=Math.random().toString(36).slice(2),Qa="__reactFiber$"+Ka,Xa="__reactProps$"+Ka,Ja="__reactContainer$"+Ka,er="__reactEvents$"+Ka;function tr(e){var t=e[Qa];if(t)return t;for(var n=e.parentNode;n;){if(t=n[Ja]||n[Qa]){if(n=t.alternate,null!==t.child||null!==n&&null!==n.child)for(e=Ga(e);null!==e;){if(n=e[Qa])return n;e=Ga(e)}return t}n=(e=n).parentNode}return null}function nr(e){return!(e=e[Qa]||e[Ja])||5!==e.tag&&6!==e.tag&&13!==e.tag&&3!==e.tag?null:e}function ar(e){if(5===e.tag||6===e.tag)return e.stateNode;throw Error(s(33))}function rr(e){return e[Xa]||null}function or(e){var t=e[er];return void 0===t&&(t=e[er]=new Set),t}var sr=[],ir=-1;function lr(e){return{current:e}}function cr(e){0>ir||(e.current=sr[ir],sr[ir]=null,ir--)}function ur(e,t){ir++,sr[ir]=e.current,e.current=t}var dr={},fr=lr(dr),pr=lr(!1),mr=dr;function gr(e,t){var n=e.type.contextTypes;if(!n)return dr;var a=e.stateNode;if(a&&a.__reactInternalMemoizedUnmaskedChildContext===t)return a.__reactInternalMemoizedMaskedChildContext;var r,o={};for(r in n)o[r]=t[r];return a&&((e=e.stateNode).__reactInternalMemoizedUnmaskedChildContext=t,e.__reactInternalMemoizedMaskedChildContext=o),o}function hr(e){return null!=(e=e.childContextTypes)}function br(){cr(pr),cr(fr)}function vr(e,t,n){if(fr.current!==dr)throw Error(s(168));ur(fr,t),ur(pr,n)}function yr(e,t,n){var a=e.stateNode;if(e=t.childContextTypes,"function"!=typeof a.getChildContext)return n;for(var o in a=a.getChildContext())if(!(o in e))throw Error(s(108,W(t)||"Unknown",o));return r({},n,a)}function xr(e){return e=(e=e.stateNode)&&e.__reactInternalMemoizedMergedChildContext||dr,mr=fr.current,ur(fr,e),ur(pr,pr.current),!0}function wr(e,t,n){var a=e.stateNode;if(!a)throw Error(s(169));n?(e=yr(e,t,mr),a.__reactInternalMemoizedMergedChildContext=e,cr(pr),cr(fr),ur(fr,e)):cr(pr),ur(pr,n)}var Sr=null,Er=null,kr=o.unstable_runWithPriority,_r=o.unstable_scheduleCallback,Cr=o.unstable_cancelCallback,qr=o.unstable_shouldYield,Tr=o.unstable_requestPaint,Ar=o.unstable_now,Lr=o.unstable_getCurrentPriorityLevel,Nr=o.unstable_ImmediatePriority,Or=o.unstable_UserBlockingPriority,Pr=o.unstable_NormalPriority,Ir=o.unstable_LowPriority,Rr=o.unstable_IdlePriority,Mr={},Dr=void 0!==Tr?Tr:function(){},Fr=null,Br=null,jr=!1,zr=Ar(),$r=1e4>zr?Ar:function(){return Ar()-zr};function Ur(){switch(Lr()){case Nr:return 99;case Or:return 98;case Pr:return 97;case Ir:return 96;case Rr:return 95;default:throw Error(s(332))}}function Zr(e){switch(e){case 99:return Nr;case 98:return Or;case 97:return Pr;case 96:return Ir;case 95:return Rr;default:throw Error(s(332))}}function Hr(e,t){return e=Zr(e),kr(e,t)}function Vr(e,t,n){return e=Zr(e),_r(e,t,n)}function Wr(){if(null!==Br){var e=Br;Br=null,Cr(e)}Gr()}function Gr(){if(!jr&&null!==Fr){jr=!0;var e=0;try{var t=Fr;Hr(99,(function(){for(;e<t.length;e++){var n=t[e];do{n=n(!0)}while(null!==n)}})),Fr=null}catch(n){throw null!==Fr&&(Fr=Fr.slice(e+1)),_r(Nr,Wr),n}finally{jr=!1}}}var Yr=w.ReactCurrentBatchConfig;function Kr(e,t){if(e&&e.defaultProps){for(var n in t=r({},t),e=e.defaultProps)void 0===t[n]&&(t[n]=e[n]);return t}return t}var Qr=lr(null),Xr=null,Jr=null,eo=null;function to(){eo=Jr=Xr=null}function no(e){var t=Qr.current;cr(Qr),e.type._context._currentValue=t}function ao(e,t){for(;null!==e;){var n=e.alternate;if((e.childLanes&t)===t){if(null===n||(n.childLanes&t)===t)break;n.childLanes|=t}else e.childLanes|=t,null!==n&&(n.childLanes|=t);e=e.return}}function ro(e,t){Xr=e,eo=Jr=null,null!==(e=e.dependencies)&&null!==e.firstContext&&(0!=(e.lanes&t)&&(Ms=!0),e.firstContext=null)}function oo(e,t){if(eo!==e&&!1!==t&&0!==t)if("number"==typeof t&&1073741823!==t||(eo=e,t=1073741823),t={context:e,observedBits:t,next:null},null===Jr){if(null===Xr)throw Error(s(308));Jr=t,Xr.dependencies={lanes:0,firstContext:t,responders:null}}else Jr=Jr.next=t;return e._currentValue}var so=!1;function io(e){e.updateQueue={baseState:e.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null},effects:null}}function lo(e,t){e=e.updateQueue,t.updateQueue===e&&(t.updateQueue={baseState:e.baseState,firstBaseUpdate:e.firstBaseUpdate,lastBaseUpdate:e.lastBaseUpdate,shared:e.shared,effects:e.effects})}function co(e,t){return{eventTime:e,lane:t,tag:0,payload:null,callback:null,next:null}}function uo(e,t){if(null!==(e=e.updateQueue)){var n=(e=e.shared).pending;null===n?t.next=t:(t.next=n.next,n.next=t),e.pending=t}}function fo(e,t){var n=e.updateQueue,a=e.alternate;if(null!==a&&n===(a=a.updateQueue)){var r=null,o=null;if(null!==(n=n.firstBaseUpdate)){do{var s={eventTime:n.eventTime,lane:n.lane,tag:n.tag,payload:n.payload,callback:n.callback,next:null};null===o?r=o=s:o=o.next=s,n=n.next}while(null!==n);null===o?r=o=t:o=o.next=t}else r=o=t;return n={baseState:a.baseState,firstBaseUpdate:r,lastBaseUpdate:o,shared:a.shared,effects:a.effects},void(e.updateQueue=n)}null===(e=n.lastBaseUpdate)?n.firstBaseUpdate=t:e.next=t,n.lastBaseUpdate=t}function po(e,t,n,a){var o=e.updateQueue;so=!1;var s=o.firstBaseUpdate,i=o.lastBaseUpdate,l=o.shared.pending;if(null!==l){o.shared.pending=null;var c=l,u=c.next;c.next=null,null===i?s=u:i.next=u,i=c;var d=e.alternate;if(null!==d){var f=(d=d.updateQueue).lastBaseUpdate;f!==i&&(null===f?d.firstBaseUpdate=u:f.next=u,d.lastBaseUpdate=c)}}if(null!==s){for(f=o.baseState,i=0,d=u=c=null;;){l=s.lane;var p=s.eventTime;if((a&l)===l){null!==d&&(d=d.next={eventTime:p,lane:0,tag:s.tag,payload:s.payload,callback:s.callback,next:null});e:{var m=e,g=s;switch(l=t,p=n,g.tag){case 1:if("function"==typeof(m=g.payload)){f=m.call(p,f,l);break e}f=m;break e;case 3:m.flags=-4097&m.flags|64;case 0:if(null==(l="function"==typeof(m=g.payload)?m.call(p,f,l):m))break e;f=r({},f,l);break e;case 2:so=!0}}null!==s.callback&&(e.flags|=32,null===(l=o.effects)?o.effects=[s]:l.push(s))}else p={eventTime:p,lane:l,tag:s.tag,payload:s.payload,callback:s.callback,next:null},null===d?(u=d=p,c=f):d=d.next=p,i|=l;if(null===(s=s.next)){if(null===(l=o.shared.pending))break;s=l.next,l.next=null,o.lastBaseUpdate=l,o.shared.pending=null}}null===d&&(c=f),o.baseState=c,o.firstBaseUpdate=u,o.lastBaseUpdate=d,zi|=i,e.lanes=i,e.memoizedState=f}}function mo(e,t,n){if(e=t.effects,t.effects=null,null!==e)for(t=0;t<e.length;t++){var a=e[t],r=a.callback;if(null!==r){if(a.callback=null,a=n,"function"!=typeof r)throw Error(s(191,r));r.call(a)}}}var go=(new a.Component).refs;function ho(e,t,n,a){n=null==(n=n(a,t=e.memoizedState))?t:r({},t,n),e.memoizedState=n,0===e.lanes&&(e.updateQueue.baseState=n)}var bo={isMounted:function(e){return!!(e=e._reactInternals)&&Ye(e)===e},enqueueSetState:function(e,t,n){e=e._reactInternals;var a=fl(),r=pl(e),o=co(a,r);o.payload=t,null!=n&&(o.callback=n),uo(e,o),ml(e,r,a)},enqueueReplaceState:function(e,t,n){e=e._reactInternals;var a=fl(),r=pl(e),o=co(a,r);o.tag=1,o.payload=t,null!=n&&(o.callback=n),uo(e,o),ml(e,r,a)},enqueueForceUpdate:function(e,t){e=e._reactInternals;var n=fl(),a=pl(e),r=co(n,a);r.tag=2,null!=t&&(r.callback=t),uo(e,r),ml(e,a,n)}};function vo(e,t,n,a,r,o,s){return"function"==typeof(e=e.stateNode).shouldComponentUpdate?e.shouldComponentUpdate(a,o,s):!t.prototype||!t.prototype.isPureReactComponent||(!da(n,a)||!da(r,o))}function yo(e,t,n){var a=!1,r=dr,o=t.contextType;return"object"==typeof o&&null!==o?o=oo(o):(r=hr(t)?mr:fr.current,o=(a=null!=(a=t.contextTypes))?gr(e,r):dr),t=new t(n,o),e.memoizedState=null!==t.state&&void 0!==t.state?t.state:null,t.updater=bo,e.stateNode=t,t._reactInternals=e,a&&((e=e.stateNode).__reactInternalMemoizedUnmaskedChildContext=r,e.__reactInternalMemoizedMaskedChildContext=o),t}function xo(e,t,n,a){e=t.state,"function"==typeof t.componentWillReceiveProps&&t.componentWillReceiveProps(n,a),"function"==typeof t.UNSAFE_componentWillReceiveProps&&t.UNSAFE_componentWillReceiveProps(n,a),t.state!==e&&bo.enqueueReplaceState(t,t.state,null)}function wo(e,t,n,a){var r=e.stateNode;r.props=n,r.state=e.memoizedState,r.refs=go,io(e);var o=t.contextType;"object"==typeof o&&null!==o?r.context=oo(o):(o=hr(t)?mr:fr.current,r.context=gr(e,o)),po(e,n,r,a),r.state=e.memoizedState,"function"==typeof(o=t.getDerivedStateFromProps)&&(ho(e,t,o,n),r.state=e.memoizedState),"function"==typeof t.getDerivedStateFromProps||"function"==typeof r.getSnapshotBeforeUpdate||"function"!=typeof r.UNSAFE_componentWillMount&&"function"!=typeof r.componentWillMount||(t=r.state,"function"==typeof r.componentWillMount&&r.componentWillMount(),"function"==typeof r.UNSAFE_componentWillMount&&r.UNSAFE_componentWillMount(),t!==r.state&&bo.enqueueReplaceState(r,r.state,null),po(e,n,r,a),r.state=e.memoizedState),"function"==typeof r.componentDidMount&&(e.flags|=4)}var So=Array.isArray;function Eo(e,t,n){if(null!==(e=n.ref)&&"function"!=typeof e&&"object"!=typeof e){if(n._owner){if(n=n._owner){if(1!==n.tag)throw Error(s(309));var a=n.stateNode}if(!a)throw Error(s(147,e));var r=""+e;return null!==t&&null!==t.ref&&"function"==typeof t.ref&&t.ref._stringRef===r?t.ref:(t=function(e){var t=a.refs;t===go&&(t=a.refs={}),null===e?delete t[r]:t[r]=e},t._stringRef=r,t)}if("string"!=typeof e)throw Error(s(284));if(!n._owner)throw Error(s(290,e))}return e}function ko(e,t){if("textarea"!==e.type)throw Error(s(31,"[object Object]"===Object.prototype.toString.call(t)?"object with keys {"+Object.keys(t).join(", ")+"}":t))}function _o(e){function t(t,n){if(e){var a=t.lastEffect;null!==a?(a.nextEffect=n,t.lastEffect=n):t.firstEffect=t.lastEffect=n,n.nextEffect=null,n.flags=8}}function n(n,a){if(!e)return null;for(;null!==a;)t(n,a),a=a.sibling;return null}function a(e,t){for(e=new Map;null!==t;)null!==t.key?e.set(t.key,t):e.set(t.index,t),t=t.sibling;return e}function r(e,t){return(e=Vl(e,t)).index=0,e.sibling=null,e}function o(t,n,a){return t.index=a,e?null!==(a=t.alternate)?(a=a.index)<n?(t.flags=2,n):a:(t.flags=2,n):n}function i(t){return e&&null===t.alternate&&(t.flags=2),t}function l(e,t,n,a){return null===t||6!==t.tag?((t=Kl(n,e.mode,a)).return=e,t):((t=r(t,n)).return=e,t)}function c(e,t,n,a){return null!==t&&t.elementType===n.type?((a=r(t,n.props)).ref=Eo(e,t,n),a.return=e,a):((a=Wl(n.type,n.key,n.props,null,e.mode,a)).ref=Eo(e,t,n),a.return=e,a)}function u(e,t,n,a){return null===t||4!==t.tag||t.stateNode.containerInfo!==n.containerInfo||t.stateNode.implementation!==n.implementation?((t=Ql(n,e.mode,a)).return=e,t):((t=r(t,n.children||[])).return=e,t)}function d(e,t,n,a,o){return null===t||7!==t.tag?((t=Gl(n,e.mode,a,o)).return=e,t):((t=r(t,n)).return=e,t)}function f(e,t,n){if("string"==typeof t||"number"==typeof t)return(t=Kl(""+t,e.mode,n)).return=e,t;if("object"==typeof t&&null!==t){switch(t.$$typeof){case S:return(n=Wl(t.type,t.key,t.props,null,e.mode,n)).ref=Eo(e,null,t),n.return=e,n;case E:return(t=Ql(t,e.mode,n)).return=e,t}if(So(t)||$(t))return(t=Gl(t,e.mode,n,null)).return=e,t;ko(e,t)}return null}function p(e,t,n,a){var r=null!==t?t.key:null;if("string"==typeof n||"number"==typeof n)return null!==r?null:l(e,t,""+n,a);if("object"==typeof n&&null!==n){switch(n.$$typeof){case S:return n.key===r?n.type===k?d(e,t,n.props.children,a,r):c(e,t,n,a):null;case E:return n.key===r?u(e,t,n,a):null}if(So(n)||$(n))return null!==r?null:d(e,t,n,a,null);ko(e,n)}return null}function m(e,t,n,a,r){if("string"==typeof a||"number"==typeof a)return l(t,e=e.get(n)||null,""+a,r);if("object"==typeof a&&null!==a){switch(a.$$typeof){case S:return e=e.get(null===a.key?n:a.key)||null,a.type===k?d(t,e,a.props.children,r,a.key):c(t,e,a,r);case E:return u(t,e=e.get(null===a.key?n:a.key)||null,a,r)}if(So(a)||$(a))return d(t,e=e.get(n)||null,a,r,null);ko(t,a)}return null}function g(r,s,i,l){for(var c=null,u=null,d=s,g=s=0,h=null;null!==d&&g<i.length;g++){d.index>g?(h=d,d=null):h=d.sibling;var b=p(r,d,i[g],l);if(null===b){null===d&&(d=h);break}e&&d&&null===b.alternate&&t(r,d),s=o(b,s,g),null===u?c=b:u.sibling=b,u=b,d=h}if(g===i.length)return n(r,d),c;if(null===d){for(;g<i.length;g++)null!==(d=f(r,i[g],l))&&(s=o(d,s,g),null===u?c=d:u.sibling=d,u=d);return c}for(d=a(r,d);g<i.length;g++)null!==(h=m(d,r,g,i[g],l))&&(e&&null!==h.alternate&&d.delete(null===h.key?g:h.key),s=o(h,s,g),null===u?c=h:u.sibling=h,u=h);return e&&d.forEach((function(e){return t(r,e)})),c}function h(r,i,l,c){var u=$(l);if("function"!=typeof u)throw Error(s(150));if(null==(l=u.call(l)))throw Error(s(151));for(var d=u=null,g=i,h=i=0,b=null,v=l.next();null!==g&&!v.done;h++,v=l.next()){g.index>h?(b=g,g=null):b=g.sibling;var y=p(r,g,v.value,c);if(null===y){null===g&&(g=b);break}e&&g&&null===y.alternate&&t(r,g),i=o(y,i,h),null===d?u=y:d.sibling=y,d=y,g=b}if(v.done)return n(r,g),u;if(null===g){for(;!v.done;h++,v=l.next())null!==(v=f(r,v.value,c))&&(i=o(v,i,h),null===d?u=v:d.sibling=v,d=v);return u}for(g=a(r,g);!v.done;h++,v=l.next())null!==(v=m(g,r,h,v.value,c))&&(e&&null!==v.alternate&&g.delete(null===v.key?h:v.key),i=o(v,i,h),null===d?u=v:d.sibling=v,d=v);return e&&g.forEach((function(e){return t(r,e)})),u}return function(e,a,o,l){var c="object"==typeof o&&null!==o&&o.type===k&&null===o.key;c&&(o=o.props.children);var u="object"==typeof o&&null!==o;if(u)switch(o.$$typeof){case S:e:{for(u=o.key,c=a;null!==c;){if(c.key===u){if(7===c.tag){if(o.type===k){n(e,c.sibling),(a=r(c,o.props.children)).return=e,e=a;break e}}else if(c.elementType===o.type){n(e,c.sibling),(a=r(c,o.props)).ref=Eo(e,c,o),a.return=e,e=a;break e}n(e,c);break}t(e,c),c=c.sibling}o.type===k?((a=Gl(o.props.children,e.mode,l,o.key)).return=e,e=a):((l=Wl(o.type,o.key,o.props,null,e.mode,l)).ref=Eo(e,a,o),l.return=e,e=l)}return i(e);case E:e:{for(c=o.key;null!==a;){if(a.key===c){if(4===a.tag&&a.stateNode.containerInfo===o.containerInfo&&a.stateNode.implementation===o.implementation){n(e,a.sibling),(a=r(a,o.children||[])).return=e,e=a;break e}n(e,a);break}t(e,a),a=a.sibling}(a=Ql(o,e.mode,l)).return=e,e=a}return i(e)}if("string"==typeof o||"number"==typeof o)return o=""+o,null!==a&&6===a.tag?(n(e,a.sibling),(a=r(a,o)).return=e,e=a):(n(e,a),(a=Kl(o,e.mode,l)).return=e,e=a),i(e);if(So(o))return g(e,a,o,l);if($(o))return h(e,a,o,l);if(u&&ko(e,o),void 0===o&&!c)switch(e.tag){case 1:case 22:case 0:case 11:case 15:throw Error(s(152,W(e.type)||"Component"))}return n(e,a)}}var Co=_o(!0),qo=_o(!1),To={},Ao=lr(To),Lo=lr(To),No=lr(To);function Oo(e){if(e===To)throw Error(s(174));return e}function Po(e,t){switch(ur(No,t),ur(Lo,e),ur(Ao,To),e=t.nodeType){case 9:case 11:t=(t=t.documentElement)?t.namespaceURI:pe(null,"");break;default:t=pe(t=(e=8===e?t.parentNode:t).namespaceURI||null,e=e.tagName)}cr(Ao),ur(Ao,t)}function Io(){cr(Ao),cr(Lo),cr(No)}function Ro(e){Oo(No.current);var t=Oo(Ao.current),n=pe(t,e.type);t!==n&&(ur(Lo,e),ur(Ao,n))}function Mo(e){Lo.current===e&&(cr(Ao),cr(Lo))}var Do=lr(0);function Fo(e){for(var t=e;null!==t;){if(13===t.tag){var n=t.memoizedState;if(null!==n&&(null===(n=n.dehydrated)||"$?"===n.data||"$!"===n.data))return t}else if(19===t.tag&&void 0!==t.memoizedProps.revealOrder){if(0!=(64&t.flags))return t}else if(null!==t.child){t.child.return=t,t=t.child;continue}if(t===e)break;for(;null===t.sibling;){if(null===t.return||t.return===e)return null;t=t.return}t.sibling.return=t.return,t=t.sibling}return null}var Bo=null,jo=null,zo=!1;function $o(e,t){var n=Zl(5,null,null,0);n.elementType="DELETED",n.type="DELETED",n.stateNode=t,n.return=e,n.flags=8,null!==e.lastEffect?(e.lastEffect.nextEffect=n,e.lastEffect=n):e.firstEffect=e.lastEffect=n}function Uo(e,t){switch(e.tag){case 5:var n=e.type;return null!==(t=1!==t.nodeType||n.toLowerCase()!==t.nodeName.toLowerCase()?null:t)&&(e.stateNode=t,!0);case 6:return null!==(t=""===e.pendingProps||3!==t.nodeType?null:t)&&(e.stateNode=t,!0);default:return!1}}function Zo(e){if(zo){var t=jo;if(t){var n=t;if(!Uo(e,t)){if(!(t=Wa(n.nextSibling))||!Uo(e,t))return e.flags=-1025&e.flags|2,zo=!1,void(Bo=e);$o(Bo,n)}Bo=e,jo=Wa(t.firstChild)}else e.flags=-1025&e.flags|2,zo=!1,Bo=e}}function Ho(e){for(e=e.return;null!==e&&5!==e.tag&&3!==e.tag&&13!==e.tag;)e=e.return;Bo=e}function Vo(e){if(e!==Bo)return!1;if(!zo)return Ho(e),zo=!0,!1;var t=e.type;if(5!==e.tag||"head"!==t&&"body"!==t&&!Ua(t,e.memoizedProps))for(t=jo;t;)$o(e,t),t=Wa(t.nextSibling);if(Ho(e),13===e.tag){if(!(e=null!==(e=e.memoizedState)?e.dehydrated:null))throw Error(s(317));e:{for(e=e.nextSibling,t=0;e;){if(8===e.nodeType){var n=e.data;if("/$"===n){if(0===t){jo=Wa(e.nextSibling);break e}t--}else"$"!==n&&"$!"!==n&&"$?"!==n||t++}e=e.nextSibling}jo=null}}else jo=Bo?Wa(e.stateNode.nextSibling):null;return!0}function Wo(){jo=Bo=null,zo=!1}var Go=[];function Yo(){for(var e=0;e<Go.length;e++)Go[e]._workInProgressVersionPrimary=null;Go.length=0}var Ko=w.ReactCurrentDispatcher,Qo=w.ReactCurrentBatchConfig,Xo=0,Jo=null,es=null,ts=null,ns=!1,as=!1;function rs(){throw Error(s(321))}function os(e,t){if(null===t)return!1;for(var n=0;n<t.length&&n<e.length;n++)if(!ca(e[n],t[n]))return!1;return!0}function ss(e,t,n,a,r,o){if(Xo=o,Jo=t,t.memoizedState=null,t.updateQueue=null,t.lanes=0,Ko.current=null===e||null===e.memoizedState?Os:Ps,e=n(a,r),as){o=0;do{if(as=!1,!(25>o))throw Error(s(301));o+=1,ts=es=null,t.updateQueue=null,Ko.current=Is,e=n(a,r)}while(as)}if(Ko.current=Ns,t=null!==es&&null!==es.next,Xo=0,ts=es=Jo=null,ns=!1,t)throw Error(s(300));return e}function is(){var e={memoizedState:null,baseState:null,baseQueue:null,queue:null,next:null};return null===ts?Jo.memoizedState=ts=e:ts=ts.next=e,ts}function ls(){if(null===es){var e=Jo.alternate;e=null!==e?e.memoizedState:null}else e=es.next;var t=null===ts?Jo.memoizedState:ts.next;if(null!==t)ts=t,es=e;else{if(null===e)throw Error(s(310));e={memoizedState:(es=e).memoizedState,baseState:es.baseState,baseQueue:es.baseQueue,queue:es.queue,next:null},null===ts?Jo.memoizedState=ts=e:ts=ts.next=e}return ts}function cs(e,t){return"function"==typeof t?t(e):t}function us(e){var t=ls(),n=t.queue;if(null===n)throw Error(s(311));n.lastRenderedReducer=e;var a=es,r=a.baseQueue,o=n.pending;if(null!==o){if(null!==r){var i=r.next;r.next=o.next,o.next=i}a.baseQueue=r=o,n.pending=null}if(null!==r){r=r.next,a=a.baseState;var l=i=o=null,c=r;do{var u=c.lane;if((Xo&u)===u)null!==l&&(l=l.next={lane:0,action:c.action,eagerReducer:c.eagerReducer,eagerState:c.eagerState,next:null}),a=c.eagerReducer===e?c.eagerState:e(a,c.action);else{var d={lane:u,action:c.action,eagerReducer:c.eagerReducer,eagerState:c.eagerState,next:null};null===l?(i=l=d,o=a):l=l.next=d,Jo.lanes|=u,zi|=u}c=c.next}while(null!==c&&c!==r);null===l?o=a:l.next=i,ca(a,t.memoizedState)||(Ms=!0),t.memoizedState=a,t.baseState=o,t.baseQueue=l,n.lastRenderedState=a}return[t.memoizedState,n.dispatch]}function ds(e){var t=ls(),n=t.queue;if(null===n)throw Error(s(311));n.lastRenderedReducer=e;var a=n.dispatch,r=n.pending,o=t.memoizedState;if(null!==r){n.pending=null;var i=r=r.next;do{o=e(o,i.action),i=i.next}while(i!==r);ca(o,t.memoizedState)||(Ms=!0),t.memoizedState=o,null===t.baseQueue&&(t.baseState=o),n.lastRenderedState=o}return[o,a]}function fs(e,t,n){var a=t._getVersion;a=a(t._source);var r=t._workInProgressVersionPrimary;if(null!==r?e=r===a:(e=e.mutableReadLanes,(e=(Xo&e)===e)&&(t._workInProgressVersionPrimary=a,Go.push(t))),e)return n(t._source);throw Go.push(t),Error(s(350))}function ps(e,t,n,a){var r=Pi;if(null===r)throw Error(s(349));var o=t._getVersion,i=o(t._source),l=Ko.current,c=l.useState((function(){return fs(r,t,n)})),u=c[1],d=c[0];c=ts;var f=e.memoizedState,p=f.refs,m=p.getSnapshot,g=f.source;f=f.subscribe;var h=Jo;return e.memoizedState={refs:p,source:t,subscribe:a},l.useEffect((function(){p.getSnapshot=n,p.setSnapshot=u;var e=o(t._source);if(!ca(i,e)){e=n(t._source),ca(d,e)||(u(e),e=pl(h),r.mutableReadLanes|=e&r.pendingLanes),e=r.mutableReadLanes,r.entangledLanes|=e;for(var a=r.entanglements,s=e;0<s;){var l=31-Ut(s),c=1<<l;a[l]|=e,s&=~c}}}),[n,t,a]),l.useEffect((function(){return a(t._source,(function(){var e=p.getSnapshot,n=p.setSnapshot;try{n(e(t._source));var a=pl(h);r.mutableReadLanes|=a&r.pendingLanes}catch(o){n((function(){throw o}))}}))}),[t,a]),ca(m,n)&&ca(g,t)&&ca(f,a)||((e={pending:null,dispatch:null,lastRenderedReducer:cs,lastRenderedState:d}).dispatch=u=Ls.bind(null,Jo,e),c.queue=e,c.baseQueue=null,d=fs(r,t,n),c.memoizedState=c.baseState=d),d}function ms(e,t,n){return ps(ls(),e,t,n)}function gs(e){var t=is();return"function"==typeof e&&(e=e()),t.memoizedState=t.baseState=e,e=(e=t.queue={pending:null,dispatch:null,lastRenderedReducer:cs,lastRenderedState:e}).dispatch=Ls.bind(null,Jo,e),[t.memoizedState,e]}function hs(e,t,n,a){return e={tag:e,create:t,destroy:n,deps:a,next:null},null===(t=Jo.updateQueue)?(t={lastEffect:null},Jo.updateQueue=t,t.lastEffect=e.next=e):null===(n=t.lastEffect)?t.lastEffect=e.next=e:(a=n.next,n.next=e,e.next=a,t.lastEffect=e),e}function bs(e){return e={current:e},is().memoizedState=e}function vs(){return ls().memoizedState}function ys(e,t,n,a){var r=is();Jo.flags|=e,r.memoizedState=hs(1|t,n,void 0,void 0===a?null:a)}function xs(e,t,n,a){var r=ls();a=void 0===a?null:a;var o=void 0;if(null!==es){var s=es.memoizedState;if(o=s.destroy,null!==a&&os(a,s.deps))return void hs(t,n,o,a)}Jo.flags|=e,r.memoizedState=hs(1|t,n,o,a)}function ws(e,t){return ys(516,4,e,t)}function Ss(e,t){return xs(516,4,e,t)}function Es(e,t){return xs(4,2,e,t)}function ks(e,t){return"function"==typeof t?(e=e(),t(e),function(){t(null)}):null!=t?(e=e(),t.current=e,function(){t.current=null}):void 0}function _s(e,t,n){return n=null!=n?n.concat([e]):null,xs(4,2,ks.bind(null,t,e),n)}function Cs(){}function qs(e,t){var n=ls();t=void 0===t?null:t;var a=n.memoizedState;return null!==a&&null!==t&&os(t,a[1])?a[0]:(n.memoizedState=[e,t],e)}function Ts(e,t){var n=ls();t=void 0===t?null:t;var a=n.memoizedState;return null!==a&&null!==t&&os(t,a[1])?a[0]:(e=e(),n.memoizedState=[e,t],e)}function As(e,t){var n=Ur();Hr(98>n?98:n,(function(){e(!0)})),Hr(97<n?97:n,(function(){var n=Qo.transition;Qo.transition=1;try{e(!1),t()}finally{Qo.transition=n}}))}function Ls(e,t,n){var a=fl(),r=pl(e),o={lane:r,action:n,eagerReducer:null,eagerState:null,next:null},s=t.pending;if(null===s?o.next=o:(o.next=s.next,s.next=o),t.pending=o,s=e.alternate,e===Jo||null!==s&&s===Jo)as=ns=!0;else{if(0===e.lanes&&(null===s||0===s.lanes)&&null!==(s=t.lastRenderedReducer))try{var i=t.lastRenderedState,l=s(i,n);if(o.eagerReducer=s,o.eagerState=l,ca(l,i))return}catch(c){}ml(e,r,a)}}var Ns={readContext:oo,useCallback:rs,useContext:rs,useEffect:rs,useImperativeHandle:rs,useLayoutEffect:rs,useMemo:rs,useReducer:rs,useRef:rs,useState:rs,useDebugValue:rs,useDeferredValue:rs,useTransition:rs,useMutableSource:rs,useOpaqueIdentifier:rs,unstable_isNewReconciler:!1},Os={readContext:oo,useCallback:function(e,t){return is().memoizedState=[e,void 0===t?null:t],e},useContext:oo,useEffect:ws,useImperativeHandle:function(e,t,n){return n=null!=n?n.concat([e]):null,ys(4,2,ks.bind(null,t,e),n)},useLayoutEffect:function(e,t){return ys(4,2,e,t)},useMemo:function(e,t){var n=is();return t=void 0===t?null:t,e=e(),n.memoizedState=[e,t],e},useReducer:function(e,t,n){var a=is();return t=void 0!==n?n(t):t,a.memoizedState=a.baseState=t,e=(e=a.queue={pending:null,dispatch:null,lastRenderedReducer:e,lastRenderedState:t}).dispatch=Ls.bind(null,Jo,e),[a.memoizedState,e]},useRef:bs,useState:gs,useDebugValue:Cs,useDeferredValue:function(e){var t=gs(e),n=t[0],a=t[1];return ws((function(){var t=Qo.transition;Qo.transition=1;try{a(e)}finally{Qo.transition=t}}),[e]),n},useTransition:function(){var e=gs(!1),t=e[0];return bs(e=As.bind(null,e[1])),[e,t]},useMutableSource:function(e,t,n){var a=is();return a.memoizedState={refs:{getSnapshot:t,setSnapshot:null},source:e,subscribe:n},ps(a,e,t,n)},useOpaqueIdentifier:function(){if(zo){var e=!1,t=function(e){return{$$typeof:R,toString:e,valueOf:e}}((function(){throw e||(e=!0,n("r:"+(Ya++).toString(36))),Error(s(355))})),n=gs(t)[1];return 0==(2&Jo.mode)&&(Jo.flags|=516,hs(5,(function(){n("r:"+(Ya++).toString(36))}),void 0,null)),t}return gs(t="r:"+(Ya++).toString(36)),t},unstable_isNewReconciler:!1},Ps={readContext:oo,useCallback:qs,useContext:oo,useEffect:Ss,useImperativeHandle:_s,useLayoutEffect:Es,useMemo:Ts,useReducer:us,useRef:vs,useState:function(){return us(cs)},useDebugValue:Cs,useDeferredValue:function(e){var t=us(cs),n=t[0],a=t[1];return Ss((function(){var t=Qo.transition;Qo.transition=1;try{a(e)}finally{Qo.transition=t}}),[e]),n},useTransition:function(){var e=us(cs)[0];return[vs().current,e]},useMutableSource:ms,useOpaqueIdentifier:function(){return us(cs)[0]},unstable_isNewReconciler:!1},Is={readContext:oo,useCallback:qs,useContext:oo,useEffect:Ss,useImperativeHandle:_s,useLayoutEffect:Es,useMemo:Ts,useReducer:ds,useRef:vs,useState:function(){return ds(cs)},useDebugValue:Cs,useDeferredValue:function(e){var t=ds(cs),n=t[0],a=t[1];return Ss((function(){var t=Qo.transition;Qo.transition=1;try{a(e)}finally{Qo.transition=t}}),[e]),n},useTransition:function(){var e=ds(cs)[0];return[vs().current,e]},useMutableSource:ms,useOpaqueIdentifier:function(){return ds(cs)[0]},unstable_isNewReconciler:!1},Rs=w.ReactCurrentOwner,Ms=!1;function Ds(e,t,n,a){t.child=null===e?qo(t,null,n,a):Co(t,e.child,n,a)}function Fs(e,t,n,a,r){n=n.render;var o=t.ref;return ro(t,r),a=ss(e,t,n,a,o,r),null===e||Ms?(t.flags|=1,Ds(e,t,a,r),t.child):(t.updateQueue=e.updateQueue,t.flags&=-517,e.lanes&=~r,oi(e,t,r))}function Bs(e,t,n,a,r,o){if(null===e){var s=n.type;return"function"!=typeof s||Hl(s)||void 0!==s.defaultProps||null!==n.compare||void 0!==n.defaultProps?((e=Wl(n.type,null,a,t,t.mode,o)).ref=t.ref,e.return=t,t.child=e):(t.tag=15,t.type=s,js(e,t,s,a,r,o))}return s=e.child,0==(r&o)&&(r=s.memoizedProps,(n=null!==(n=n.compare)?n:da)(r,a)&&e.ref===t.ref)?oi(e,t,o):(t.flags|=1,(e=Vl(s,a)).ref=t.ref,e.return=t,t.child=e)}function js(e,t,n,a,r,o){if(null!==e&&da(e.memoizedProps,a)&&e.ref===t.ref){if(Ms=!1,0==(o&r))return t.lanes=e.lanes,oi(e,t,o);0!=(16384&e.flags)&&(Ms=!0)}return Us(e,t,n,a,o)}function zs(e,t,n){var a=t.pendingProps,r=a.children,o=null!==e?e.memoizedState:null;if("hidden"===a.mode||"unstable-defer-without-hiding"===a.mode)if(0==(4&t.mode))t.memoizedState={baseLanes:0},Sl(t,n);else{if(0==(1073741824&n))return e=null!==o?o.baseLanes|n:n,t.lanes=t.childLanes=1073741824,t.memoizedState={baseLanes:e},Sl(t,e),null;t.memoizedState={baseLanes:0},Sl(t,null!==o?o.baseLanes:n)}else null!==o?(a=o.baseLanes|n,t.memoizedState=null):a=n,Sl(t,a);return Ds(e,t,r,n),t.child}function $s(e,t){var n=t.ref;(null===e&&null!==n||null!==e&&e.ref!==n)&&(t.flags|=128)}function Us(e,t,n,a,r){var o=hr(n)?mr:fr.current;return o=gr(t,o),ro(t,r),n=ss(e,t,n,a,o,r),null===e||Ms?(t.flags|=1,Ds(e,t,n,r),t.child):(t.updateQueue=e.updateQueue,t.flags&=-517,e.lanes&=~r,oi(e,t,r))}function Zs(e,t,n,a,r){if(hr(n)){var o=!0;xr(t)}else o=!1;if(ro(t,r),null===t.stateNode)null!==e&&(e.alternate=null,t.alternate=null,t.flags|=2),yo(t,n,a),wo(t,n,a,r),a=!0;else if(null===e){var s=t.stateNode,i=t.memoizedProps;s.props=i;var l=s.context,c=n.contextType;"object"==typeof c&&null!==c?c=oo(c):c=gr(t,c=hr(n)?mr:fr.current);var u=n.getDerivedStateFromProps,d="function"==typeof u||"function"==typeof s.getSnapshotBeforeUpdate;d||"function"!=typeof s.UNSAFE_componentWillReceiveProps&&"function"!=typeof s.componentWillReceiveProps||(i!==a||l!==c)&&xo(t,s,a,c),so=!1;var f=t.memoizedState;s.state=f,po(t,a,s,r),l=t.memoizedState,i!==a||f!==l||pr.current||so?("function"==typeof u&&(ho(t,n,u,a),l=t.memoizedState),(i=so||vo(t,n,i,a,f,l,c))?(d||"function"!=typeof s.UNSAFE_componentWillMount&&"function"!=typeof s.componentWillMount||("function"==typeof s.componentWillMount&&s.componentWillMount(),"function"==typeof s.UNSAFE_componentWillMount&&s.UNSAFE_componentWillMount()),"function"==typeof s.componentDidMount&&(t.flags|=4)):("function"==typeof s.componentDidMount&&(t.flags|=4),t.memoizedProps=a,t.memoizedState=l),s.props=a,s.state=l,s.context=c,a=i):("function"==typeof s.componentDidMount&&(t.flags|=4),a=!1)}else{s=t.stateNode,lo(e,t),i=t.memoizedProps,c=t.type===t.elementType?i:Kr(t.type,i),s.props=c,d=t.pendingProps,f=s.context,"object"==typeof(l=n.contextType)&&null!==l?l=oo(l):l=gr(t,l=hr(n)?mr:fr.current);var p=n.getDerivedStateFromProps;(u="function"==typeof p||"function"==typeof s.getSnapshotBeforeUpdate)||"function"!=typeof s.UNSAFE_componentWillReceiveProps&&"function"!=typeof s.componentWillReceiveProps||(i!==d||f!==l)&&xo(t,s,a,l),so=!1,f=t.memoizedState,s.state=f,po(t,a,s,r);var m=t.memoizedState;i!==d||f!==m||pr.current||so?("function"==typeof p&&(ho(t,n,p,a),m=t.memoizedState),(c=so||vo(t,n,c,a,f,m,l))?(u||"function"!=typeof s.UNSAFE_componentWillUpdate&&"function"!=typeof s.componentWillUpdate||("function"==typeof s.componentWillUpdate&&s.componentWillUpdate(a,m,l),"function"==typeof s.UNSAFE_componentWillUpdate&&s.UNSAFE_componentWillUpdate(a,m,l)),"function"==typeof s.componentDidUpdate&&(t.flags|=4),"function"==typeof s.getSnapshotBeforeUpdate&&(t.flags|=256)):("function"!=typeof s.componentDidUpdate||i===e.memoizedProps&&f===e.memoizedState||(t.flags|=4),"function"!=typeof s.getSnapshotBeforeUpdate||i===e.memoizedProps&&f===e.memoizedState||(t.flags|=256),t.memoizedProps=a,t.memoizedState=m),s.props=a,s.state=m,s.context=l,a=c):("function"!=typeof s.componentDidUpdate||i===e.memoizedProps&&f===e.memoizedState||(t.flags|=4),"function"!=typeof s.getSnapshotBeforeUpdate||i===e.memoizedProps&&f===e.memoizedState||(t.flags|=256),a=!1)}return Hs(e,t,n,a,o,r)}function Hs(e,t,n,a,r,o){$s(e,t);var s=0!=(64&t.flags);if(!a&&!s)return r&&wr(t,n,!1),oi(e,t,o);a=t.stateNode,Rs.current=t;var i=s&&"function"!=typeof n.getDerivedStateFromError?null:a.render();return t.flags|=1,null!==e&&s?(t.child=Co(t,e.child,null,o),t.child=Co(t,null,i,o)):Ds(e,t,i,o),t.memoizedState=a.state,r&&wr(t,n,!0),t.child}function Vs(e){var t=e.stateNode;t.pendingContext?vr(0,t.pendingContext,t.pendingContext!==t.context):t.context&&vr(0,t.context,!1),Po(e,t.containerInfo)}var Ws,Gs,Ys,Ks,Qs={dehydrated:null,retryLane:0};function Xs(e,t,n){var a,r=t.pendingProps,o=Do.current,s=!1;return(a=0!=(64&t.flags))||(a=(null===e||null!==e.memoizedState)&&0!=(2&o)),a?(s=!0,t.flags&=-65):null!==e&&null===e.memoizedState||void 0===r.fallback||!0===r.unstable_avoidThisFallback||(o|=1),ur(Do,1&o),null===e?(void 0!==r.fallback&&Zo(t),e=r.children,o=r.fallback,s?(e=Js(t,e,o,n),t.child.memoizedState={baseLanes:n},t.memoizedState=Qs,e):"number"==typeof r.unstable_expectedLoadTime?(e=Js(t,e,o,n),t.child.memoizedState={baseLanes:n},t.memoizedState=Qs,t.lanes=33554432,e):((n=Yl({mode:"visible",children:e},t.mode,n,null)).return=t,t.child=n)):(e.memoizedState,s?(r=ti(e,t,r.children,r.fallback,n),s=t.child,o=e.child.memoizedState,s.memoizedState=null===o?{baseLanes:n}:{baseLanes:o.baseLanes|n},s.childLanes=e.childLanes&~n,t.memoizedState=Qs,r):(n=ei(e,t,r.children,n),t.memoizedState=null,n))}function Js(e,t,n,a){var r=e.mode,o=e.child;return t={mode:"hidden",children:t},0==(2&r)&&null!==o?(o.childLanes=0,o.pendingProps=t):o=Yl(t,r,0,null),n=Gl(n,r,a,null),o.return=e,n.return=e,o.sibling=n,e.child=o,n}function ei(e,t,n,a){var r=e.child;return e=r.sibling,n=Vl(r,{mode:"visible",children:n}),0==(2&t.mode)&&(n.lanes=a),n.return=t,n.sibling=null,null!==e&&(e.nextEffect=null,e.flags=8,t.firstEffect=t.lastEffect=e),t.child=n}function ti(e,t,n,a,r){var o=t.mode,s=e.child;e=s.sibling;var i={mode:"hidden",children:n};return 0==(2&o)&&t.child!==s?((n=t.child).childLanes=0,n.pendingProps=i,null!==(s=n.lastEffect)?(t.firstEffect=n.firstEffect,t.lastEffect=s,s.nextEffect=null):t.firstEffect=t.lastEffect=null):n=Vl(s,i),null!==e?a=Vl(e,a):(a=Gl(a,o,r,null)).flags|=2,a.return=t,n.return=t,n.sibling=a,t.child=n,a}function ni(e,t){e.lanes|=t;var n=e.alternate;null!==n&&(n.lanes|=t),ao(e.return,t)}function ai(e,t,n,a,r,o){var s=e.memoizedState;null===s?e.memoizedState={isBackwards:t,rendering:null,renderingStartTime:0,last:a,tail:n,tailMode:r,lastEffect:o}:(s.isBackwards=t,s.rendering=null,s.renderingStartTime=0,s.last=a,s.tail=n,s.tailMode=r,s.lastEffect=o)}function ri(e,t,n){var a=t.pendingProps,r=a.revealOrder,o=a.tail;if(Ds(e,t,a.children,n),0!=(2&(a=Do.current)))a=1&a|2,t.flags|=64;else{if(null!==e&&0!=(64&e.flags))e:for(e=t.child;null!==e;){if(13===e.tag)null!==e.memoizedState&&ni(e,n);else if(19===e.tag)ni(e,n);else if(null!==e.child){e.child.return=e,e=e.child;continue}if(e===t)break e;for(;null===e.sibling;){if(null===e.return||e.return===t)break e;e=e.return}e.sibling.return=e.return,e=e.sibling}a&=1}if(ur(Do,a),0==(2&t.mode))t.memoizedState=null;else switch(r){case"forwards":for(n=t.child,r=null;null!==n;)null!==(e=n.alternate)&&null===Fo(e)&&(r=n),n=n.sibling;null===(n=r)?(r=t.child,t.child=null):(r=n.sibling,n.sibling=null),ai(t,!1,r,n,o,t.lastEffect);break;case"backwards":for(n=null,r=t.child,t.child=null;null!==r;){if(null!==(e=r.alternate)&&null===Fo(e)){t.child=r;break}e=r.sibling,r.sibling=n,n=r,r=e}ai(t,!0,n,null,o,t.lastEffect);break;case"together":ai(t,!1,null,null,void 0,t.lastEffect);break;default:t.memoizedState=null}return t.child}function oi(e,t,n){if(null!==e&&(t.dependencies=e.dependencies),zi|=t.lanes,0!=(n&t.childLanes)){if(null!==e&&t.child!==e.child)throw Error(s(153));if(null!==t.child){for(n=Vl(e=t.child,e.pendingProps),t.child=n,n.return=t;null!==e.sibling;)e=e.sibling,(n=n.sibling=Vl(e,e.pendingProps)).return=t;n.sibling=null}return t.child}return null}function si(e,t){if(!zo)switch(e.tailMode){case"hidden":t=e.tail;for(var n=null;null!==t;)null!==t.alternate&&(n=t),t=t.sibling;null===n?e.tail=null:n.sibling=null;break;case"collapsed":n=e.tail;for(var a=null;null!==n;)null!==n.alternate&&(a=n),n=n.sibling;null===a?t||null===e.tail?e.tail=null:e.tail.sibling=null:a.sibling=null}}function ii(e,t,n){var a=t.pendingProps;switch(t.tag){case 2:case 16:case 15:case 0:case 11:case 7:case 8:case 12:case 9:case 14:return null;case 1:case 17:return hr(t.type)&&br(),null;case 3:return Io(),cr(pr),cr(fr),Yo(),(a=t.stateNode).pendingContext&&(a.context=a.pendingContext,a.pendingContext=null),null!==e&&null!==e.child||(Vo(t)?t.flags|=4:a.hydrate||(t.flags|=256)),Gs(t),null;case 5:Mo(t);var o=Oo(No.current);if(n=t.type,null!==e&&null!=t.stateNode)Ys(e,t,n,a,o),e.ref!==t.ref&&(t.flags|=128);else{if(!a){if(null===t.stateNode)throw Error(s(166));return null}if(e=Oo(Ao.current),Vo(t)){a=t.stateNode,n=t.type;var i=t.memoizedProps;switch(a[Qa]=t,a[Xa]=i,n){case"dialog":Aa("cancel",a),Aa("close",a);break;case"iframe":case"object":case"embed":Aa("load",a);break;case"video":case"audio":for(e=0;e<_a.length;e++)Aa(_a[e],a);break;case"source":Aa("error",a);break;case"img":case"image":case"link":Aa("error",a),Aa("load",a);break;case"details":Aa("toggle",a);break;case"input":ee(a,i),Aa("invalid",a);break;case"select":a._wrapperState={wasMultiple:!!i.multiple},Aa("invalid",a);break;case"textarea":le(a,i),Aa("invalid",a)}for(var c in Ee(n,i),e=null,i)i.hasOwnProperty(c)&&(o=i[c],"children"===c?"string"==typeof o?a.textContent!==o&&(e=["children",o]):"number"==typeof o&&a.textContent!==""+o&&(e=["children",""+o]):l.hasOwnProperty(c)&&null!=o&&"onScroll"===c&&Aa("scroll",a));switch(n){case"input":K(a),ae(a,i,!0);break;case"textarea":K(a),ue(a);break;case"select":case"option":break;default:"function"==typeof i.onClick&&(a.onclick=Ba)}a=e,t.updateQueue=a,null!==a&&(t.flags|=4)}else{switch(c=9===o.nodeType?o:o.ownerDocument,e===de.html&&(e=fe(n)),e===de.html?"script"===n?((e=c.createElement("div")).innerHTML="<script><\/script>",e=e.removeChild(e.firstChild)):"string"==typeof a.is?e=c.createElement(n,{is:a.is}):(e=c.createElement(n),"select"===n&&(c=e,a.multiple?c.multiple=!0:a.size&&(c.size=a.size))):e=c.createElementNS(e,n),e[Qa]=t,e[Xa]=a,Ws(e,t,!1,!1),t.stateNode=e,c=ke(n,a),n){case"dialog":Aa("cancel",e),Aa("close",e),o=a;break;case"iframe":case"object":case"embed":Aa("load",e),o=a;break;case"video":case"audio":for(o=0;o<_a.length;o++)Aa(_a[o],e);o=a;break;case"source":Aa("error",e),o=a;break;case"img":case"image":case"link":Aa("error",e),Aa("load",e),o=a;break;case"details":Aa("toggle",e),o=a;break;case"input":ee(e,a),o=J(e,a),Aa("invalid",e);break;case"option":o=oe(e,a);break;case"select":e._wrapperState={wasMultiple:!!a.multiple},o=r({},a,{value:void 0}),Aa("invalid",e);break;case"textarea":le(e,a),o=ie(e,a),Aa("invalid",e);break;default:o=a}Ee(n,o);var u=o;for(i in u)if(u.hasOwnProperty(i)){var d=u[i];"style"===i?we(e,d):"dangerouslySetInnerHTML"===i?null!=(d=d?d.__html:void 0)&&he(e,d):"children"===i?"string"==typeof d?("textarea"!==n||""!==d)&&be(e,d):"number"==typeof d&&be(e,""+d):"suppressContentEditableWarning"!==i&&"suppressHydrationWarning"!==i&&"autoFocus"!==i&&(l.hasOwnProperty(i)?null!=d&&"onScroll"===i&&Aa("scroll",e):null!=d&&x(e,i,d,c))}switch(n){case"input":K(e),ae(e,a,!1);break;case"textarea":K(e),ue(e);break;case"option":null!=a.value&&e.setAttribute("value",""+G(a.value));break;case"select":e.multiple=!!a.multiple,null!=(i=a.value)?se(e,!!a.multiple,i,!1):null!=a.defaultValue&&se(e,!!a.multiple,a.defaultValue,!0);break;default:"function"==typeof o.onClick&&(e.onclick=Ba)}$a(n,a)&&(t.flags|=4)}null!==t.ref&&(t.flags|=128)}return null;case 6:if(e&&null!=t.stateNode)Ks(e,t,e.memoizedProps,a);else{if("string"!=typeof a&&null===t.stateNode)throw Error(s(166));n=Oo(No.current),Oo(Ao.current),Vo(t)?(a=t.stateNode,n=t.memoizedProps,a[Qa]=t,a.nodeValue!==n&&(t.flags|=4)):((a=(9===n.nodeType?n:n.ownerDocument).createTextNode(a))[Qa]=t,t.stateNode=a)}return null;case 13:return cr(Do),a=t.memoizedState,0!=(64&t.flags)?(t.lanes=n,t):(a=null!==a,n=!1,null===e?void 0!==t.memoizedProps.fallback&&Vo(t):n=null!==e.memoizedState,a&&!n&&0!=(2&t.mode)&&(null===e&&!0!==t.memoizedProps.unstable_avoidThisFallback||0!=(1&Do.current)?0===Fi&&(Fi=3):(0!==Fi&&3!==Fi||(Fi=4),null===Pi||0==(134217727&zi)&&0==(134217727&$i)||vl(Pi,Ri))),(a||n)&&(t.flags|=4),null);case 4:return Io(),Gs(t),null===e&&Na(t.stateNode.containerInfo),null;case 10:return no(t),null;case 19:if(cr(Do),null===(a=t.memoizedState))return null;if(i=0!=(64&t.flags),null===(c=a.rendering))if(i)si(a,!1);else{if(0!==Fi||null!==e&&0!=(64&e.flags))for(e=t.child;null!==e;){if(null!==(c=Fo(e))){for(t.flags|=64,si(a,!1),null!==(i=c.updateQueue)&&(t.updateQueue=i,t.flags|=4),null===a.lastEffect&&(t.firstEffect=null),t.lastEffect=a.lastEffect,a=n,n=t.child;null!==n;)e=a,(i=n).flags&=2,i.nextEffect=null,i.firstEffect=null,i.lastEffect=null,null===(c=i.alternate)?(i.childLanes=0,i.lanes=e,i.child=null,i.memoizedProps=null,i.memoizedState=null,i.updateQueue=null,i.dependencies=null,i.stateNode=null):(i.childLanes=c.childLanes,i.lanes=c.lanes,i.child=c.child,i.memoizedProps=c.memoizedProps,i.memoizedState=c.memoizedState,i.updateQueue=c.updateQueue,i.type=c.type,e=c.dependencies,i.dependencies=null===e?null:{lanes:e.lanes,firstContext:e.firstContext}),n=n.sibling;return ur(Do,1&Do.current|2),t.child}e=e.sibling}null!==a.tail&&$r()>Vi&&(t.flags|=64,i=!0,si(a,!1),t.lanes=33554432)}else{if(!i)if(null!==(e=Fo(c))){if(t.flags|=64,i=!0,null!==(n=e.updateQueue)&&(t.updateQueue=n,t.flags|=4),si(a,!0),null===a.tail&&"hidden"===a.tailMode&&!c.alternate&&!zo)return null!==(t=t.lastEffect=a.lastEffect)&&(t.nextEffect=null),null}else 2*$r()-a.renderingStartTime>Vi&&1073741824!==n&&(t.flags|=64,i=!0,si(a,!1),t.lanes=33554432);a.isBackwards?(c.sibling=t.child,t.child=c):(null!==(n=a.last)?n.sibling=c:t.child=c,a.last=c)}return null!==a.tail?(n=a.tail,a.rendering=n,a.tail=n.sibling,a.lastEffect=t.lastEffect,a.renderingStartTime=$r(),n.sibling=null,t=Do.current,ur(Do,i?1&t|2:1&t),n):null;case 23:case 24:return El(),null!==e&&null!==e.memoizedState!=(null!==t.memoizedState)&&"unstable-defer-without-hiding"!==a.mode&&(t.flags|=4),null}throw Error(s(156,t.tag))}function li(e){switch(e.tag){case 1:hr(e.type)&&br();var t=e.flags;return 4096&t?(e.flags=-4097&t|64,e):null;case 3:if(Io(),cr(pr),cr(fr),Yo(),0!=(64&(t=e.flags)))throw Error(s(285));return e.flags=-4097&t|64,e;case 5:return Mo(e),null;case 13:return cr(Do),4096&(t=e.flags)?(e.flags=-4097&t|64,e):null;case 19:return cr(Do),null;case 4:return Io(),null;case 10:return no(e),null;case 23:case 24:return El(),null;default:return null}}function ci(e,t){try{var n="",a=t;do{n+=V(a),a=a.return}while(a);var r=n}catch(o){r="\nError generating stack: "+o.message+"\n"+o.stack}return{value:e,source:t,stack:r}}function ui(e,t){try{console.error(t.value)}catch(n){setTimeout((function(){throw n}))}}Ws=function(e,t){for(var n=t.child;null!==n;){if(5===n.tag||6===n.tag)e.appendChild(n.stateNode);else if(4!==n.tag&&null!==n.child){n.child.return=n,n=n.child;continue}if(n===t)break;for(;null===n.sibling;){if(null===n.return||n.return===t)return;n=n.return}n.sibling.return=n.return,n=n.sibling}},Gs=function(){},Ys=function(e,t,n,a){var o=e.memoizedProps;if(o!==a){e=t.stateNode,Oo(Ao.current);var s,i=null;switch(n){case"input":o=J(e,o),a=J(e,a),i=[];break;case"option":o=oe(e,o),a=oe(e,a),i=[];break;case"select":o=r({},o,{value:void 0}),a=r({},a,{value:void 0}),i=[];break;case"textarea":o=ie(e,o),a=ie(e,a),i=[];break;default:"function"!=typeof o.onClick&&"function"==typeof a.onClick&&(e.onclick=Ba)}for(d in Ee(n,a),n=null,o)if(!a.hasOwnProperty(d)&&o.hasOwnProperty(d)&&null!=o[d])if("style"===d){var c=o[d];for(s in c)c.hasOwnProperty(s)&&(n||(n={}),n[s]="")}else"dangerouslySetInnerHTML"!==d&&"children"!==d&&"suppressContentEditableWarning"!==d&&"suppressHydrationWarning"!==d&&"autoFocus"!==d&&(l.hasOwnProperty(d)?i||(i=[]):(i=i||[]).push(d,null));for(d in a){var u=a[d];if(c=null!=o?o[d]:void 0,a.hasOwnProperty(d)&&u!==c&&(null!=u||null!=c))if("style"===d)if(c){for(s in c)!c.hasOwnProperty(s)||u&&u.hasOwnProperty(s)||(n||(n={}),n[s]="");for(s in u)u.hasOwnProperty(s)&&c[s]!==u[s]&&(n||(n={}),n[s]=u[s])}else n||(i||(i=[]),i.push(d,n)),n=u;else"dangerouslySetInnerHTML"===d?(u=u?u.__html:void 0,c=c?c.__html:void 0,null!=u&&c!==u&&(i=i||[]).push(d,u)):"children"===d?"string"!=typeof u&&"number"!=typeof u||(i=i||[]).push(d,""+u):"suppressContentEditableWarning"!==d&&"suppressHydrationWarning"!==d&&(l.hasOwnProperty(d)?(null!=u&&"onScroll"===d&&Aa("scroll",e),i||c===u||(i=[])):"object"==typeof u&&null!==u&&u.$$typeof===R?u.toString():(i=i||[]).push(d,u))}n&&(i=i||[]).push("style",n);var d=i;(t.updateQueue=d)&&(t.flags|=4)}},Ks=function(e,t,n,a){n!==a&&(t.flags|=4)};var di="function"==typeof WeakMap?WeakMap:Map;function fi(e,t,n){(n=co(-1,n)).tag=3,n.payload={element:null};var a=t.value;return n.callback=function(){Ki||(Ki=!0,Qi=a),ui(0,t)},n}function pi(e,t,n){(n=co(-1,n)).tag=3;var a=e.type.getDerivedStateFromError;if("function"==typeof a){var r=t.value;n.payload=function(){return ui(0,t),a(r)}}var o=e.stateNode;return null!==o&&"function"==typeof o.componentDidCatch&&(n.callback=function(){"function"!=typeof a&&(null===Xi?Xi=new Set([this]):Xi.add(this),ui(0,t));var e=t.stack;this.componentDidCatch(t.value,{componentStack:null!==e?e:""})}),n}var mi="function"==typeof WeakSet?WeakSet:Set;function gi(e){var t=e.ref;if(null!==t)if("function"==typeof t)try{t(null)}catch(n){jl(e,n)}else t.current=null}function hi(e,t){switch(t.tag){case 0:case 11:case 15:case 22:case 5:case 6:case 4:case 17:return;case 1:if(256&t.flags&&null!==e){var n=e.memoizedProps,a=e.memoizedState;t=(e=t.stateNode).getSnapshotBeforeUpdate(t.elementType===t.type?n:Kr(t.type,n),a),e.__reactInternalSnapshotBeforeUpdate=t}return;case 3:return void(256&t.flags&&Va(t.stateNode.containerInfo))}throw Error(s(163))}function bi(e,t,n){switch(n.tag){case 0:case 11:case 15:case 22:if(null!==(t=null!==(t=n.updateQueue)?t.lastEffect:null)){e=t=t.next;do{if(3==(3&e.tag)){var a=e.create;e.destroy=a()}e=e.next}while(e!==t)}if(null!==(t=null!==(t=n.updateQueue)?t.lastEffect:null)){e=t=t.next;do{var r=e;a=r.next,0!=(4&(r=r.tag))&&0!=(1&r)&&(Dl(n,e),Ml(n,e)),e=a}while(e!==t)}return;case 1:return e=n.stateNode,4&n.flags&&(null===t?e.componentDidMount():(a=n.elementType===n.type?t.memoizedProps:Kr(n.type,t.memoizedProps),e.componentDidUpdate(a,t.memoizedState,e.__reactInternalSnapshotBeforeUpdate))),void(null!==(t=n.updateQueue)&&mo(n,t,e));case 3:if(null!==(t=n.updateQueue)){if(e=null,null!==n.child)switch(n.child.tag){case 5:case 1:e=n.child.stateNode}mo(n,t,e)}return;case 5:return e=n.stateNode,void(null===t&&4&n.flags&&$a(n.type,n.memoizedProps)&&e.focus());case 6:case 4:case 12:case 19:case 17:case 20:case 21:case 23:case 24:return;case 13:return void(null===n.memoizedState&&(n=n.alternate,null!==n&&(n=n.memoizedState,null!==n&&(n=n.dehydrated,null!==n&&wt(n)))))}throw Error(s(163))}function vi(e,t){for(var n=e;;){if(5===n.tag){var a=n.stateNode;if(t)"function"==typeof(a=a.style).setProperty?a.setProperty("display","none","important"):a.display="none";else{a=n.stateNode;var r=n.memoizedProps.style;r=null!=r&&r.hasOwnProperty("display")?r.display:null,a.style.display=xe("display",r)}}else if(6===n.tag)n.stateNode.nodeValue=t?"":n.memoizedProps;else if((23!==n.tag&&24!==n.tag||null===n.memoizedState||n===e)&&null!==n.child){n.child.return=n,n=n.child;continue}if(n===e)break;for(;null===n.sibling;){if(null===n.return||n.return===e)return;n=n.return}n.sibling.return=n.return,n=n.sibling}}function yi(e,t){if(Er&&"function"==typeof Er.onCommitFiberUnmount)try{Er.onCommitFiberUnmount(Sr,t)}catch(o){}switch(t.tag){case 0:case 11:case 14:case 15:case 22:if(null!==(e=t.updateQueue)&&null!==(e=e.lastEffect)){var n=e=e.next;do{var a=n,r=a.destroy;if(a=a.tag,void 0!==r)if(0!=(4&a))Dl(t,n);else{a=t;try{r()}catch(o){jl(a,o)}}n=n.next}while(n!==e)}break;case 1:if(gi(t),"function"==typeof(e=t.stateNode).componentWillUnmount)try{e.props=t.memoizedProps,e.state=t.memoizedState,e.componentWillUnmount()}catch(o){jl(t,o)}break;case 5:gi(t);break;case 4:_i(e,t)}}function xi(e){e.alternate=null,e.child=null,e.dependencies=null,e.firstEffect=null,e.lastEffect=null,e.memoizedProps=null,e.memoizedState=null,e.pendingProps=null,e.return=null,e.updateQueue=null}function wi(e){return 5===e.tag||3===e.tag||4===e.tag}function Si(e){e:{for(var t=e.return;null!==t;){if(wi(t))break e;t=t.return}throw Error(s(160))}var n=t;switch(t=n.stateNode,n.tag){case 5:var a=!1;break;case 3:case 4:t=t.containerInfo,a=!0;break;default:throw Error(s(161))}16&n.flags&&(be(t,""),n.flags&=-17);e:t:for(n=e;;){for(;null===n.sibling;){if(null===n.return||wi(n.return)){n=null;break e}n=n.return}for(n.sibling.return=n.return,n=n.sibling;5!==n.tag&&6!==n.tag&&18!==n.tag;){if(2&n.flags)continue t;if(null===n.child||4===n.tag)continue t;n.child.return=n,n=n.child}if(!(2&n.flags)){n=n.stateNode;break e}}a?Ei(e,n,t):ki(e,n,t)}function Ei(e,t,n){var a=e.tag,r=5===a||6===a;if(r)e=r?e.stateNode:e.stateNode.instance,t?8===n.nodeType?n.parentNode.insertBefore(e,t):n.insertBefore(e,t):(8===n.nodeType?(t=n.parentNode).insertBefore(e,n):(t=n).appendChild(e),null!=(n=n._reactRootContainer)||null!==t.onclick||(t.onclick=Ba));else if(4!==a&&null!==(e=e.child))for(Ei(e,t,n),e=e.sibling;null!==e;)Ei(e,t,n),e=e.sibling}function ki(e,t,n){var a=e.tag,r=5===a||6===a;if(r)e=r?e.stateNode:e.stateNode.instance,t?n.insertBefore(e,t):n.appendChild(e);else if(4!==a&&null!==(e=e.child))for(ki(e,t,n),e=e.sibling;null!==e;)ki(e,t,n),e=e.sibling}function _i(e,t){for(var n,a,r=t,o=!1;;){if(!o){o=r.return;e:for(;;){if(null===o)throw Error(s(160));switch(n=o.stateNode,o.tag){case 5:a=!1;break e;case 3:case 4:n=n.containerInfo,a=!0;break e}o=o.return}o=!0}if(5===r.tag||6===r.tag){e:for(var i=e,l=r,c=l;;)if(yi(i,c),null!==c.child&&4!==c.tag)c.child.return=c,c=c.child;else{if(c===l)break e;for(;null===c.sibling;){if(null===c.return||c.return===l)break e;c=c.return}c.sibling.return=c.return,c=c.sibling}a?(i=n,l=r.stateNode,8===i.nodeType?i.parentNode.removeChild(l):i.removeChild(l)):n.removeChild(r.stateNode)}else if(4===r.tag){if(null!==r.child){n=r.stateNode.containerInfo,a=!0,r.child.return=r,r=r.child;continue}}else if(yi(e,r),null!==r.child){r.child.return=r,r=r.child;continue}if(r===t)break;for(;null===r.sibling;){if(null===r.return||r.return===t)return;4===(r=r.return).tag&&(o=!1)}r.sibling.return=r.return,r=r.sibling}}function Ci(e,t){switch(t.tag){case 0:case 11:case 14:case 15:case 22:var n=t.updateQueue;if(null!==(n=null!==n?n.lastEffect:null)){var a=n=n.next;do{3==(3&a.tag)&&(e=a.destroy,a.destroy=void 0,void 0!==e&&e()),a=a.next}while(a!==n)}return;case 1:case 12:case 17:return;case 5:if(null!=(n=t.stateNode)){a=t.memoizedProps;var r=null!==e?e.memoizedProps:a;e=t.type;var o=t.updateQueue;if(t.updateQueue=null,null!==o){for(n[Xa]=a,"input"===e&&"radio"===a.type&&null!=a.name&&te(n,a),ke(e,r),t=ke(e,a),r=0;r<o.length;r+=2){var i=o[r],l=o[r+1];"style"===i?we(n,l):"dangerouslySetInnerHTML"===i?he(n,l):"children"===i?be(n,l):x(n,i,l,t)}switch(e){case"input":ne(n,a);break;case"textarea":ce(n,a);break;case"select":e=n._wrapperState.wasMultiple,n._wrapperState.wasMultiple=!!a.multiple,null!=(o=a.value)?se(n,!!a.multiple,o,!1):e!==!!a.multiple&&(null!=a.defaultValue?se(n,!!a.multiple,a.defaultValue,!0):se(n,!!a.multiple,a.multiple?[]:"",!1))}}}return;case 6:if(null===t.stateNode)throw Error(s(162));return void(t.stateNode.nodeValue=t.memoizedProps);case 3:return void((n=t.stateNode).hydrate&&(n.hydrate=!1,wt(n.containerInfo)));case 13:return null!==t.memoizedState&&(Hi=$r(),vi(t.child,!0)),void qi(t);case 19:return void qi(t);case 23:case 24:return void vi(t,null!==t.memoizedState)}throw Error(s(163))}function qi(e){var t=e.updateQueue;if(null!==t){e.updateQueue=null;var n=e.stateNode;null===n&&(n=e.stateNode=new mi),t.forEach((function(t){var a=$l.bind(null,e,t);n.has(t)||(n.add(t),t.then(a,a))}))}}function Ti(e,t){return null!==e&&(null===(e=e.memoizedState)||null!==e.dehydrated)&&(null!==(t=t.memoizedState)&&null===t.dehydrated)}var Ai=Math.ceil,Li=w.ReactCurrentDispatcher,Ni=w.ReactCurrentOwner,Oi=0,Pi=null,Ii=null,Ri=0,Mi=0,Di=lr(0),Fi=0,Bi=null,ji=0,zi=0,$i=0,Ui=0,Zi=null,Hi=0,Vi=1/0;function Wi(){Vi=$r()+500}var Gi,Yi=null,Ki=!1,Qi=null,Xi=null,Ji=!1,el=null,tl=90,nl=[],al=[],rl=null,ol=0,sl=null,il=-1,ll=0,cl=0,ul=null,dl=!1;function fl(){return 0!=(48&Oi)?$r():-1!==il?il:il=$r()}function pl(e){if(0==(2&(e=e.mode)))return 1;if(0==(4&e))return 99===Ur()?1:2;if(0===ll&&(ll=ji),0!==Yr.transition){0!==cl&&(cl=null!==Zi?Zi.pendingLanes:0),e=ll;var t=4186112&~cl;return 0===(t&=-t)&&(0===(t=(e=4186112&~e)&-e)&&(t=8192)),t}return e=Ur(),0!=(4&Oi)&&98===e?e=Bt(12,ll):e=Bt(e=function(e){switch(e){case 99:return 15;case 98:return 10;case 97:case 96:return 8;case 95:return 2;default:return 0}}(e),ll),e}function ml(e,t,n){if(50<ol)throw ol=0,sl=null,Error(s(185));if(null===(e=gl(e,t)))return null;$t(e,t,n),e===Pi&&($i|=t,4===Fi&&vl(e,Ri));var a=Ur();1===t?0!=(8&Oi)&&0==(48&Oi)?yl(e):(hl(e,n),0===Oi&&(Wi(),Wr())):(0==(4&Oi)||98!==a&&99!==a||(null===rl?rl=new Set([e]):rl.add(e)),hl(e,n)),Zi=e}function gl(e,t){e.lanes|=t;var n=e.alternate;for(null!==n&&(n.lanes|=t),n=e,e=e.return;null!==e;)e.childLanes|=t,null!==(n=e.alternate)&&(n.childLanes|=t),n=e,e=e.return;return 3===n.tag?n.stateNode:null}function hl(e,t){for(var n=e.callbackNode,a=e.suspendedLanes,r=e.pingedLanes,o=e.expirationTimes,i=e.pendingLanes;0<i;){var l=31-Ut(i),c=1<<l,u=o[l];if(-1===u){if(0==(c&a)||0!=(c&r)){u=t,Mt(c);var d=Rt;o[l]=10<=d?u+250:6<=d?u+5e3:-1}}else u<=t&&(e.expiredLanes|=c);i&=~c}if(a=Dt(e,e===Pi?Ri:0),t=Rt,0===a)null!==n&&(n!==Mr&&Cr(n),e.callbackNode=null,e.callbackPriority=0);else{if(null!==n){if(e.callbackPriority===t)return;n!==Mr&&Cr(n)}15===t?(n=yl.bind(null,e),null===Fr?(Fr=[n],Br=_r(Nr,Gr)):Fr.push(n),n=Mr):14===t?n=Vr(99,yl.bind(null,e)):(n=function(e){switch(e){case 15:case 14:return 99;case 13:case 12:case 11:case 10:return 98;case 9:case 8:case 7:case 6:case 4:case 5:return 97;case 3:case 2:case 1:return 95;case 0:return 90;default:throw Error(s(358,e))}}(t),n=Vr(n,bl.bind(null,e))),e.callbackPriority=t,e.callbackNode=n}}function bl(e){if(il=-1,cl=ll=0,0!=(48&Oi))throw Error(s(327));var t=e.callbackNode;if(Rl()&&e.callbackNode!==t)return null;var n=Dt(e,e===Pi?Ri:0);if(0===n)return null;var a=n,r=Oi;Oi|=16;var o=Cl();for(Pi===e&&Ri===a||(Wi(),kl(e,a));;)try{Al();break}catch(l){_l(e,l)}if(to(),Li.current=o,Oi=r,null!==Ii?a=0:(Pi=null,Ri=0,a=Fi),0!=(ji&$i))kl(e,0);else if(0!==a){if(2===a&&(Oi|=64,e.hydrate&&(e.hydrate=!1,Va(e.containerInfo)),0!==(n=Ft(e))&&(a=ql(e,n))),1===a)throw t=Bi,kl(e,0),vl(e,n),hl(e,$r()),t;switch(e.finishedWork=e.current.alternate,e.finishedLanes=n,a){case 0:case 1:throw Error(s(345));case 2:case 5:Ol(e);break;case 3:if(vl(e,n),(62914560&n)===n&&10<(a=Hi+500-$r())){if(0!==Dt(e,0))break;if(((r=e.suspendedLanes)&n)!==n){fl(),e.pingedLanes|=e.suspendedLanes&r;break}e.timeoutHandle=Za(Ol.bind(null,e),a);break}Ol(e);break;case 4:if(vl(e,n),(4186112&n)===n)break;for(a=e.eventTimes,r=-1;0<n;){var i=31-Ut(n);o=1<<i,(i=a[i])>r&&(r=i),n&=~o}if(n=r,10<(n=(120>(n=$r()-n)?120:480>n?480:1080>n?1080:1920>n?1920:3e3>n?3e3:4320>n?4320:1960*Ai(n/1960))-n)){e.timeoutHandle=Za(Ol.bind(null,e),n);break}Ol(e);break;default:throw Error(s(329))}}return hl(e,$r()),e.callbackNode===t?bl.bind(null,e):null}function vl(e,t){for(t&=~Ui,t&=~$i,e.suspendedLanes|=t,e.pingedLanes&=~t,e=e.expirationTimes;0<t;){var n=31-Ut(t),a=1<<n;e[n]=-1,t&=~a}}function yl(e){if(0!=(48&Oi))throw Error(s(327));if(Rl(),e===Pi&&0!=(e.expiredLanes&Ri)){var t=Ri,n=ql(e,t);0!=(ji&$i)&&(n=ql(e,t=Dt(e,t)))}else n=ql(e,t=Dt(e,0));if(0!==e.tag&&2===n&&(Oi|=64,e.hydrate&&(e.hydrate=!1,Va(e.containerInfo)),0!==(t=Ft(e))&&(n=ql(e,t))),1===n)throw n=Bi,kl(e,0),vl(e,t),hl(e,$r()),n;return e.finishedWork=e.current.alternate,e.finishedLanes=t,Ol(e),hl(e,$r()),null}function xl(e,t){var n=Oi;Oi|=1;try{return e(t)}finally{0===(Oi=n)&&(Wi(),Wr())}}function wl(e,t){var n=Oi;Oi&=-2,Oi|=8;try{return e(t)}finally{0===(Oi=n)&&(Wi(),Wr())}}function Sl(e,t){ur(Di,Mi),Mi|=t,ji|=t}function El(){Mi=Di.current,cr(Di)}function kl(e,t){e.finishedWork=null,e.finishedLanes=0;var n=e.timeoutHandle;if(-1!==n&&(e.timeoutHandle=-1,Ha(n)),null!==Ii)for(n=Ii.return;null!==n;){var a=n;switch(a.tag){case 1:null!=(a=a.type.childContextTypes)&&br();break;case 3:Io(),cr(pr),cr(fr),Yo();break;case 5:Mo(a);break;case 4:Io();break;case 13:case 19:cr(Do);break;case 10:no(a);break;case 23:case 24:El()}n=n.return}Pi=e,Ii=Vl(e.current,null),Ri=Mi=ji=t,Fi=0,Bi=null,Ui=$i=zi=0}function _l(e,t){for(;;){var n=Ii;try{if(to(),Ko.current=Ns,ns){for(var a=Jo.memoizedState;null!==a;){var r=a.queue;null!==r&&(r.pending=null),a=a.next}ns=!1}if(Xo=0,ts=es=Jo=null,as=!1,Ni.current=null,null===n||null===n.return){Fi=1,Bi=t,Ii=null;break}e:{var o=e,s=n.return,i=n,l=t;if(t=Ri,i.flags|=2048,i.firstEffect=i.lastEffect=null,null!==l&&"object"==typeof l&&"function"==typeof l.then){var c=l;if(0==(2&i.mode)){var u=i.alternate;u?(i.updateQueue=u.updateQueue,i.memoizedState=u.memoizedState,i.lanes=u.lanes):(i.updateQueue=null,i.memoizedState=null)}var d=0!=(1&Do.current),f=s;do{var p;if(p=13===f.tag){var m=f.memoizedState;if(null!==m)p=null!==m.dehydrated;else{var g=f.memoizedProps;p=void 0!==g.fallback&&(!0!==g.unstable_avoidThisFallback||!d)}}if(p){var h=f.updateQueue;if(null===h){var b=new Set;b.add(c),f.updateQueue=b}else h.add(c);if(0==(2&f.mode)){if(f.flags|=64,i.flags|=16384,i.flags&=-2981,1===i.tag)if(null===i.alternate)i.tag=17;else{var v=co(-1,1);v.tag=2,uo(i,v)}i.lanes|=1;break e}l=void 0,i=t;var y=o.pingCache;if(null===y?(y=o.pingCache=new di,l=new Set,y.set(c,l)):void 0===(l=y.get(c))&&(l=new Set,y.set(c,l)),!l.has(i)){l.add(i);var x=zl.bind(null,o,c,i);c.then(x,x)}f.flags|=4096,f.lanes=t;break e}f=f.return}while(null!==f);l=Error((W(i.type)||"A React component")+" suspended while rendering, but no fallback UI was specified.\n\nAdd a <Suspense fallback=...> component higher in the tree to provide a loading indicator or placeholder to display.")}5!==Fi&&(Fi=2),l=ci(l,i),f=s;do{switch(f.tag){case 3:o=l,f.flags|=4096,t&=-t,f.lanes|=t,fo(f,fi(0,o,t));break e;case 1:o=l;var w=f.type,S=f.stateNode;if(0==(64&f.flags)&&("function"==typeof w.getDerivedStateFromError||null!==S&&"function"==typeof S.componentDidCatch&&(null===Xi||!Xi.has(S)))){f.flags|=4096,t&=-t,f.lanes|=t,fo(f,pi(f,o,t));break e}}f=f.return}while(null!==f)}Nl(n)}catch(E){t=E,Ii===n&&null!==n&&(Ii=n=n.return);continue}break}}function Cl(){var e=Li.current;return Li.current=Ns,null===e?Ns:e}function ql(e,t){var n=Oi;Oi|=16;var a=Cl();for(Pi===e&&Ri===t||kl(e,t);;)try{Tl();break}catch(r){_l(e,r)}if(to(),Oi=n,Li.current=a,null!==Ii)throw Error(s(261));return Pi=null,Ri=0,Fi}function Tl(){for(;null!==Ii;)Ll(Ii)}function Al(){for(;null!==Ii&&!qr();)Ll(Ii)}function Ll(e){var t=Gi(e.alternate,e,Mi);e.memoizedProps=e.pendingProps,null===t?Nl(e):Ii=t,Ni.current=null}function Nl(e){var t=e;do{var n=t.alternate;if(e=t.return,0==(2048&t.flags)){if(null!==(n=ii(n,t,Mi)))return void(Ii=n);if(24!==(n=t).tag&&23!==n.tag||null===n.memoizedState||0!=(1073741824&Mi)||0==(4&n.mode)){for(var a=0,r=n.child;null!==r;)a|=r.lanes|r.childLanes,r=r.sibling;n.childLanes=a}null!==e&&0==(2048&e.flags)&&(null===e.firstEffect&&(e.firstEffect=t.firstEffect),null!==t.lastEffect&&(null!==e.lastEffect&&(e.lastEffect.nextEffect=t.firstEffect),e.lastEffect=t.lastEffect),1<t.flags&&(null!==e.lastEffect?e.lastEffect.nextEffect=t:e.firstEffect=t,e.lastEffect=t))}else{if(null!==(n=li(t)))return n.flags&=2047,void(Ii=n);null!==e&&(e.firstEffect=e.lastEffect=null,e.flags|=2048)}if(null!==(t=t.sibling))return void(Ii=t);Ii=t=e}while(null!==t);0===Fi&&(Fi=5)}function Ol(e){var t=Ur();return Hr(99,Pl.bind(null,e,t)),null}function Pl(e,t){do{Rl()}while(null!==el);if(0!=(48&Oi))throw Error(s(327));var n=e.finishedWork;if(null===n)return null;if(e.finishedWork=null,e.finishedLanes=0,n===e.current)throw Error(s(177));e.callbackNode=null;var a=n.lanes|n.childLanes,r=a,o=e.pendingLanes&~r;e.pendingLanes=r,e.suspendedLanes=0,e.pingedLanes=0,e.expiredLanes&=r,e.mutableReadLanes&=r,e.entangledLanes&=r,r=e.entanglements;for(var i=e.eventTimes,l=e.expirationTimes;0<o;){var c=31-Ut(o),u=1<<c;r[c]=0,i[c]=-1,l[c]=-1,o&=~u}if(null!==rl&&0==(24&a)&&rl.has(e)&&rl.delete(e),e===Pi&&(Ii=Pi=null,Ri=0),1<n.flags?null!==n.lastEffect?(n.lastEffect.nextEffect=n,a=n.firstEffect):a=n:a=n.firstEffect,null!==a){if(r=Oi,Oi|=32,Ni.current=null,ja=Gt,ha(i=ga())){if("selectionStart"in i)l={start:i.selectionStart,end:i.selectionEnd};else e:if(l=(l=i.ownerDocument)&&l.defaultView||window,(u=l.getSelection&&l.getSelection())&&0!==u.rangeCount){l=u.anchorNode,o=u.anchorOffset,c=u.focusNode,u=u.focusOffset;try{l.nodeType,c.nodeType}catch(C){l=null;break e}var d=0,f=-1,p=-1,m=0,g=0,h=i,b=null;t:for(;;){for(var v;h!==l||0!==o&&3!==h.nodeType||(f=d+o),h!==c||0!==u&&3!==h.nodeType||(p=d+u),3===h.nodeType&&(d+=h.nodeValue.length),null!==(v=h.firstChild);)b=h,h=v;for(;;){if(h===i)break t;if(b===l&&++m===o&&(f=d),b===c&&++g===u&&(p=d),null!==(v=h.nextSibling))break;b=(h=b).parentNode}h=v}l=-1===f||-1===p?null:{start:f,end:p}}else l=null;l=l||{start:0,end:0}}else l=null;za={focusedElem:i,selectionRange:l},Gt=!1,ul=null,dl=!1,Yi=a;do{try{Il()}catch(C){if(null===Yi)throw Error(s(330));jl(Yi,C),Yi=Yi.nextEffect}}while(null!==Yi);ul=null,Yi=a;do{try{for(i=e;null!==Yi;){var y=Yi.flags;if(16&y&&be(Yi.stateNode,""),128&y){var x=Yi.alternate;if(null!==x){var w=x.ref;null!==w&&("function"==typeof w?w(null):w.current=null)}}switch(1038&y){case 2:Si(Yi),Yi.flags&=-3;break;case 6:Si(Yi),Yi.flags&=-3,Ci(Yi.alternate,Yi);break;case 1024:Yi.flags&=-1025;break;case 1028:Yi.flags&=-1025,Ci(Yi.alternate,Yi);break;case 4:Ci(Yi.alternate,Yi);break;case 8:_i(i,l=Yi);var S=l.alternate;xi(l),null!==S&&xi(S)}Yi=Yi.nextEffect}}catch(C){if(null===Yi)throw Error(s(330));jl(Yi,C),Yi=Yi.nextEffect}}while(null!==Yi);if(w=za,x=ga(),y=w.focusedElem,i=w.selectionRange,x!==y&&y&&y.ownerDocument&&ma(y.ownerDocument.documentElement,y)){null!==i&&ha(y)&&(x=i.start,void 0===(w=i.end)&&(w=x),"selectionStart"in y?(y.selectionStart=x,y.selectionEnd=Math.min(w,y.value.length)):(w=(x=y.ownerDocument||document)&&x.defaultView||window).getSelection&&(w=w.getSelection(),l=y.textContent.length,S=Math.min(i.start,l),i=void 0===i.end?S:Math.min(i.end,l),!w.extend&&S>i&&(l=i,i=S,S=l),l=pa(y,S),o=pa(y,i),l&&o&&(1!==w.rangeCount||w.anchorNode!==l.node||w.anchorOffset!==l.offset||w.focusNode!==o.node||w.focusOffset!==o.offset)&&((x=x.createRange()).setStart(l.node,l.offset),w.removeAllRanges(),S>i?(w.addRange(x),w.extend(o.node,o.offset)):(x.setEnd(o.node,o.offset),w.addRange(x))))),x=[];for(w=y;w=w.parentNode;)1===w.nodeType&&x.push({element:w,left:w.scrollLeft,top:w.scrollTop});for("function"==typeof y.focus&&y.focus(),y=0;y<x.length;y++)(w=x[y]).element.scrollLeft=w.left,w.element.scrollTop=w.top}Gt=!!ja,za=ja=null,e.current=n,Yi=a;do{try{for(y=e;null!==Yi;){var E=Yi.flags;if(36&E&&bi(y,Yi.alternate,Yi),128&E){x=void 0;var k=Yi.ref;if(null!==k){var _=Yi.stateNode;Yi.tag,x=_,"function"==typeof k?k(x):k.current=x}}Yi=Yi.nextEffect}}catch(C){if(null===Yi)throw Error(s(330));jl(Yi,C),Yi=Yi.nextEffect}}while(null!==Yi);Yi=null,Dr(),Oi=r}else e.current=n;if(Ji)Ji=!1,el=e,tl=t;else for(Yi=a;null!==Yi;)t=Yi.nextEffect,Yi.nextEffect=null,8&Yi.flags&&((E=Yi).sibling=null,E.stateNode=null),Yi=t;if(0===(a=e.pendingLanes)&&(Xi=null),1===a?e===sl?ol++:(ol=0,sl=e):ol=0,n=n.stateNode,Er&&"function"==typeof Er.onCommitFiberRoot)try{Er.onCommitFiberRoot(Sr,n,void 0,64==(64&n.current.flags))}catch(C){}if(hl(e,$r()),Ki)throw Ki=!1,e=Qi,Qi=null,e;return 0!=(8&Oi)||Wr(),null}function Il(){for(;null!==Yi;){var e=Yi.alternate;dl||null===ul||(0!=(8&Yi.flags)?Je(Yi,ul)&&(dl=!0):13===Yi.tag&&Ti(e,Yi)&&Je(Yi,ul)&&(dl=!0));var t=Yi.flags;0!=(256&t)&&hi(e,Yi),0==(512&t)||Ji||(Ji=!0,Vr(97,(function(){return Rl(),null}))),Yi=Yi.nextEffect}}function Rl(){if(90!==tl){var e=97<tl?97:tl;return tl=90,Hr(e,Fl)}return!1}function Ml(e,t){nl.push(t,e),Ji||(Ji=!0,Vr(97,(function(){return Rl(),null})))}function Dl(e,t){al.push(t,e),Ji||(Ji=!0,Vr(97,(function(){return Rl(),null})))}function Fl(){if(null===el)return!1;var e=el;if(el=null,0!=(48&Oi))throw Error(s(331));var t=Oi;Oi|=32;var n=al;al=[];for(var a=0;a<n.length;a+=2){var r=n[a],o=n[a+1],i=r.destroy;if(r.destroy=void 0,"function"==typeof i)try{i()}catch(c){if(null===o)throw Error(s(330));jl(o,c)}}for(n=nl,nl=[],a=0;a<n.length;a+=2){r=n[a],o=n[a+1];try{var l=r.create;r.destroy=l()}catch(c){if(null===o)throw Error(s(330));jl(o,c)}}for(l=e.current.firstEffect;null!==l;)e=l.nextEffect,l.nextEffect=null,8&l.flags&&(l.sibling=null,l.stateNode=null),l=e;return Oi=t,Wr(),!0}function Bl(e,t,n){uo(e,t=fi(0,t=ci(n,t),1)),t=fl(),null!==(e=gl(e,1))&&($t(e,1,t),hl(e,t))}function jl(e,t){if(3===e.tag)Bl(e,e,t);else for(var n=e.return;null!==n;){if(3===n.tag){Bl(n,e,t);break}if(1===n.tag){var a=n.stateNode;if("function"==typeof n.type.getDerivedStateFromError||"function"==typeof a.componentDidCatch&&(null===Xi||!Xi.has(a))){var r=pi(n,e=ci(t,e),1);if(uo(n,r),r=fl(),null!==(n=gl(n,1)))$t(n,1,r),hl(n,r);else if("function"==typeof a.componentDidCatch&&(null===Xi||!Xi.has(a)))try{a.componentDidCatch(t,e)}catch(o){}break}}n=n.return}}function zl(e,t,n){var a=e.pingCache;null!==a&&a.delete(t),t=fl(),e.pingedLanes|=e.suspendedLanes&n,Pi===e&&(Ri&n)===n&&(4===Fi||3===Fi&&(62914560&Ri)===Ri&&500>$r()-Hi?kl(e,0):Ui|=n),hl(e,t)}function $l(e,t){var n=e.stateNode;null!==n&&n.delete(t),0===(t=0)&&(0==(2&(t=e.mode))?t=1:0==(4&t)?t=99===Ur()?1:2:(0===ll&&(ll=ji),0===(t=jt(62914560&~ll))&&(t=4194304))),n=fl(),null!==(e=gl(e,t))&&($t(e,t,n),hl(e,n))}function Ul(e,t,n,a){this.tag=e,this.key=n,this.sibling=this.child=this.return=this.stateNode=this.type=this.elementType=null,this.index=0,this.ref=null,this.pendingProps=t,this.dependencies=this.memoizedState=this.updateQueue=this.memoizedProps=null,this.mode=a,this.flags=0,this.lastEffect=this.firstEffect=this.nextEffect=null,this.childLanes=this.lanes=0,this.alternate=null}function Zl(e,t,n,a){return new Ul(e,t,n,a)}function Hl(e){return!(!(e=e.prototype)||!e.isReactComponent)}function Vl(e,t){var n=e.alternate;return null===n?((n=Zl(e.tag,t,e.key,e.mode)).elementType=e.elementType,n.type=e.type,n.stateNode=e.stateNode,n.alternate=e,e.alternate=n):(n.pendingProps=t,n.type=e.type,n.flags=0,n.nextEffect=null,n.firstEffect=null,n.lastEffect=null),n.childLanes=e.childLanes,n.lanes=e.lanes,n.child=e.child,n.memoizedProps=e.memoizedProps,n.memoizedState=e.memoizedState,n.updateQueue=e.updateQueue,t=e.dependencies,n.dependencies=null===t?null:{lanes:t.lanes,firstContext:t.firstContext},n.sibling=e.sibling,n.index=e.index,n.ref=e.ref,n}function Wl(e,t,n,a,r,o){var i=2;if(a=e,"function"==typeof e)Hl(e)&&(i=1);else if("string"==typeof e)i=5;else e:switch(e){case k:return Gl(n.children,r,o,t);case M:i=8,r|=16;break;case _:i=8,r|=1;break;case C:return(e=Zl(12,n,t,8|r)).elementType=C,e.type=C,e.lanes=o,e;case L:return(e=Zl(13,n,t,r)).type=L,e.elementType=L,e.lanes=o,e;case N:return(e=Zl(19,n,t,r)).elementType=N,e.lanes=o,e;case D:return Yl(n,r,o,t);case F:return(e=Zl(24,n,t,r)).elementType=F,e.lanes=o,e;default:if("object"==typeof e&&null!==e)switch(e.$$typeof){case q:i=10;break e;case T:i=9;break e;case A:i=11;break e;case O:i=14;break e;case P:i=16,a=null;break e;case I:i=22;break e}throw Error(s(130,null==e?e:typeof e,""))}return(t=Zl(i,n,t,r)).elementType=e,t.type=a,t.lanes=o,t}function Gl(e,t,n,a){return(e=Zl(7,e,a,t)).lanes=n,e}function Yl(e,t,n,a){return(e=Zl(23,e,a,t)).elementType=D,e.lanes=n,e}function Kl(e,t,n){return(e=Zl(6,e,null,t)).lanes=n,e}function Ql(e,t,n){return(t=Zl(4,null!==e.children?e.children:[],e.key,t)).lanes=n,t.stateNode={containerInfo:e.containerInfo,pendingChildren:null,implementation:e.implementation},t}function Xl(e,t,n){this.tag=t,this.containerInfo=e,this.finishedWork=this.pingCache=this.current=this.pendingChildren=null,this.timeoutHandle=-1,this.pendingContext=this.context=null,this.hydrate=n,this.callbackNode=null,this.callbackPriority=0,this.eventTimes=zt(0),this.expirationTimes=zt(-1),this.entangledLanes=this.finishedLanes=this.mutableReadLanes=this.expiredLanes=this.pingedLanes=this.suspendedLanes=this.pendingLanes=0,this.entanglements=zt(0),this.mutableSourceEagerHydrationData=null}function Jl(e,t,n,a){var r=t.current,o=fl(),i=pl(r);e:if(n){t:{if(Ye(n=n._reactInternals)!==n||1!==n.tag)throw Error(s(170));var l=n;do{switch(l.tag){case 3:l=l.stateNode.context;break t;case 1:if(hr(l.type)){l=l.stateNode.__reactInternalMemoizedMergedChildContext;break t}}l=l.return}while(null!==l);throw Error(s(171))}if(1===n.tag){var c=n.type;if(hr(c)){n=yr(n,c,l);break e}}n=l}else n=dr;return null===t.context?t.context=n:t.pendingContext=n,(t=co(o,i)).payload={element:e},null!==(a=void 0===a?null:a)&&(t.callback=a),uo(r,t),ml(r,i,o),i}function ec(e){return(e=e.current).child?(e.child.tag,e.child.stateNode):null}function tc(e,t){if(null!==(e=e.memoizedState)&&null!==e.dehydrated){var n=e.retryLane;e.retryLane=0!==n&&n<t?n:t}}function nc(e,t){tc(e,t),(e=e.alternate)&&tc(e,t)}function ac(e,t,n){var a=null!=n&&null!=n.hydrationOptions&&n.hydrationOptions.mutableSources||null;if(n=new Xl(e,t,null!=n&&!0===n.hydrate),t=Zl(3,null,null,2===t?7:1===t?3:0),n.current=t,t.stateNode=n,io(t),e[Ja]=n.current,Na(8===e.nodeType?e.parentNode:e),a)for(e=0;e<a.length;e++){var r=(t=a[e])._getVersion;r=r(t._source),null==n.mutableSourceEagerHydrationData?n.mutableSourceEagerHydrationData=[t,r]:n.mutableSourceEagerHydrationData.push(t,r)}this._internalRoot=n}function rc(e){return!(!e||1!==e.nodeType&&9!==e.nodeType&&11!==e.nodeType&&(8!==e.nodeType||" react-mount-point-unstable "!==e.nodeValue))}function oc(e,t,n,a,r){var o=n._reactRootContainer;if(o){var s=o._internalRoot;if("function"==typeof r){var i=r;r=function(){var e=ec(s);i.call(e)}}Jl(t,s,e,r)}else{if(o=n._reactRootContainer=function(e,t){if(t||(t=!(!(t=e?9===e.nodeType?e.documentElement:e.firstChild:null)||1!==t.nodeType||!t.hasAttribute("data-reactroot"))),!t)for(var n;n=e.lastChild;)e.removeChild(n);return new ac(e,0,t?{hydrate:!0}:void 0)}(n,a),s=o._internalRoot,"function"==typeof r){var l=r;r=function(){var e=ec(s);l.call(e)}}wl((function(){Jl(t,s,e,r)}))}return ec(s)}function sc(e,t){var n=2<arguments.length&&void 0!==arguments[2]?arguments[2]:null;if(!rc(t))throw Error(s(200));return function(e,t,n){var a=3<arguments.length&&void 0!==arguments[3]?arguments[3]:null;return{$$typeof:E,key:null==a?null:""+a,children:e,containerInfo:t,implementation:n}}(e,t,null,n)}Gi=function(e,t,n){var a=t.lanes;if(null!==e)if(e.memoizedProps!==t.pendingProps||pr.current)Ms=!0;else{if(0==(n&a)){switch(Ms=!1,t.tag){case 3:Vs(t),Wo();break;case 5:Ro(t);break;case 1:hr(t.type)&&xr(t);break;case 4:Po(t,t.stateNode.containerInfo);break;case 10:a=t.memoizedProps.value;var r=t.type._context;ur(Qr,r._currentValue),r._currentValue=a;break;case 13:if(null!==t.memoizedState)return 0!=(n&t.child.childLanes)?Xs(e,t,n):(ur(Do,1&Do.current),null!==(t=oi(e,t,n))?t.sibling:null);ur(Do,1&Do.current);break;case 19:if(a=0!=(n&t.childLanes),0!=(64&e.flags)){if(a)return ri(e,t,n);t.flags|=64}if(null!==(r=t.memoizedState)&&(r.rendering=null,r.tail=null,r.lastEffect=null),ur(Do,Do.current),a)break;return null;case 23:case 24:return t.lanes=0,zs(e,t,n)}return oi(e,t,n)}Ms=0!=(16384&e.flags)}else Ms=!1;switch(t.lanes=0,t.tag){case 2:if(a=t.type,null!==e&&(e.alternate=null,t.alternate=null,t.flags|=2),e=t.pendingProps,r=gr(t,fr.current),ro(t,n),r=ss(null,t,a,e,r,n),t.flags|=1,"object"==typeof r&&null!==r&&"function"==typeof r.render&&void 0===r.$$typeof){if(t.tag=1,t.memoizedState=null,t.updateQueue=null,hr(a)){var o=!0;xr(t)}else o=!1;t.memoizedState=null!==r.state&&void 0!==r.state?r.state:null,io(t);var i=a.getDerivedStateFromProps;"function"==typeof i&&ho(t,a,i,e),r.updater=bo,t.stateNode=r,r._reactInternals=t,wo(t,a,e,n),t=Hs(null,t,a,!0,o,n)}else t.tag=0,Ds(null,t,r,n),t=t.child;return t;case 16:r=t.elementType;e:{switch(null!==e&&(e.alternate=null,t.alternate=null,t.flags|=2),e=t.pendingProps,r=(o=r._init)(r._payload),t.type=r,o=t.tag=function(e){if("function"==typeof e)return Hl(e)?1:0;if(null!=e){if((e=e.$$typeof)===A)return 11;if(e===O)return 14}return 2}(r),e=Kr(r,e),o){case 0:t=Us(null,t,r,e,n);break e;case 1:t=Zs(null,t,r,e,n);break e;case 11:t=Fs(null,t,r,e,n);break e;case 14:t=Bs(null,t,r,Kr(r.type,e),a,n);break e}throw Error(s(306,r,""))}return t;case 0:return a=t.type,r=t.pendingProps,Us(e,t,a,r=t.elementType===a?r:Kr(a,r),n);case 1:return a=t.type,r=t.pendingProps,Zs(e,t,a,r=t.elementType===a?r:Kr(a,r),n);case 3:if(Vs(t),a=t.updateQueue,null===e||null===a)throw Error(s(282));if(a=t.pendingProps,r=null!==(r=t.memoizedState)?r.element:null,lo(e,t),po(t,a,null,n),(a=t.memoizedState.element)===r)Wo(),t=oi(e,t,n);else{if((o=(r=t.stateNode).hydrate)&&(jo=Wa(t.stateNode.containerInfo.firstChild),Bo=t,o=zo=!0),o){if(null!=(e=r.mutableSourceEagerHydrationData))for(r=0;r<e.length;r+=2)(o=e[r])._workInProgressVersionPrimary=e[r+1],Go.push(o);for(n=qo(t,null,a,n),t.child=n;n;)n.flags=-3&n.flags|1024,n=n.sibling}else Ds(e,t,a,n),Wo();t=t.child}return t;case 5:return Ro(t),null===e&&Zo(t),a=t.type,r=t.pendingProps,o=null!==e?e.memoizedProps:null,i=r.children,Ua(a,r)?i=null:null!==o&&Ua(a,o)&&(t.flags|=16),$s(e,t),Ds(e,t,i,n),t.child;case 6:return null===e&&Zo(t),null;case 13:return Xs(e,t,n);case 4:return Po(t,t.stateNode.containerInfo),a=t.pendingProps,null===e?t.child=Co(t,null,a,n):Ds(e,t,a,n),t.child;case 11:return a=t.type,r=t.pendingProps,Fs(e,t,a,r=t.elementType===a?r:Kr(a,r),n);case 7:return Ds(e,t,t.pendingProps,n),t.child;case 8:case 12:return Ds(e,t,t.pendingProps.children,n),t.child;case 10:e:{a=t.type._context,r=t.pendingProps,i=t.memoizedProps,o=r.value;var l=t.type._context;if(ur(Qr,l._currentValue),l._currentValue=o,null!==i)if(l=i.value,0===(o=ca(l,o)?0:0|("function"==typeof a._calculateChangedBits?a._calculateChangedBits(l,o):1073741823))){if(i.children===r.children&&!pr.current){t=oi(e,t,n);break e}}else for(null!==(l=t.child)&&(l.return=t);null!==l;){var c=l.dependencies;if(null!==c){i=l.child;for(var u=c.firstContext;null!==u;){if(u.context===a&&0!=(u.observedBits&o)){1===l.tag&&((u=co(-1,n&-n)).tag=2,uo(l,u)),l.lanes|=n,null!==(u=l.alternate)&&(u.lanes|=n),ao(l.return,n),c.lanes|=n;break}u=u.next}}else i=10===l.tag&&l.type===t.type?null:l.child;if(null!==i)i.return=l;else for(i=l;null!==i;){if(i===t){i=null;break}if(null!==(l=i.sibling)){l.return=i.return,i=l;break}i=i.return}l=i}Ds(e,t,r.children,n),t=t.child}return t;case 9:return r=t.type,a=(o=t.pendingProps).children,ro(t,n),a=a(r=oo(r,o.unstable_observedBits)),t.flags|=1,Ds(e,t,a,n),t.child;case 14:return o=Kr(r=t.type,t.pendingProps),Bs(e,t,r,o=Kr(r.type,o),a,n);case 15:return js(e,t,t.type,t.pendingProps,a,n);case 17:return a=t.type,r=t.pendingProps,r=t.elementType===a?r:Kr(a,r),null!==e&&(e.alternate=null,t.alternate=null,t.flags|=2),t.tag=1,hr(a)?(e=!0,xr(t)):e=!1,ro(t,n),yo(t,a,r),wo(t,a,r,n),Hs(null,t,a,!0,e,n);case 19:return ri(e,t,n);case 23:case 24:return zs(e,t,n)}throw Error(s(156,t.tag))},ac.prototype.render=function(e){Jl(e,this._internalRoot,null,null)},ac.prototype.unmount=function(){var e=this._internalRoot,t=e.containerInfo;Jl(null,e,null,(function(){t[Ja]=null}))},et=function(e){13===e.tag&&(ml(e,4,fl()),nc(e,4))},tt=function(e){13===e.tag&&(ml(e,67108864,fl()),nc(e,67108864))},nt=function(e){if(13===e.tag){var t=fl(),n=pl(e);ml(e,n,t),nc(e,n)}},at=function(e,t){return t()},Ce=function(e,t,n){switch(t){case"input":if(ne(e,n),t=n.name,"radio"===n.type&&null!=t){for(n=e;n.parentNode;)n=n.parentNode;for(n=n.querySelectorAll("input[name="+JSON.stringify(""+t)+'][type="radio"]'),t=0;t<n.length;t++){var a=n[t];if(a!==e&&a.form===e.form){var r=rr(a);if(!r)throw Error(s(90));Q(a),ne(a,r)}}}break;case"textarea":ce(e,n);break;case"select":null!=(t=n.value)&&se(e,!!n.multiple,t,!1)}},Oe=xl,Pe=function(e,t,n,a,r){var o=Oi;Oi|=4;try{return Hr(98,e.bind(null,t,n,a,r))}finally{0===(Oi=o)&&(Wi(),Wr())}},Ie=function(){0==(49&Oi)&&(function(){if(null!==rl){var e=rl;rl=null,e.forEach((function(e){e.expiredLanes|=24&e.pendingLanes,hl(e,$r())}))}Wr()}(),Rl())},Re=function(e,t){var n=Oi;Oi|=2;try{return e(t)}finally{0===(Oi=n)&&(Wi(),Wr())}};var ic={Events:[nr,ar,rr,Le,Ne,Rl,{current:!1}]},lc={findFiberByHostInstance:tr,bundleType:0,version:"17.0.2",rendererPackageName:"react-dom"},cc={bundleType:lc.bundleType,version:lc.version,rendererPackageName:lc.rendererPackageName,rendererConfig:lc.rendererConfig,overrideHookState:null,overrideHookStateDeletePath:null,overrideHookStateRenamePath:null,overrideProps:null,overridePropsDeletePath:null,overridePropsRenamePath:null,setSuspenseHandler:null,scheduleUpdate:null,currentDispatcherRef:w.ReactCurrentDispatcher,findHostInstanceByFiber:function(e){return null===(e=Xe(e))?null:e.stateNode},findFiberByHostInstance:lc.findFiberByHostInstance||function(){return null},findHostInstancesForRefresh:null,scheduleRefresh:null,scheduleRoot:null,setRefreshHandler:null,getCurrentFiber:null};if("undefined"!=typeof __REACT_DEVTOOLS_GLOBAL_HOOK__){var uc=__REACT_DEVTOOLS_GLOBAL_HOOK__;if(!uc.isDisabled&&uc.supportsFiber)try{Sr=uc.inject(cc),Er=uc}catch(ge){}}t.hydrate=function(e,t,n){if(!rc(t))throw Error(s(200));return oc(null,e,t,!0,n)}},3935:(e,t,n)=>{"use strict";!function e(){if("undefined"!=typeof __REACT_DEVTOOLS_GLOBAL_HOOK__&&"function"==typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE)try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(e)}catch(t){console.error(t)}}(),e.exports=n(4448)},9590:e=>{var t="undefined"!=typeof Element,n="function"==typeof Map,a="function"==typeof Set,r="function"==typeof ArrayBuffer&&!!ArrayBuffer.isView;function o(e,s){if(e===s)return!0;if(e&&s&&"object"==typeof e&&"object"==typeof s){if(e.constructor!==s.constructor)return!1;var i,l,c,u;if(Array.isArray(e)){if((i=e.length)!=s.length)return!1;for(l=i;0!=l--;)if(!o(e[l],s[l]))return!1;return!0}if(n&&e instanceof Map&&s instanceof Map){if(e.size!==s.size)return!1;for(u=e.entries();!(l=u.next()).done;)if(!s.has(l.value[0]))return!1;for(u=e.entries();!(l=u.next()).done;)if(!o(l.value[1],s.get(l.value[0])))return!1;return!0}if(a&&e instanceof Set&&s instanceof Set){if(e.size!==s.size)return!1;for(u=e.entries();!(l=u.next()).done;)if(!s.has(l.value[0]))return!1;return!0}if(r&&ArrayBuffer.isView(e)&&ArrayBuffer.isView(s)){if((i=e.length)!=s.length)return!1;for(l=i;0!=l--;)if(e[l]!==s[l])return!1;return!0}if(e.constructor===RegExp)return e.source===s.source&&e.flags===s.flags;if(e.valueOf!==Object.prototype.valueOf&&"function"==typeof e.valueOf&&"function"==typeof s.valueOf)return e.valueOf()===s.valueOf();if(e.toString!==Object.prototype.toString&&"function"==typeof e.toString&&"function"==typeof s.toString)return e.toString()===s.toString();if((i=(c=Object.keys(e)).length)!==Object.keys(s).length)return!1;for(l=i;0!=l--;)if(!Object.prototype.hasOwnProperty.call(s,c[l]))return!1;if(t&&e instanceof Element)return!1;for(l=i;0!=l--;)if(("_owner"!==c[l]&&"__v"!==c[l]&&"__o"!==c[l]||!e.$$typeof)&&!o(e[c[l]],s[c[l]]))return!1;return!0}return e!=e&&s!=s}e.exports=function(e,t){try{return o(e,t)}catch(n){if((n.message||"").match(/stack|recursion/i))return console.warn("react-fast-compare cannot handle circular refs"),!1;throw n}}},405:(e,t,n)=>{"use strict";n.d(t,{B6:()=>H,ql:()=>J});var a=n(7294),r=n(5697),o=n.n(r),s=n(9590),i=n.n(s),l=n(1143),c=n.n(l),u=n(6774),d=n.n(u);function f(){return f=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var a in n)Object.prototype.hasOwnProperty.call(n,a)&&(e[a]=n[a])}return e},f.apply(this,arguments)}function p(e,t){e.prototype=Object.create(t.prototype),e.prototype.constructor=e,m(e,t)}function m(e,t){return m=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e},m(e,t)}function g(e,t){if(null==e)return{};var n,a,r={},o=Object.keys(e);for(a=0;a<o.length;a++)t.indexOf(n=o[a])>=0||(r[n]=e[n]);return r}var h={BASE:"base",BODY:"body",HEAD:"head",HTML:"html",LINK:"link",META:"meta",NOSCRIPT:"noscript",SCRIPT:"script",STYLE:"style",TITLE:"title",FRAGMENT:"Symbol(react.fragment)"},b={rel:["amphtml","canonical","alternate"]},v={type:["application/ld+json"]},y={charset:"",name:["robots","description"],property:["og:type","og:title","og:url","og:image","og:image:alt","og:description","twitter:url","twitter:title","twitter:description","twitter:image","twitter:image:alt","twitter:card","twitter:site"]},x=Object.keys(h).map((function(e){return h[e]})),w={accesskey:"accessKey",charset:"charSet",class:"className",contenteditable:"contentEditable",contextmenu:"contextMenu","http-equiv":"httpEquiv",itemprop:"itemProp",tabindex:"tabIndex"},S=Object.keys(w).reduce((function(e,t){return e[w[t]]=t,e}),{}),E=function(e,t){for(var n=e.length-1;n>=0;n-=1){var a=e[n];if(Object.prototype.hasOwnProperty.call(a,t))return a[t]}return null},k=function(e){var t=E(e,h.TITLE),n=E(e,"titleTemplate");if(Array.isArray(t)&&(t=t.join("")),n&&t)return n.replace(/%s/g,(function(){return t}));var a=E(e,"defaultTitle");return t||a||void 0},_=function(e){return E(e,"onChangeClientState")||function(){}},C=function(e,t){return t.filter((function(t){return void 0!==t[e]})).map((function(t){return t[e]})).reduce((function(e,t){return f({},e,t)}),{})},q=function(e,t){return t.filter((function(e){return void 0!==e[h.BASE]})).map((function(e){return e[h.BASE]})).reverse().reduce((function(t,n){if(!t.length)for(var a=Object.keys(n),r=0;r<a.length;r+=1){var o=a[r].toLowerCase();if(-1!==e.indexOf(o)&&n[o])return t.concat(n)}return t}),[])},T=function(e,t,n){var a={};return n.filter((function(t){return!!Array.isArray(t[e])||(void 0!==t[e]&&console&&"function"==typeof console.warn&&console.warn("Helmet: "+e+' should be of type "Array". Instead found type "'+typeof t[e]+'"'),!1)})).map((function(t){return t[e]})).reverse().reduce((function(e,n){var r={};n.filter((function(e){for(var n,o=Object.keys(e),s=0;s<o.length;s+=1){var i=o[s],l=i.toLowerCase();-1===t.indexOf(l)||"rel"===n&&"canonical"===e[n].toLowerCase()||"rel"===l&&"stylesheet"===e[l].toLowerCase()||(n=l),-1===t.indexOf(i)||"innerHTML"!==i&&"cssText"!==i&&"itemprop"!==i||(n=i)}if(!n||!e[n])return!1;var c=e[n].toLowerCase();return a[n]||(a[n]={}),r[n]||(r[n]={}),!a[n][c]&&(r[n][c]=!0,!0)})).reverse().forEach((function(t){return e.push(t)}));for(var o=Object.keys(r),s=0;s<o.length;s+=1){var i=o[s],l=f({},a[i],r[i]);a[i]=l}return e}),[]).reverse()},A=function(e,t){if(Array.isArray(e)&&e.length)for(var n=0;n<e.length;n+=1)if(e[n][t])return!0;return!1},L=function(e){return Array.isArray(e)?e.join(""):e},N=function(e,t){return Array.isArray(e)?e.reduce((function(e,n){return function(e,t){for(var n=Object.keys(e),a=0;a<n.length;a+=1)if(t[n[a]]&&t[n[a]].includes(e[n[a]]))return!0;return!1}(n,t)?e.priority.push(n):e.default.push(n),e}),{priority:[],default:[]}):{default:e}},O=function(e,t){var n;return f({},e,((n={})[t]=void 0,n))},P=[h.NOSCRIPT,h.SCRIPT,h.STYLE],I=function(e,t){return void 0===t&&(t=!0),!1===t?String(e):String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")},R=function(e){return Object.keys(e).reduce((function(t,n){var a=void 0!==e[n]?n+'="'+e[n]+'"':""+n;return t?t+" "+a:a}),"")},M=function(e,t){return void 0===t&&(t={}),Object.keys(e).reduce((function(t,n){return t[w[n]||n]=e[n],t}),t)},D=function(e,t){return t.map((function(t,n){var r,o=((r={key:n})["data-rh"]=!0,r);return Object.keys(t).forEach((function(e){var n=w[e]||e;"innerHTML"===n||"cssText"===n?o.dangerouslySetInnerHTML={__html:t.innerHTML||t.cssText}:o[n]=t[e]})),a.createElement(e,o)}))},F=function(e,t,n){switch(e){case h.TITLE:return{toComponent:function(){return n=t.titleAttributes,(r={key:e=t.title})["data-rh"]=!0,o=M(n,r),[a.createElement(h.TITLE,o,e)];var e,n,r,o},toString:function(){return function(e,t,n,a){var r=R(n),o=L(t);return r?"<"+e+' data-rh="true" '+r+">"+I(o,a)+"</"+e+">":"<"+e+' data-rh="true">'+I(o,a)+"</"+e+">"}(e,t.title,t.titleAttributes,n)}};case"bodyAttributes":case"htmlAttributes":return{toComponent:function(){return M(t)},toString:function(){return R(t)}};default:return{toComponent:function(){return D(e,t)},toString:function(){return function(e,t,n){return t.reduce((function(t,a){var r=Object.keys(a).filter((function(e){return!("innerHTML"===e||"cssText"===e)})).reduce((function(e,t){var r=void 0===a[t]?t:t+'="'+I(a[t],n)+'"';return e?e+" "+r:r}),""),o=a.innerHTML||a.cssText||"",s=-1===P.indexOf(e);return t+"<"+e+' data-rh="true" '+r+(s?"/>":">"+o+"</"+e+">")}),"")}(e,t,n)}}}},B=function(e){var t=e.baseTag,n=e.bodyAttributes,a=e.encode,r=e.htmlAttributes,o=e.noscriptTags,s=e.styleTags,i=e.title,l=void 0===i?"":i,c=e.titleAttributes,u=e.linkTags,d=e.metaTags,f=e.scriptTags,p={toComponent:function(){},toString:function(){return""}};if(e.prioritizeSeoTags){var m=function(e){var t=e.linkTags,n=e.scriptTags,a=e.encode,r=N(e.metaTags,y),o=N(t,b),s=N(n,v);return{priorityMethods:{toComponent:function(){return[].concat(D(h.META,r.priority),D(h.LINK,o.priority),D(h.SCRIPT,s.priority))},toString:function(){return F(h.META,r.priority,a)+" "+F(h.LINK,o.priority,a)+" "+F(h.SCRIPT,s.priority,a)}},metaTags:r.default,linkTags:o.default,scriptTags:s.default}}(e);p=m.priorityMethods,u=m.linkTags,d=m.metaTags,f=m.scriptTags}return{priority:p,base:F(h.BASE,t,a),bodyAttributes:F("bodyAttributes",n,a),htmlAttributes:F("htmlAttributes",r,a),link:F(h.LINK,u,a),meta:F(h.META,d,a),noscript:F(h.NOSCRIPT,o,a),script:F(h.SCRIPT,f,a),style:F(h.STYLE,s,a),title:F(h.TITLE,{title:l,titleAttributes:c},a)}},j=[],z=function(e,t){var n=this;void 0===t&&(t="undefined"!=typeof document),this.instances=[],this.value={setHelmet:function(e){n.context.helmet=e},helmetInstances:{get:function(){return n.canUseDOM?j:n.instances},add:function(e){(n.canUseDOM?j:n.instances).push(e)},remove:function(e){var t=(n.canUseDOM?j:n.instances).indexOf(e);(n.canUseDOM?j:n.instances).splice(t,1)}}},this.context=e,this.canUseDOM=t,t||(e.helmet=B({baseTag:[],bodyAttributes:{},encodeSpecialCharacters:!0,htmlAttributes:{},linkTags:[],metaTags:[],noscriptTags:[],scriptTags:[],styleTags:[],title:"",titleAttributes:{}}))},$=a.createContext({}),U=o().shape({setHelmet:o().func,helmetInstances:o().shape({get:o().func,add:o().func,remove:o().func})}),Z="undefined"!=typeof document,H=function(e){function t(n){var a;return(a=e.call(this,n)||this).helmetData=new z(a.props.context,t.canUseDOM),a}return p(t,e),t.prototype.render=function(){return a.createElement($.Provider,{value:this.helmetData.value},this.props.children)},t}(a.Component);H.canUseDOM=Z,H.propTypes={context:o().shape({helmet:o().shape()}),children:o().node.isRequired},H.defaultProps={context:{}},H.displayName="HelmetProvider";var V=function(e,t){var n,a=document.head||document.querySelector(h.HEAD),r=a.querySelectorAll(e+"[data-rh]"),o=[].slice.call(r),s=[];return t&&t.length&&t.forEach((function(t){var a=document.createElement(e);for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&("innerHTML"===r?a.innerHTML=t.innerHTML:"cssText"===r?a.styleSheet?a.styleSheet.cssText=t.cssText:a.appendChild(document.createTextNode(t.cssText)):a.setAttribute(r,void 0===t[r]?"":t[r]));a.setAttribute("data-rh","true"),o.some((function(e,t){return n=t,a.isEqualNode(e)}))?o.splice(n,1):s.push(a)})),o.forEach((function(e){return e.parentNode.removeChild(e)})),s.forEach((function(e){return a.appendChild(e)})),{oldTags:o,newTags:s}},W=function(e,t){var n=document.getElementsByTagName(e)[0];if(n){for(var a=n.getAttribute("data-rh"),r=a?a.split(","):[],o=[].concat(r),s=Object.keys(t),i=0;i<s.length;i+=1){var l=s[i],c=t[l]||"";n.getAttribute(l)!==c&&n.setAttribute(l,c),-1===r.indexOf(l)&&r.push(l);var u=o.indexOf(l);-1!==u&&o.splice(u,1)}for(var d=o.length-1;d>=0;d-=1)n.removeAttribute(o[d]);r.length===o.length?n.removeAttribute("data-rh"):n.getAttribute("data-rh")!==s.join(",")&&n.setAttribute("data-rh",s.join(","))}},G=function(e,t){var n=e.baseTag,a=e.htmlAttributes,r=e.linkTags,o=e.metaTags,s=e.noscriptTags,i=e.onChangeClientState,l=e.scriptTags,c=e.styleTags,u=e.title,d=e.titleAttributes;W(h.BODY,e.bodyAttributes),W(h.HTML,a),function(e,t){void 0!==e&&document.title!==e&&(document.title=L(e)),W(h.TITLE,t)}(u,d);var f={baseTag:V(h.BASE,n),linkTags:V(h.LINK,r),metaTags:V(h.META,o),noscriptTags:V(h.NOSCRIPT,s),scriptTags:V(h.SCRIPT,l),styleTags:V(h.STYLE,c)},p={},m={};Object.keys(f).forEach((function(e){var t=f[e],n=t.newTags,a=t.oldTags;n.length&&(p[e]=n),a.length&&(m[e]=f[e].oldTags)})),t&&t(),i(e,p,m)},Y=null,K=function(e){function t(){for(var t,n=arguments.length,a=new Array(n),r=0;r<n;r++)a[r]=arguments[r];return(t=e.call.apply(e,[this].concat(a))||this).rendered=!1,t}p(t,e);var n=t.prototype;return n.shouldComponentUpdate=function(e){return!d()(e,this.props)},n.componentDidUpdate=function(){this.emitChange()},n.componentWillUnmount=function(){this.props.context.helmetInstances.remove(this),this.emitChange()},n.emitChange=function(){var e,t,n=this.props.context,a=n.setHelmet,r=null,o=(e=n.helmetInstances.get().map((function(e){var t=f({},e.props);return delete t.context,t})),{baseTag:q(["href"],e),bodyAttributes:C("bodyAttributes",e),defer:E(e,"defer"),encode:E(e,"encodeSpecialCharacters"),htmlAttributes:C("htmlAttributes",e),linkTags:T(h.LINK,["rel","href"],e),metaTags:T(h.META,["name","charset","http-equiv","property","itemprop"],e),noscriptTags:T(h.NOSCRIPT,["innerHTML"],e),onChangeClientState:_(e),scriptTags:T(h.SCRIPT,["src","innerHTML"],e),styleTags:T(h.STYLE,["cssText"],e),title:k(e),titleAttributes:C("titleAttributes",e),prioritizeSeoTags:A(e,"prioritizeSeoTags")});H.canUseDOM?(t=o,Y&&cancelAnimationFrame(Y),t.defer?Y=requestAnimationFrame((function(){G(t,(function(){Y=null}))})):(G(t),Y=null)):B&&(r=B(o)),a(r)},n.init=function(){this.rendered||(this.rendered=!0,this.props.context.helmetInstances.add(this),this.emitChange())},n.render=function(){return this.init(),null},t}(a.Component);K.propTypes={context:U.isRequired},K.displayName="HelmetDispatcher";var Q=["children"],X=["children"],J=function(e){function t(){return e.apply(this,arguments)||this}p(t,e);var n=t.prototype;return n.shouldComponentUpdate=function(e){return!i()(O(this.props,"helmetData"),O(e,"helmetData"))},n.mapNestedChildrenToProps=function(e,t){if(!t)return null;switch(e.type){case h.SCRIPT:case h.NOSCRIPT:return{innerHTML:t};case h.STYLE:return{cssText:t};default:throw new Error("<"+e.type+" /> elements are self-closing and can not contain children. Refer to our API for more information.")}},n.flattenArrayTypeChildren=function(e){var t,n=e.child,a=e.arrayTypeChildren;return f({},a,((t={})[n.type]=[].concat(a[n.type]||[],[f({},e.newChildProps,this.mapNestedChildrenToProps(n,e.nestedChildren))]),t))},n.mapObjectTypeChildren=function(e){var t,n,a=e.child,r=e.newProps,o=e.newChildProps,s=e.nestedChildren;switch(a.type){case h.TITLE:return f({},r,((t={})[a.type]=s,t.titleAttributes=f({},o),t));case h.BODY:return f({},r,{bodyAttributes:f({},o)});case h.HTML:return f({},r,{htmlAttributes:f({},o)});default:return f({},r,((n={})[a.type]=f({},o),n))}},n.mapArrayTypeChildrenToProps=function(e,t){var n=f({},t);return Object.keys(e).forEach((function(t){var a;n=f({},n,((a={})[t]=e[t],a))})),n},n.warnOnInvalidChildren=function(e,t){return c()(x.some((function(t){return e.type===t})),"function"==typeof e.type?"You may be attempting to nest <Helmet> components within each other, which is not allowed. Refer to our API for more information.":"Only elements types "+x.join(", ")+" are allowed. Helmet does not support rendering <"+e.type+"> elements. Refer to our API for more information."),c()(!t||"string"==typeof t||Array.isArray(t)&&!t.some((function(e){return"string"!=typeof e})),"Helmet expects a string as a child of <"+e.type+">. Did you forget to wrap your children in braces? ( <"+e.type+">{``}</"+e.type+"> ) Refer to our API for more information."),!0},n.mapChildrenToProps=function(e,t){var n=this,r={};return a.Children.forEach(e,(function(e){if(e&&e.props){var a=e.props,o=a.children,s=g(a,Q),i=Object.keys(s).reduce((function(e,t){return e[S[t]||t]=s[t],e}),{}),l=e.type;switch("symbol"==typeof l?l=l.toString():n.warnOnInvalidChildren(e,o),l){case h.FRAGMENT:t=n.mapChildrenToProps(o,t);break;case h.LINK:case h.META:case h.NOSCRIPT:case h.SCRIPT:case h.STYLE:r=n.flattenArrayTypeChildren({child:e,arrayTypeChildren:r,newChildProps:i,nestedChildren:o});break;default:t=n.mapObjectTypeChildren({child:e,newProps:t,newChildProps:i,nestedChildren:o})}}})),this.mapArrayTypeChildrenToProps(r,t)},n.render=function(){var e=this.props,t=e.children,n=g(e,X),r=f({},n),o=n.helmetData;return t&&(r=this.mapChildrenToProps(t,r)),!o||o instanceof z||(o=new z(o.context,o.instances)),o?a.createElement(K,f({},r,{context:o.value,helmetData:void 0})):a.createElement($.Consumer,null,(function(e){return a.createElement(K,f({},r,{context:e}))}))},t}(a.Component);J.propTypes={base:o().object,bodyAttributes:o().object,children:o().oneOfType([o().arrayOf(o().node),o().node]),defaultTitle:o().string,defer:o().bool,encodeSpecialCharacters:o().bool,htmlAttributes:o().object,link:o().arrayOf(o().object),meta:o().arrayOf(o().object),noscript:o().arrayOf(o().object),onChangeClientState:o().func,script:o().arrayOf(o().object),style:o().arrayOf(o().object),title:o().string,titleAttributes:o().object,titleTemplate:o().string,prioritizeSeoTags:o().bool,helmetData:o().object},J.defaultProps={defer:!0,encodeSpecialCharacters:!0,prioritizeSeoTags:!1},J.displayName="Helmet"},9921:(e,t)=>{"use strict";var n="function"==typeof Symbol&&Symbol.for,a=n?Symbol.for("react.element"):60103,r=n?Symbol.for("react.portal"):60106,o=n?Symbol.for("react.fragment"):60107,s=n?Symbol.for("react.strict_mode"):60108,i=n?Symbol.for("react.profiler"):60114,l=n?Symbol.for("react.provider"):60109,c=n?Symbol.for("react.context"):60110,u=n?Symbol.for("react.async_mode"):60111,d=n?Symbol.for("react.concurrent_mode"):60111,f=n?Symbol.for("react.forward_ref"):60112,p=n?Symbol.for("react.suspense"):60113,m=n?Symbol.for("react.suspense_list"):60120,g=n?Symbol.for("react.memo"):60115,h=n?Symbol.for("react.lazy"):60116,b=n?Symbol.for("react.block"):60121,v=n?Symbol.for("react.fundamental"):60117,y=n?Symbol.for("react.responder"):60118,x=n?Symbol.for("react.scope"):60119;function w(e){if("object"==typeof e&&null!==e){var t=e.$$typeof;switch(t){case a:switch(e=e.type){case u:case d:case o:case i:case s:case p:return e;default:switch(e=e&&e.$$typeof){case c:case f:case h:case g:case l:return e;default:return t}}case r:return t}}}function S(e){return w(e)===d}t.AsyncMode=u,t.ConcurrentMode=d,t.ContextConsumer=c,t.ContextProvider=l,t.Element=a,t.ForwardRef=f,t.Fragment=o,t.Lazy=h,t.Memo=g,t.Portal=r,t.Profiler=i,t.StrictMode=s,t.Suspense=p,t.isAsyncMode=function(e){return S(e)||w(e)===u},t.isConcurrentMode=S,t.isContextConsumer=function(e){return w(e)===c},t.isContextProvider=function(e){return w(e)===l},t.isElement=function(e){return"object"==typeof e&&null!==e&&e.$$typeof===a},t.isForwardRef=function(e){return w(e)===f},t.isFragment=function(e){return w(e)===o},t.isLazy=function(e){return w(e)===h},t.isMemo=function(e){return w(e)===g},t.isPortal=function(e){return w(e)===r},t.isProfiler=function(e){return w(e)===i},t.isStrictMode=function(e){return w(e)===s},t.isSuspense=function(e){return w(e)===p},t.isValidElementType=function(e){return"string"==typeof e||"function"==typeof e||e===o||e===d||e===i||e===s||e===p||e===m||"object"==typeof e&&null!==e&&(e.$$typeof===h||e.$$typeof===g||e.$$typeof===l||e.$$typeof===c||e.$$typeof===f||e.$$typeof===v||e.$$typeof===y||e.$$typeof===x||e.$$typeof===b)},t.typeOf=w},9864:(e,t,n)=>{"use strict";e.exports=n(9921)},8356:(e,t,n)=>{"use strict";function a(e,t){e.prototype=Object.create(t.prototype),e.prototype.constructor=e,e.__proto__=t}function r(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function s(){return s=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var a in n)Object.prototype.hasOwnProperty.call(n,a)&&(e[a]=n[a])}return e},s.apply(this,arguments)}var i=n(7294),l=n(5697),c=[],u=[];function d(e){var t=e(),n={loading:!0,loaded:null,error:null};return n.promise=t.then((function(e){return n.loading=!1,n.loaded=e,e})).catch((function(e){throw n.loading=!1,n.error=e,e})),n}function f(e){var t={loading:!1,loaded:{},error:null},n=[];try{Object.keys(e).forEach((function(a){var r=d(e[a]);r.loading?t.loading=!0:(t.loaded[a]=r.loaded,t.error=r.error),n.push(r.promise),r.promise.then((function(e){t.loaded[a]=e})).catch((function(e){t.error=e}))}))}catch(a){t.error=a}return t.promise=Promise.all(n).then((function(e){return t.loading=!1,e})).catch((function(e){throw t.loading=!1,e})),t}function p(e,t){return i.createElement((n=e)&&n.__esModule?n.default:n,t);var n}function m(e,t){var d,f;if(!t.loading)throw new Error("react-loadable requires a `loading` component");var m=s({loader:null,loading:null,delay:200,timeout:null,render:p,webpack:null,modules:null},t),g=null;function h(){return g||(g=e(m.loader)),g.promise}return c.push(h),"function"==typeof m.webpack&&u.push((function(){if((0,m.webpack)().every((function(e){return void 0!==e&&void 0!==n.m[e]})))return h()})),f=d=function(t){function n(n){var a;return o(r(r(a=t.call(this,n)||this)),"retry",(function(){a.setState({error:null,loading:!0,timedOut:!1}),g=e(m.loader),a._loadModule()})),h(),a.state={error:g.error,pastDelay:!1,timedOut:!1,loading:g.loading,loaded:g.loaded},a}a(n,t),n.preload=function(){return h()};var s=n.prototype;return s.UNSAFE_componentWillMount=function(){this._loadModule()},s.componentDidMount=function(){this._mounted=!0},s._loadModule=function(){var e=this;if(this.context.loadable&&Array.isArray(m.modules)&&m.modules.forEach((function(t){e.context.loadable.report(t)})),g.loading){var t=function(t){e._mounted&&e.setState(t)};"number"==typeof m.delay&&(0===m.delay?this.setState({pastDelay:!0}):this._delay=setTimeout((function(){t({pastDelay:!0})}),m.delay)),"number"==typeof m.timeout&&(this._timeout=setTimeout((function(){t({timedOut:!0})}),m.timeout));var n=function(){t({error:g.error,loaded:g.loaded,loading:g.loading}),e._clearTimeouts()};g.promise.then((function(){return n(),null})).catch((function(e){return n(),null}))}},s.componentWillUnmount=function(){this._mounted=!1,this._clearTimeouts()},s._clearTimeouts=function(){clearTimeout(this._delay),clearTimeout(this._timeout)},s.render=function(){return this.state.loading||this.state.error?i.createElement(m.loading,{isLoading:this.state.loading,pastDelay:this.state.pastDelay,timedOut:this.state.timedOut,error:this.state.error,retry:this.retry}):this.state.loaded?m.render(this.state.loaded,this.props):null},n}(i.Component),o(d,"contextTypes",{loadable:l.shape({report:l.func.isRequired})}),f}function g(e){return m(d,e)}g.Map=function(e){if("function"!=typeof e.render)throw new Error("LoadableMap requires a `render(loaded, props)` function");return m(f,e)};var h=function(e){function t(){return e.apply(this,arguments)||this}a(t,e);var n=t.prototype;return n.getChildContext=function(){return{loadable:{report:this.props.report}}},n.render=function(){return i.Children.only(this.props.children)},t}(i.Component);function b(e){for(var t=[];e.length;){var n=e.pop();t.push(n())}return Promise.all(t).then((function(){if(e.length)return b(e)}))}o(h,"propTypes",{report:l.func.isRequired}),o(h,"childContextTypes",{loadable:l.shape({report:l.func.isRequired}).isRequired}),g.Capture=h,g.preloadAll=function(){return new Promise((function(e,t){b(c).then(e,t)}))},g.preloadReady=function(){return new Promise((function(e,t){b(u).then(e,e)}))},e.exports=g},8790:(e,t,n)=>{"use strict";n.d(t,{H:()=>i,f:()=>s});var a=n(6550),r=n(7462),o=n(7294);function s(e,t,n){return void 0===n&&(n=[]),e.some((function(e){var r=e.path?(0,a.LX)(t,e):n.length?n[n.length-1].match:a.F0.computeRootMatch(t);return r&&(n.push({route:e,match:r}),e.routes&&s(e.routes,t,n)),r})),n}function i(e,t,n){return void 0===t&&(t={}),void 0===n&&(n={}),e?o.createElement(a.rs,n,e.map((function(e,n){return o.createElement(a.AW,{key:e.key||n,path:e.path,exact:e.exact,strict:e.strict,render:function(n){return e.render?e.render((0,r.Z)({},n,{},t,{route:e})):o.createElement(e.component,(0,r.Z)({},n,t,{route:e}))}})}))):null}},3727:(e,t,n)=>{"use strict";n.d(t,{OL:()=>y,VK:()=>u,rU:()=>h});var a=n(6550),r=n(5068),o=n(7294),s=n(9318),i=n(7462),l=n(3366),c=n(8776),u=function(e){function t(){for(var t,n=arguments.length,a=new Array(n),r=0;r<n;r++)a[r]=arguments[r];return(t=e.call.apply(e,[this].concat(a))||this).history=(0,s.lX)(t.props),t}return(0,r.Z)(t,e),t.prototype.render=function(){return o.createElement(a.F0,{history:this.history,children:this.props.children})},t}(o.Component);o.Component;var d=function(e,t){return"function"==typeof e?e(t):e},f=function(e,t){return"string"==typeof e?(0,s.ob)(e,null,null,t):e},p=function(e){return e},m=o.forwardRef;void 0===m&&(m=p);var g=m((function(e,t){var n=e.innerRef,a=e.navigate,r=e.onClick,s=(0,l.Z)(e,["innerRef","navigate","onClick"]),c=s.target,u=(0,i.Z)({},s,{onClick:function(e){try{r&&r(e)}catch(t){throw e.preventDefault(),t}e.defaultPrevented||0!==e.button||c&&"_self"!==c||function(e){return!!(e.metaKey||e.altKey||e.ctrlKey||e.shiftKey)}(e)||(e.preventDefault(),a())}});return u.ref=p!==m&&t||n,o.createElement("a",u)}));var h=m((function(e,t){var n=e.component,r=void 0===n?g:n,u=e.replace,h=e.to,b=e.innerRef,v=(0,l.Z)(e,["component","replace","to","innerRef"]);return o.createElement(a.s6.Consumer,null,(function(e){e||(0,c.Z)(!1);var n=e.history,a=f(d(h,e.location),e.location),l=a?n.createHref(a):"",g=(0,i.Z)({},v,{href:l,navigate:function(){var t=d(h,e.location),a=(0,s.Ep)(e.location)===(0,s.Ep)(f(t));(u||a?n.replace:n.push)(t)}});return p!==m?g.ref=t||b:g.innerRef=b,o.createElement(r,g)}))})),b=function(e){return e},v=o.forwardRef;void 0===v&&(v=b);var y=v((function(e,t){var n=e["aria-current"],r=void 0===n?"page":n,s=e.activeClassName,u=void 0===s?"active":s,p=e.activeStyle,m=e.className,g=e.exact,y=e.isActive,x=e.location,w=e.sensitive,S=e.strict,E=e.style,k=e.to,_=e.innerRef,C=(0,l.Z)(e,["aria-current","activeClassName","activeStyle","className","exact","isActive","location","sensitive","strict","style","to","innerRef"]);return o.createElement(a.s6.Consumer,null,(function(e){e||(0,c.Z)(!1);var n=x||e.location,s=f(d(k,n),n),l=s.pathname,q=l&&l.replace(/([.+*?=^!:${}()[\]|/\\])/g,"\\$1"),T=q?(0,a.LX)(n.pathname,{path:q,exact:g,sensitive:w,strict:S}):null,A=!!(y?y(T,n):T),L="function"==typeof m?m(A):m,N="function"==typeof E?E(A):E;A&&(L=function(){for(var e=arguments.length,t=new Array(e),n=0;n<e;n++)t[n]=arguments[n];return t.filter((function(e){return e})).join(" ")}(L,u),N=(0,i.Z)({},N,p));var O=(0,i.Z)({"aria-current":A&&r||null,className:L,style:N,to:s},C);return b!==v?O.ref=t||_:O.innerRef=_,o.createElement(h,O)}))}))},6550:(e,t,n)=>{"use strict";n.d(t,{AW:()=>k,F0:()=>y,LX:()=>E,TH:()=>P,k6:()=>O,rs:()=>L,s6:()=>v});var a=n(5068),r=n(7294),o=n(5697),s=n.n(o),i=n(9318),l=n(8776),c=n(7462),u=n(9658),d=n.n(u),f=(n(9864),n(3366)),p=(n(8679),1073741823),m="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:void 0!==n.g?n.g:{};var g=r.createContext||function(e,t){var n,o,i="__create-react-context-"+function(){var e="__global_unique_id__";return m[e]=(m[e]||0)+1}()+"__",l=function(e){function n(){for(var t,n,a,r=arguments.length,o=new Array(r),s=0;s<r;s++)o[s]=arguments[s];return(t=e.call.apply(e,[this].concat(o))||this).emitter=(n=t.props.value,a=[],{on:function(e){a.push(e)},off:function(e){a=a.filter((function(t){return t!==e}))},get:function(){return n},set:function(e,t){n=e,a.forEach((function(e){return e(n,t)}))}}),t}(0,a.Z)(n,e);var r=n.prototype;return r.getChildContext=function(){var e;return(e={})[i]=this.emitter,e},r.componentWillReceiveProps=function(e){if(this.props.value!==e.value){var n,a=this.props.value,r=e.value;((o=a)===(s=r)?0!==o||1/o==1/s:o!=o&&s!=s)?n=0:(n="function"==typeof t?t(a,r):p,0!==(n|=0)&&this.emitter.set(e.value,n))}var o,s},r.render=function(){return this.props.children},n}(r.Component);l.childContextTypes=((n={})[i]=s().object.isRequired,n);var c=function(t){function n(){for(var e,n=arguments.length,a=new Array(n),r=0;r<n;r++)a[r]=arguments[r];return(e=t.call.apply(t,[this].concat(a))||this).observedBits=void 0,e.state={value:e.getValue()},e.onUpdate=function(t,n){0!=((0|e.observedBits)&n)&&e.setState({value:e.getValue()})},e}(0,a.Z)(n,t);var r=n.prototype;return r.componentWillReceiveProps=function(e){var t=e.observedBits;this.observedBits=null==t?p:t},r.componentDidMount=function(){this.context[i]&&this.context[i].on(this.onUpdate);var e=this.props.observedBits;this.observedBits=null==e?p:e},r.componentWillUnmount=function(){this.context[i]&&this.context[i].off(this.onUpdate)},r.getValue=function(){return this.context[i]?this.context[i].get():e},r.render=function(){return(e=this.props.children,Array.isArray(e)?e[0]:e)(this.state.value);var e},n}(r.Component);return c.contextTypes=((o={})[i]=s().object,o),{Provider:l,Consumer:c}},h=function(e){var t=g();return t.displayName=e,t},b=h("Router-History"),v=h("Router"),y=function(e){function t(t){var n;return(n=e.call(this,t)||this).state={location:t.history.location},n._isMounted=!1,n._pendingLocation=null,t.staticContext||(n.unlisten=t.history.listen((function(e){n._pendingLocation=e}))),n}(0,a.Z)(t,e),t.computeRootMatch=function(e){return{path:"/",url:"/",params:{},isExact:"/"===e}};var n=t.prototype;return n.componentDidMount=function(){var e=this;this._isMounted=!0,this.unlisten&&this.unlisten(),this.props.staticContext||(this.unlisten=this.props.history.listen((function(t){e._isMounted&&e.setState({location:t})}))),this._pendingLocation&&this.setState({location:this._pendingLocation})},n.componentWillUnmount=function(){this.unlisten&&(this.unlisten(),this._isMounted=!1,this._pendingLocation=null)},n.render=function(){return r.createElement(v.Provider,{value:{history:this.props.history,location:this.state.location,match:t.computeRootMatch(this.state.location.pathname),staticContext:this.props.staticContext}},r.createElement(b.Provider,{children:this.props.children||null,value:this.props.history}))},t}(r.Component);r.Component;r.Component;var x={},w=1e4,S=0;function E(e,t){void 0===t&&(t={}),("string"==typeof t||Array.isArray(t))&&(t={path:t});var n=t,a=n.path,r=n.exact,o=void 0!==r&&r,s=n.strict,i=void 0!==s&&s,l=n.sensitive,c=void 0!==l&&l;return[].concat(a).reduce((function(t,n){if(!n&&""!==n)return null;if(t)return t;var a=function(e,t){var n=""+t.end+t.strict+t.sensitive,a=x[n]||(x[n]={});if(a[e])return a[e];var r=[],o={regexp:d()(e,r,t),keys:r};return S<w&&(a[e]=o,S++),o}(n,{end:o,strict:i,sensitive:c}),r=a.regexp,s=a.keys,l=r.exec(e);if(!l)return null;var u=l[0],f=l.slice(1),p=e===u;return o&&!p?null:{path:n,url:"/"===n&&""===u?"/":u,isExact:p,params:s.reduce((function(e,t,n){return e[t.name]=f[n],e}),{})}}),null)}var k=function(e){function t(){return e.apply(this,arguments)||this}return(0,a.Z)(t,e),t.prototype.render=function(){var e=this;return r.createElement(v.Consumer,null,(function(t){t||(0,l.Z)(!1);var n=e.props.location||t.location,a=e.props.computedMatch?e.props.computedMatch:e.props.path?E(n.pathname,e.props):t.match,o=(0,c.Z)({},t,{location:n,match:a}),s=e.props,i=s.children,u=s.component,d=s.render;return Array.isArray(i)&&function(e){return 0===r.Children.count(e)}(i)&&(i=null),r.createElement(v.Provider,{value:o},o.match?i?"function"==typeof i?i(o):i:u?r.createElement(u,o):d?d(o):null:"function"==typeof i?i(o):null)}))},t}(r.Component);function _(e){return"/"===e.charAt(0)?e:"/"+e}function C(e,t){if(!e)return t;var n=_(e);return 0!==t.pathname.indexOf(n)?t:(0,c.Z)({},t,{pathname:t.pathname.substr(n.length)})}function q(e){return"string"==typeof e?e:(0,i.Ep)(e)}function T(e){return function(){(0,l.Z)(!1)}}function A(){}r.Component;var L=function(e){function t(){return e.apply(this,arguments)||this}return(0,a.Z)(t,e),t.prototype.render=function(){var e=this;return r.createElement(v.Consumer,null,(function(t){t||(0,l.Z)(!1);var n,a,o=e.props.location||t.location;return r.Children.forEach(e.props.children,(function(e){if(null==a&&r.isValidElement(e)){n=e;var s=e.props.path||e.props.from;a=s?E(o.pathname,(0,c.Z)({},e.props,{path:s})):t.match}})),a?r.cloneElement(n,{location:o,computedMatch:a}):null}))},t}(r.Component);var N=r.useContext;function O(){return N(b)}function P(){return N(v).location}},9658:(e,t,n)=>{var a=n(5826);e.exports=p,e.exports.parse=o,e.exports.compile=function(e,t){return i(o(e,t),t)},e.exports.tokensToFunction=i,e.exports.tokensToRegExp=f;var r=new RegExp(["(\\\\.)","([\\/.])?(?:(?:\\:(\\w+)(?:\\(((?:\\\\.|[^\\\\()])+)\\))?|\\(((?:\\\\.|[^\\\\()])+)\\))([+*?])?|(\\*))"].join("|"),"g");function o(e,t){for(var n,a=[],o=0,s=0,i="",u=t&&t.delimiter||"/";null!=(n=r.exec(e));){var d=n[0],f=n[1],p=n.index;if(i+=e.slice(s,p),s=p+d.length,f)i+=f[1];else{var m=e[s],g=n[2],h=n[3],b=n[4],v=n[5],y=n[6],x=n[7];i&&(a.push(i),i="");var w=null!=g&&null!=m&&m!==g,S="+"===y||"*"===y,E="?"===y||"*"===y,k=n[2]||u,_=b||v;a.push({name:h||o++,prefix:g||"",delimiter:k,optional:E,repeat:S,partial:w,asterisk:!!x,pattern:_?c(_):x?".*":"[^"+l(k)+"]+?"})}}return s<e.length&&(i+=e.substr(s)),i&&a.push(i),a}function s(e){return encodeURI(e).replace(/[\/?#]/g,(function(e){return"%"+e.charCodeAt(0).toString(16).toUpperCase()}))}function i(e,t){for(var n=new Array(e.length),r=0;r<e.length;r++)"object"==typeof e[r]&&(n[r]=new RegExp("^(?:"+e[r].pattern+")$",d(t)));return function(t,r){for(var o="",i=t||{},l=(r||{}).pretty?s:encodeURIComponent,c=0;c<e.length;c++){var u=e[c];if("string"!=typeof u){var d,f=i[u.name];if(null==f){if(u.optional){u.partial&&(o+=u.prefix);continue}throw new TypeError('Expected "'+u.name+'" to be defined')}if(a(f)){if(!u.repeat)throw new TypeError('Expected "'+u.name+'" to not repeat, but received `'+JSON.stringify(f)+"`");if(0===f.length){if(u.optional)continue;throw new TypeError('Expected "'+u.name+'" to not be empty')}for(var p=0;p<f.length;p++){if(d=l(f[p]),!n[c].test(d))throw new TypeError('Expected all "'+u.name+'" to match "'+u.pattern+'", but received `'+JSON.stringify(d)+"`");o+=(0===p?u.prefix:u.delimiter)+d}}else{if(d=u.asterisk?encodeURI(f).replace(/[?#]/g,(function(e){return"%"+e.charCodeAt(0).toString(16).toUpperCase()})):l(f),!n[c].test(d))throw new TypeError('Expected "'+u.name+'" to match "'+u.pattern+'", but received "'+d+'"');o+=u.prefix+d}}else o+=u}return o}}function l(e){return e.replace(/([.+*?=^!:${}()[\]|\/\\])/g,"\\$1")}function c(e){return e.replace(/([=!:$\/()])/g,"\\$1")}function u(e,t){return e.keys=t,e}function d(e){return e&&e.sensitive?"":"i"}function f(e,t,n){a(t)||(n=t||n,t=[]);for(var r=(n=n||{}).strict,o=!1!==n.end,s="",i=0;i<e.length;i++){var c=e[i];if("string"==typeof c)s+=l(c);else{var f=l(c.prefix),p="(?:"+c.pattern+")";t.push(c),c.repeat&&(p+="(?:"+f+p+")*"),s+=p=c.optional?c.partial?f+"("+p+")?":"(?:"+f+"("+p+"))?":f+"("+p+")"}}var m=l(n.delimiter||"/"),g=s.slice(-m.length)===m;return r||(s=(g?s.slice(0,-m.length):s)+"(?:"+m+"(?=$))?"),s+=o?"$":r&&g?"":"(?="+m+"|$)",u(new RegExp("^"+s,d(n)),t)}function p(e,t,n){return a(t)||(n=t||n,t=[]),n=n||{},e instanceof RegExp?function(e,t){var n=e.source.match(/\((?!\?)/g);if(n)for(var a=0;a<n.length;a++)t.push({name:a,prefix:null,delimiter:null,optional:!1,repeat:!1,partial:!1,asterisk:!1,pattern:null});return u(e,t)}(e,t):a(e)?function(e,t,n){for(var a=[],r=0;r<e.length;r++)a.push(p(e[r],t,n).source);return u(new RegExp("(?:"+a.join("|")+")",d(n)),t)}(e,t,n):function(e,t,n){return f(o(e,n),t,n)}(e,t,n)}},2408:(e,t,n)=>{"use strict";var a=n(7418),r=60103,o=60106;t.Fragment=60107,t.StrictMode=60108,t.Profiler=60114;var s=60109,i=60110,l=60112;t.Suspense=60113;var c=60115,u=60116;if("function"==typeof Symbol&&Symbol.for){var d=Symbol.for;r=d("react.element"),o=d("react.portal"),t.Fragment=d("react.fragment"),t.StrictMode=d("react.strict_mode"),t.Profiler=d("react.profiler"),s=d("react.provider"),i=d("react.context"),l=d("react.forward_ref"),t.Suspense=d("react.suspense"),c=d("react.memo"),u=d("react.lazy")}var f="function"==typeof Symbol&&Symbol.iterator;function p(e){for(var t="https://reactjs.org/docs/error-decoder.html?invariant="+e,n=1;n<arguments.length;n++)t+="&args[]="+encodeURIComponent(arguments[n]);return"Minified React error #"+e+"; visit "+t+" for the full message or use the non-minified dev environment for full errors and additional helpful warnings."}var m={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},g={};function h(e,t,n){this.props=e,this.context=t,this.refs=g,this.updater=n||m}function b(){}function v(e,t,n){this.props=e,this.context=t,this.refs=g,this.updater=n||m}h.prototype.isReactComponent={},h.prototype.setState=function(e,t){if("object"!=typeof e&&"function"!=typeof e&&null!=e)throw Error(p(85));this.updater.enqueueSetState(this,e,t,"setState")},h.prototype.forceUpdate=function(e){this.updater.enqueueForceUpdate(this,e,"forceUpdate")},b.prototype=h.prototype;var y=v.prototype=new b;y.constructor=v,a(y,h.prototype),y.isPureReactComponent=!0;var x={current:null},w=Object.prototype.hasOwnProperty,S={key:!0,ref:!0,__self:!0,__source:!0};function E(e,t,n){var a,o={},s=null,i=null;if(null!=t)for(a in void 0!==t.ref&&(i=t.ref),void 0!==t.key&&(s=""+t.key),t)w.call(t,a)&&!S.hasOwnProperty(a)&&(o[a]=t[a]);var l=arguments.length-2;if(1===l)o.children=n;else if(1<l){for(var c=Array(l),u=0;u<l;u++)c[u]=arguments[u+2];o.children=c}if(e&&e.defaultProps)for(a in l=e.defaultProps)void 0===o[a]&&(o[a]=l[a]);return{$$typeof:r,type:e,key:s,ref:i,props:o,_owner:x.current}}function k(e){return"object"==typeof e&&null!==e&&e.$$typeof===r}var _=/\/+/g;function C(e,t){return"object"==typeof e&&null!==e&&null!=e.key?function(e){var t={"=":"=0",":":"=2"};return"$"+e.replace(/[=:]/g,(function(e){return t[e]}))}(""+e.key):t.toString(36)}function q(e,t,n,a,s){var i=typeof e;"undefined"!==i&&"boolean"!==i||(e=null);var l=!1;if(null===e)l=!0;else switch(i){case"string":case"number":l=!0;break;case"object":switch(e.$$typeof){case r:case o:l=!0}}if(l)return s=s(l=e),e=""===a?"."+C(l,0):a,Array.isArray(s)?(n="",null!=e&&(n=e.replace(_,"$&/")+"/"),q(s,t,n,"",(function(e){return e}))):null!=s&&(k(s)&&(s=function(e,t){return{$$typeof:r,type:e.type,key:t,ref:e.ref,props:e.props,_owner:e._owner}}(s,n+(!s.key||l&&l.key===s.key?"":(""+s.key).replace(_,"$&/")+"/")+e)),t.push(s)),1;if(l=0,a=""===a?".":a+":",Array.isArray(e))for(var c=0;c<e.length;c++){var u=a+C(i=e[c],c);l+=q(i,t,n,u,s)}else if(u=function(e){return null===e||"object"!=typeof e?null:"function"==typeof(e=f&&e[f]||e["@@iterator"])?e:null}(e),"function"==typeof u)for(e=u.call(e),c=0;!(i=e.next()).done;)l+=q(i=i.value,t,n,u=a+C(i,c++),s);else if("object"===i)throw t=""+e,Error(p(31,"[object Object]"===t?"object with keys {"+Object.keys(e).join(", ")+"}":t));return l}function T(e,t,n){if(null==e)return e;var a=[],r=0;return q(e,a,"","",(function(e){return t.call(n,e,r++)})),a}function A(e){if(-1===e._status){var t=e._result;t=t(),e._status=0,e._result=t,t.then((function(t){0===e._status&&(t=t.default,e._status=1,e._result=t)}),(function(t){0===e._status&&(e._status=2,e._result=t)}))}if(1===e._status)return e._result;throw e._result}var L={current:null};function N(){var e=L.current;if(null===e)throw Error(p(321));return e}var O={ReactCurrentDispatcher:L,ReactCurrentBatchConfig:{transition:0},ReactCurrentOwner:x,IsSomeRendererActing:{current:!1},assign:a};t.Children={map:T,forEach:function(e,t,n){T(e,(function(){t.apply(this,arguments)}),n)},count:function(e){var t=0;return T(e,(function(){t++})),t},toArray:function(e){return T(e,(function(e){return e}))||[]},only:function(e){if(!k(e))throw Error(p(143));return e}},t.Component=h,t.PureComponent=v,t.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED=O,t.cloneElement=function(e,t,n){if(null==e)throw Error(p(267,e));var o=a({},e.props),s=e.key,i=e.ref,l=e._owner;if(null!=t){if(void 0!==t.ref&&(i=t.ref,l=x.current),void 0!==t.key&&(s=""+t.key),e.type&&e.type.defaultProps)var c=e.type.defaultProps;for(u in t)w.call(t,u)&&!S.hasOwnProperty(u)&&(o[u]=void 0===t[u]&&void 0!==c?c[u]:t[u])}var u=arguments.length-2;if(1===u)o.children=n;else if(1<u){c=Array(u);for(var d=0;d<u;d++)c[d]=arguments[d+2];o.children=c}return{$$typeof:r,type:e.type,key:s,ref:i,props:o,_owner:l}},t.createContext=function(e,t){return void 0===t&&(t=null),(e={$$typeof:i,_calculateChangedBits:t,_currentValue:e,_currentValue2:e,_threadCount:0,Provider:null,Consumer:null}).Provider={$$typeof:s,_context:e},e.Consumer=e},t.createElement=E,t.createFactory=function(e){var t=E.bind(null,e);return t.type=e,t},t.createRef=function(){return{current:null}},t.forwardRef=function(e){return{$$typeof:l,render:e}},t.isValidElement=k,t.lazy=function(e){return{$$typeof:u,_payload:{_status:-1,_result:e},_init:A}},t.memo=function(e,t){return{$$typeof:c,type:e,compare:void 0===t?null:t}},t.useCallback=function(e,t){return N().useCallback(e,t)},t.useContext=function(e,t){return N().useContext(e,t)},t.useDebugValue=function(){},t.useEffect=function(e,t){return N().useEffect(e,t)},t.useImperativeHandle=function(e,t,n){return N().useImperativeHandle(e,t,n)},t.useLayoutEffect=function(e,t){return N().useLayoutEffect(e,t)},t.useMemo=function(e,t){return N().useMemo(e,t)},t.useReducer=function(e,t,n){return N().useReducer(e,t,n)},t.useRef=function(e){return N().useRef(e)},t.useState=function(e){return N().useState(e)},t.version="17.0.2"},7294:(e,t,n)=>{"use strict";e.exports=n(2408)},53:(e,t)=>{"use strict";var n,a,r,o;if("object"==typeof performance&&"function"==typeof performance.now){var s=performance;t.unstable_now=function(){return s.now()}}else{var i=Date,l=i.now();t.unstable_now=function(){return i.now()-l}}if("undefined"==typeof window||"function"!=typeof MessageChannel){var c=null,u=null,d=function(){if(null!==c)try{var e=t.unstable_now();c(!0,e),c=null}catch(n){throw setTimeout(d,0),n}};n=function(e){null!==c?setTimeout(n,0,e):(c=e,setTimeout(d,0))},a=function(e,t){u=setTimeout(e,t)},r=function(){clearTimeout(u)},t.unstable_shouldYield=function(){return!1},o=t.unstable_forceFrameRate=function(){}}else{var f=window.setTimeout,p=window.clearTimeout;if("undefined"!=typeof console){var m=window.cancelAnimationFrame;"function"!=typeof window.requestAnimationFrame&&console.error("This browser doesn't support requestAnimationFrame. Make sure that you load a polyfill in older browsers. https://reactjs.org/link/react-polyfills"),"function"!=typeof m&&console.error("This browser doesn't support cancelAnimationFrame. Make sure that you load a polyfill in older browsers. https://reactjs.org/link/react-polyfills")}var g=!1,h=null,b=-1,v=5,y=0;t.unstable_shouldYield=function(){return t.unstable_now()>=y},o=function(){},t.unstable_forceFrameRate=function(e){0>e||125<e?console.error("forceFrameRate takes a positive int between 0 and 125, forcing frame rates higher than 125 fps is not supported"):v=0<e?Math.floor(1e3/e):5};var x=new MessageChannel,w=x.port2;x.port1.onmessage=function(){if(null!==h){var e=t.unstable_now();y=e+v;try{h(!0,e)?w.postMessage(null):(g=!1,h=null)}catch(n){throw w.postMessage(null),n}}else g=!1},n=function(e){h=e,g||(g=!0,w.postMessage(null))},a=function(e,n){b=f((function(){e(t.unstable_now())}),n)},r=function(){p(b),b=-1}}function S(e,t){var n=e.length;e.push(t);e:for(;;){var a=n-1>>>1,r=e[a];if(!(void 0!==r&&0<_(r,t)))break e;e[a]=t,e[n]=r,n=a}}function E(e){return void 0===(e=e[0])?null:e}function k(e){var t=e[0];if(void 0!==t){var n=e.pop();if(n!==t){e[0]=n;e:for(var a=0,r=e.length;a<r;){var o=2*(a+1)-1,s=e[o],i=o+1,l=e[i];if(void 0!==s&&0>_(s,n))void 0!==l&&0>_(l,s)?(e[a]=l,e[i]=n,a=i):(e[a]=s,e[o]=n,a=o);else{if(!(void 0!==l&&0>_(l,n)))break e;e[a]=l,e[i]=n,a=i}}}return t}return null}function _(e,t){var n=e.sortIndex-t.sortIndex;return 0!==n?n:e.id-t.id}var C=[],q=[],T=1,A=null,L=3,N=!1,O=!1,P=!1;function I(e){for(var t=E(q);null!==t;){if(null===t.callback)k(q);else{if(!(t.startTime<=e))break;k(q),t.sortIndex=t.expirationTime,S(C,t)}t=E(q)}}function R(e){if(P=!1,I(e),!O)if(null!==E(C))O=!0,n(M);else{var t=E(q);null!==t&&a(R,t.startTime-e)}}function M(e,n){O=!1,P&&(P=!1,r()),N=!0;var o=L;try{for(I(n),A=E(C);null!==A&&(!(A.expirationTime>n)||e&&!t.unstable_shouldYield());){var s=A.callback;if("function"==typeof s){A.callback=null,L=A.priorityLevel;var i=s(A.expirationTime<=n);n=t.unstable_now(),"function"==typeof i?A.callback=i:A===E(C)&&k(C),I(n)}else k(C);A=E(C)}if(null!==A)var l=!0;else{var c=E(q);null!==c&&a(R,c.startTime-n),l=!1}return l}finally{A=null,L=o,N=!1}}var D=o;t.unstable_IdlePriority=5,t.unstable_ImmediatePriority=1,t.unstable_LowPriority=4,t.unstable_NormalPriority=3,t.unstable_Profiling=null,t.unstable_UserBlockingPriority=2,t.unstable_cancelCallback=function(e){e.callback=null},t.unstable_continueExecution=function(){O||N||(O=!0,n(M))},t.unstable_getCurrentPriorityLevel=function(){return L},t.unstable_getFirstCallbackNode=function(){return E(C)},t.unstable_next=function(e){switch(L){case 1:case 2:case 3:var t=3;break;default:t=L}var n=L;L=t;try{return e()}finally{L=n}},t.unstable_pauseExecution=function(){},t.unstable_requestPaint=D,t.unstable_runWithPriority=function(e,t){switch(e){case 1:case 2:case 3:case 4:case 5:break;default:e=3}var n=L;L=e;try{return t()}finally{L=n}},t.unstable_scheduleCallback=function(e,o,s){var i=t.unstable_now();switch("object"==typeof s&&null!==s?s="number"==typeof(s=s.delay)&&0<s?i+s:i:s=i,e){case 1:var l=-1;break;case 2:l=250;break;case 5:l=1073741823;break;case 4:l=1e4;break;default:l=5e3}return e={id:T++,callback:o,priorityLevel:e,startTime:s,expirationTime:l=s+l,sortIndex:-1},s>i?(e.sortIndex=s,S(q,e),null===E(C)&&e===E(q)&&(P?r():P=!0,a(R,s-i))):(e.sortIndex=l,S(C,e),O||N||(O=!0,n(M))),e},t.unstable_wrapCallback=function(e){var t=L;return function(){var n=L;L=t;try{return e.apply(this,arguments)}finally{L=n}}}},3840:(e,t,n)=>{"use strict";e.exports=n(53)},6774:e=>{e.exports=function(e,t,n,a){var r=n?n.call(a,e,t):void 0;if(void 0!==r)return!!r;if(e===t)return!0;if("object"!=typeof e||!e||"object"!=typeof t||!t)return!1;var o=Object.keys(e),s=Object.keys(t);if(o.length!==s.length)return!1;for(var i=Object.prototype.hasOwnProperty.bind(t),l=0;l<o.length;l++){var c=o[l];if(!i(c))return!1;var u=e[c],d=t[c];if(!1===(r=n?n.call(a,u,d,c):void 0)||void 0===r&&u!==d)return!1}return!0}},3250:(e,t,n)=>{"use strict";var a=n(7294);var r="function"==typeof Object.is?Object.is:function(e,t){return e===t&&(0!==e||1/e==1/t)||e!=e&&t!=t},o=a.useState,s=a.useEffect,i=a.useLayoutEffect,l=a.useDebugValue;function c(e){var t=e.getSnapshot;e=e.value;try{var n=t();return!r(e,n)}catch(a){return!0}}var u="undefined"==typeof window||void 0===window.document||void 0===window.document.createElement?function(e,t){return t()}:function(e,t){var n=t(),a=o({inst:{value:n,getSnapshot:t}}),r=a[0].inst,u=a[1];return i((function(){r.value=n,r.getSnapshot=t,c(r)&&u({inst:r})}),[e,n,t]),s((function(){return c(r)&&u({inst:r}),e((function(){c(r)&&u({inst:r})}))}),[e]),l(n),n};void 0!==a.useSyncExternalStore&&a.useSyncExternalStore},1688:(e,t,n)=>{"use strict";n(3250)},6809:(e,t,n)=>{"use strict";n.d(t,{default:()=>a});const a={title:"GlueSQL",tagline:"GlueSQL is quite sticky. It attaches to anywhere",favicon:"img/favicon.ico",url:"https://gluesql.org",baseUrl:"/docs/dev/",onBrokenLinks:"throw",onBrokenMarkdownLinks:"warn",i18n:{defaultLocale:"en",locales:["en"],path:"i18n",localeConfigs:{}},presets:[["classic",{theme:{customCss:"/home/runner/work/gluesql/gluesql/docs/src/css/custom.css"},pages:!1,docs:{sidebarPath:"/home/runner/work/gluesql/gluesql/docs/sidebars.js",routeBasePath:"/"}}]],themeConfig:{colorMode:{disableSwitch:!1,respectPrefersColorScheme:!0,defaultMode:"light"},navbar:{title:"GlueSQL",items:[{to:"getting-started/rust",position:"left",label:"Getting Started",activeBasePath:"getting-started"},{to:"sql-syntax/intro",position:"left",label:"SQL Syntax",activeBasePath:"sql-syntax"},{to:"ast-builder/intro",position:"left",label:"AST Builder",activeBasePath:"ast-builder"},{to:"storages/intro",position:"left",label:"Storages",activeBasePath:"storages"},{href:"https://gluesql.org/blog",label:"Blog",position:"right"},{href:"https://github.com/gluesql/gluesql",label:"GitHub",position:"right"}],hideOnScroll:!1},prism:{theme:{plain:{color:"#393A34",backgroundColor:"#f6f8fa"},styles:[{types:["comment","prolog","doctype","cdata"],style:{color:"#999988",fontStyle:"italic"}},{types:["namespace"],style:{opacity:.7}},{types:["string","attr-value"],style:{color:"#e3116c"}},{types:["punctuation","operator"],style:{color:"#393A34"}},{types:["entity","url","symbol","number","boolean","variable","constant","property","regex","inserted"],style:{color:"#36acaa"}},{types:["atrule","keyword","attr-name","selector"],style:{color:"#00a4db"}},{types:["function","deleted","tag"],style:{color:"#d73a49"}},{types:["function-variable"],style:{color:"#6f42c1"}},{types:["tag","selector","keyword"],style:{color:"#00009f"}}]},darkTheme:{plain:{color:"#F8F8F2",backgroundColor:"#282A36"},styles:[{types:["prolog","constant","builtin"],style:{color:"rgb(189, 147, 249)"}},{types:["inserted","function"],style:{color:"rgb(80, 250, 123)"}},{types:["deleted"],style:{color:"rgb(255, 85, 85)"}},{types:["changed"],style:{color:"rgb(255, 184, 108)"}},{types:["punctuation","symbol"],style:{color:"rgb(248, 248, 242)"}},{types:["string","char","tag","selector"],style:{color:"rgb(255, 121, 198)"}},{types:["keyword","variable"],style:{color:"rgb(189, 147, 249)",fontStyle:"italic"}},{types:["comment"],style:{color:"rgb(98, 114, 164)"}},{types:["attr-name"],style:{color:"rgb(241, 250, 140)"}}]},additionalLanguages:["rust","toml"],magicComments:[{className:"theme-code-block-highlighted-line",line:"highlight-next-line",block:{start:"highlight-start",end:"highlight-end"}}]},docs:{versionPersistence:"localStorage",sidebar:{hideable:!1,autoCollapseCategories:!1}},metadata:[],tableOfContents:{minHeadingLevel:2,maxHeadingLevel:3}},baseUrlIssueBanner:!0,onDuplicateRoutes:"warn",staticDirectories:["static"],customFields:{},plugins:[],themes:[],scripts:[],headTags:[],stylesheets:[],clientModules:[],titleDelimiter:"|",noIndex:!1,markdown:{mermaid:!1}}},7462:(e,t,n)=>{"use strict";function a(){return a=Object.assign?Object.assign.bind():function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var a in n)Object.prototype.hasOwnProperty.call(n,a)&&(e[a]=n[a])}return e},a.apply(this,arguments)}n.d(t,{Z:()=>a})},5068:(e,t,n)=>{"use strict";function a(e,t){return a=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(e,t){return e.__proto__=t,e},a(e,t)}function r(e,t){e.prototype=Object.create(t.prototype),e.prototype.constructor=e,a(e,t)}n.d(t,{Z:()=>r})},3366:(e,t,n)=>{"use strict";function a(e,t){if(null==e)return{};var n,a,r={},o=Object.keys(e);for(a=0;a<o.length;a++)n=o[a],t.indexOf(n)>=0||(r[n]=e[n]);return r}n.d(t,{Z:()=>a})},8776:(e,t,n)=>{"use strict";n.d(t,{Z:()=>o});var a=!0,r="Invariant failed";function o(e,t){if(!e){if(a)throw new Error(r);var n="function"==typeof t?t():t,o=n?"".concat(r,": ").concat(n):r;throw new Error(o)}}},7529:e=>{"use strict";e.exports={}},6887:e=>{"use strict";e.exports=JSON.parse('{"/docs/dev/blog-9f6":{"__comp":"a6aa9e1f","__context":{"plugin":"1c41eae2"},"sidebar":"814f3328","items":[{"content":"20e2ece2"},{"content":"5058a078"},{"content":"8417e7a5"},{"content":"23f93eeb"}],"metadata":"81cb5929"},"/docs/dev/blog/archive-f0a":{"__comp":"9e4087bc","__context":{"plugin":"1c41eae2"},"archive":"b1f622a1"},"/docs/dev/blog/breaking-the-boundary-between-sql-and-nosql-150":{"__comp":"ccc49370","__context":{"plugin":"1c41eae2"},"sidebar":"814f3328","content":"7d170ab0"},"/docs/dev/blog/release-v0.14-d1b":{"__comp":"ccc49370","__context":{"plugin":"1c41eae2"},"sidebar":"814f3328","content":"234733fd"},"/docs/dev/blog/revolutionizing-databases-by-unifying-query-interfaces-c88":{"__comp":"ccc49370","__context":{"plugin":"1c41eae2"},"sidebar":"814f3328","content":"772fc39d"},"/docs/dev/blog/tags-946":{"__comp":"01a85c17","__context":{"plugin":"1c41eae2"},"sidebar":"814f3328","tags":"89739c9f"},"/docs/dev/blog/tags/automation-7a5":{"__comp":"6875c492","__context":{"plugin":"1c41eae2"},"sidebar":"814f3328","items":[{"content":"5058a078"}],"tag":"31f1dbb1","listMetadata":"2bed8b6f"},"/docs/dev/blog/tags/chat-gpt-65d":{"__comp":"6875c492","__context":{"plugin":"1c41eae2"},"sidebar":"814f3328","items":[{"content":"5058a078"}],"tag":"9624c11c","listMetadata":"db5d1fe1"},"/docs/dev/blog/tags/database-53f":{"__comp":"6875c492","__context":{"plugin":"1c41eae2"},"sidebar":"814f3328","items":[{"content":"20e2ece2"},{"content":"5058a078"},{"content":"8417e7a5"}],"tag":"9bbfd40a","listMetadata":"38a882bf"},"/docs/dev/blog/tags/documentation-7d2":{"__comp":"6875c492","__context":{"plugin":"1c41eae2"},"sidebar":"814f3328","items":[{"content":"5058a078"}],"tag":"79c85cd0","listMetadata":"93e7cfc5"},"/docs/dev/blog/tags/gluesql-22b":{"__comp":"6875c492","__context":{"plugin":"1c41eae2"},"sidebar":"814f3328","items":[{"content":"20e2ece2"}],"tag":"daad7c1d","listMetadata":"40386700"},"/docs/dev/blog/tags/nosql-582":{"__comp":"6875c492","__context":{"plugin":"1c41eae2"},"sidebar":"814f3328","items":[{"content":"8417e7a5"}],"tag":"768594c0","listMetadata":"0ccdbf16"},"/docs/dev/blog/tags/proposal-5c5":{"__comp":"6875c492","__context":{"plugin":"1c41eae2"},"sidebar":"814f3328","items":[{"content":"20e2ece2"}],"tag":"e519b4b4","listMetadata":"67002961"},"/docs/dev/blog/tags/query-interface-ee0":{"__comp":"6875c492","__context":{"plugin":"1c41eae2"},"sidebar":"814f3328","items":[{"content":"20e2ece2"}],"tag":"9d02ad31","listMetadata":"a6177d3d"},"/docs/dev/blog/tags/release-note-991":{"__comp":"6875c492","__context":{"plugin":"1c41eae2"},"sidebar":"814f3328","items":[{"content":"23f93eeb"}],"tag":"54df49be","listMetadata":"ee6dd1d2"},"/docs/dev/blog/tags/sql-959":{"__comp":"6875c492","__context":{"plugin":"1c41eae2"},"sidebar":"814f3328","items":[{"content":"8417e7a5"}],"tag":"65f7a26b","listMetadata":"ebfca923"},"/docs/dev/blog/tags/tdd-ff0":{"__comp":"6875c492","__context":{"plugin":"1c41eae2"},"sidebar":"814f3328","items":[{"content":"5058a078"}],"tag":"153137de","listMetadata":"dc5cc32c"},"/docs/dev/blog/tags/test-driven-documentation-fcc":{"__comp":"6875c492","__context":{"plugin":"1c41eae2"},"sidebar":"814f3328","items":[{"content":"5058a078"}],"tag":"f81fb924","listMetadata":"77b9a1ed"},"/docs/dev/blog/tags/v-0-14-b4d":{"__comp":"6875c492","__context":{"plugin":"1c41eae2"},"sidebar":"814f3328","items":[{"content":"23f93eeb"}],"tag":"9017a27d","listMetadata":"65722401"},"/docs/dev/blog/test-driven-documentation-af8":{"__comp":"ccc49370","__context":{"plugin":"1c41eae2"},"sidebar":"814f3328","content":"25196878"},"/docs/dev/-d5f":{"__comp":"1be78505","__context":{"plugin":"1e4e1fb6"},"versionMetadata":"935f2afb"},"/docs/dev/-666":{"__comp":"17896441","content":"c377a04b"},"/docs/dev/ast-builder/expressions/conditional-32d":{"__comp":"17896441","content":"a4bc1622"},"/docs/dev/ast-builder/expressions/nested-dcd":{"__comp":"17896441","content":"5df6e7df"},"/docs/dev/ast-builder/expressions/operator-based-172":{"__comp":"17896441","content":"44954150"},"/docs/dev/ast-builder/expressions/pattern-matching-8b6":{"__comp":"17896441","content":"2b265210"},"/docs/dev/ast-builder/expressions/value-checking-c44":{"__comp":"17896441","content":"b6bceaff"},"/docs/dev/ast-builder/functions/date-&-time/conversion-bf0":{"__comp":"17896441","content":"acfabe81"},"/docs/dev/ast-builder/functions/date-&-time/current-date-and-time-16a":{"__comp":"17896441","content":"8c7569e5"},"/docs/dev/ast-builder/functions/date-&-time/date-and-time-extraction-273":{"__comp":"17896441","content":"7ea7f008"},"/docs/dev/ast-builder/functions/date-&-time/formatting-b9b":{"__comp":"17896441","content":"463dc00f"},"/docs/dev/ast-builder/functions/geometry/coordinate-extraction-5d6":{"__comp":"17896441","content":"f6ca3de5"},"/docs/dev/ast-builder/functions/geometry/distance-calculation-900":{"__comp":"17896441","content":"89fc5f00"},"/docs/dev/ast-builder/functions/geometry/point-creation-1a3":{"__comp":"17896441","content":"a6b6486c"},"/docs/dev/ast-builder/functions/list-&-map/list-and-map-concatenation-35b":{"__comp":"17896441","content":"81bf07f5"},"/docs/dev/ast-builder/functions/list-&-map/list-manipulation-2cf":{"__comp":"17896441","content":"a2ab2bad"},"/docs/dev/ast-builder/functions/math/basic-arithmetic-f0a":{"__comp":"17896441","content":"9c5158ac"},"/docs/dev/ast-builder/functions/math/conversion-7c8":{"__comp":"17896441","content":"02aa4531"},"/docs/dev/ast-builder/functions/math/logarithmic-and-exponential-fb1":{"__comp":"17896441","content":"980f8d5e"},"/docs/dev/ast-builder/functions/math/rounding-7ca":{"__comp":"17896441","content":"1ce64703"},"/docs/dev/ast-builder/functions/math/special-mathematical-3ee":{"__comp":"17896441","content":"89196f72"},"/docs/dev/ast-builder/functions/math/trigonometric-29b":{"__comp":"17896441","content":"c5e834bc"},"/docs/dev/ast-builder/functions/others/null-handling-948":{"__comp":"17896441","content":"078a6308"},"/docs/dev/ast-builder/functions/others/type-conversion-a77":{"__comp":"17896441","content":"26c0a43c"},"/docs/dev/ast-builder/functions/others/unique-identifier-0a6":{"__comp":"17896441","content":"d5aa49f9"},"/docs/dev/ast-builder/functions/text/case-conversion-605":{"__comp":"17896441","content":"d7a493e6"},"/docs/dev/ast-builder/functions/text/character-conversion-919":{"__comp":"17896441","content":"3cfbc8af"},"/docs/dev/ast-builder/functions/text/padding-7b6":{"__comp":"17896441","content":"07294b24"},"/docs/dev/ast-builder/functions/text/position-and-indexing-1ed":{"__comp":"17896441","content":"f9553497"},"/docs/dev/ast-builder/functions/text/text-manipulation-762":{"__comp":"17896441","content":"1cdac986"},"/docs/dev/ast-builder/functions/text/trimming-63b":{"__comp":"17896441","content":"02bfc02d"},"/docs/dev/ast-builder/intro-06b":{"__comp":"17896441","content":"4add0c6c"},"/docs/dev/ast-builder/statements/data-manipulation/deleting-data-9f7":{"__comp":"17896441","content":"376759eb"},"/docs/dev/ast-builder/statements/data-manipulation/inserting-data-83e":{"__comp":"17896441","content":"bac2c42d"},"/docs/dev/ast-builder/statements/data-manipulation/updating-data-6c8":{"__comp":"17896441","content":"037683de"},"/docs/dev/ast-builder/statements/querying/creating-derived-subqueries-f4d":{"__comp":"17896441","content":"017e736e"},"/docs/dev/ast-builder/statements/querying/data-aggregation-5f9":{"__comp":"17896441","content":"b3de9677"},"/docs/dev/ast-builder/statements/querying/data-injection-a84":{"__comp":"17896441","content":"4be897c9"},"/docs/dev/ast-builder/statements/querying/data-joining-2c0":{"__comp":"17896441","content":"e5f53749"},"/docs/dev/ast-builder/statements/querying/data-selection-and-projection-34f":{"__comp":"17896441","content":"f914cfe8"},"/docs/dev/ast-builder/statements/querying/data-sorting-and-limiting-234":{"__comp":"17896441","content":"16815c2a"},"/docs/dev/ast-builder/statements/querying/fetching-data-from-storage-b2e":{"__comp":"17896441","content":"ee244d12"},"/docs/dev/ast-builder/statements/querying/using-preloaded-data-35f":{"__comp":"17896441","content":"d97b7d4d"},"/docs/dev/getting-started/cli-f3c":{"__comp":"17896441","content":"1c93e70c"},"/docs/dev/getting-started/javascript-web-ae6":{"__comp":"17896441","content":"e10f7c24"},"/docs/dev/getting-started/nodejs-37e":{"__comp":"17896441","content":"01a12966"},"/docs/dev/getting-started/rust-3fc":{"__comp":"17896441","content":"72c409f7"},"/docs/dev/sql-syntax/data-types/boolean-c7f":{"__comp":"17896441","content":"e68f8ad6"},"/docs/dev/sql-syntax/data-types/bytea-ed8":{"__comp":"17896441","content":"1798d0b3"},"/docs/dev/sql-syntax/data-types/date-612":{"__comp":"17896441","content":"a5971d1a"},"/docs/dev/sql-syntax/data-types/decimal-3f2":{"__comp":"17896441","content":"0b621d16"},"/docs/dev/sql-syntax/data-types/float-f0c":{"__comp":"17896441","content":"f33f2c05"},"/docs/dev/sql-syntax/data-types/inet-5c7":{"__comp":"17896441","content":"a9e26133"},"/docs/dev/sql-syntax/data-types/integers-171":{"__comp":"17896441","content":"aa1cf9a2"},"/docs/dev/sql-syntax/data-types/interval-59c":{"__comp":"17896441","content":"6ff6e7c9"},"/docs/dev/sql-syntax/data-types/list-0c2":{"__comp":"17896441","content":"2c0d2b92"},"/docs/dev/sql-syntax/data-types/map-744":{"__comp":"17896441","content":"50818478"},"/docs/dev/sql-syntax/data-types/text-f2f":{"__comp":"17896441","content":"d077f377"},"/docs/dev/sql-syntax/data-types/time-66e":{"__comp":"17896441","content":"ff7b8d8e"},"/docs/dev/sql-syntax/data-types/timestamp-546":{"__comp":"17896441","content":"a8d11699"},"/docs/dev/sql-syntax/data-types/uuid-5fa":{"__comp":"17896441","content":"bfb64759"},"/docs/dev/sql-syntax/functions/datetime/extract-ae9":{"__comp":"17896441","content":"4f675ae9"},"/docs/dev/sql-syntax/functions/datetime/format-2c8":{"__comp":"17896441","content":"f18bbaf6"},"/docs/dev/sql-syntax/functions/datetime/now-93b":{"__comp":"17896441","content":"98306a23"},"/docs/dev/sql-syntax/functions/datetime/to-date-8b3":{"__comp":"17896441","content":"928a5d6f"},"/docs/dev/sql-syntax/functions/datetime/to-time-b6e":{"__comp":"17896441","content":"a7153b78"},"/docs/dev/sql-syntax/functions/datetime/to-timestamp-52a":{"__comp":"17896441","content":"c2e5ab4f"},"/docs/dev/sql-syntax/functions/geometry/calc-distance-e9f":{"__comp":"17896441","content":"aff456d7"},"/docs/dev/sql-syntax/functions/geometry/get-x-2ae":{"__comp":"17896441","content":"9a3e57da"},"/docs/dev/sql-syntax/functions/geometry/get-y-54a":{"__comp":"17896441","content":"2a4d41ed"},"/docs/dev/sql-syntax/functions/geometry/point-12a":{"__comp":"17896441","content":"1a3daba8"},"/docs/dev/sql-syntax/functions/list-map/append-be2":{"__comp":"17896441","content":"0c18287f"},"/docs/dev/sql-syntax/functions/list-map/concat-cc9":{"__comp":"17896441","content":"cf518063"},"/docs/dev/sql-syntax/functions/list-map/prepend-7d8":{"__comp":"17896441","content":"77cc432a"},"/docs/dev/sql-syntax/functions/list-map/splice-d4b":{"__comp":"17896441","content":"4d9df5b1"},"/docs/dev/sql-syntax/functions/math/abs-b85":{"__comp":"17896441","content":"5a8c7729"},"/docs/dev/sql-syntax/functions/math/acos-ec1":{"__comp":"17896441","content":"6ba4a510"},"/docs/dev/sql-syntax/functions/math/asin-c78":{"__comp":"17896441","content":"68c17ba1"},"/docs/dev/sql-syntax/functions/math/atan-ad0":{"__comp":"17896441","content":"ba43b2d5"},"/docs/dev/sql-syntax/functions/math/ceil-0d5":{"__comp":"17896441","content":"56ccfc32"},"/docs/dev/sql-syntax/functions/math/cos-8ae":{"__comp":"17896441","content":"2f7bd5c8"},"/docs/dev/sql-syntax/functions/math/degrees-e0e":{"__comp":"17896441","content":"c97e0540"},"/docs/dev/sql-syntax/functions/math/div-048":{"__comp":"17896441","content":"920bdc78"},"/docs/dev/sql-syntax/functions/math/exp-a31":{"__comp":"17896441","content":"faca410e"},"/docs/dev/sql-syntax/functions/math/floor-03a":{"__comp":"17896441","content":"1b8ca8c3"},"/docs/dev/sql-syntax/functions/math/gcd-f38":{"__comp":"17896441","content":"cdaafcc9"},"/docs/dev/sql-syntax/functions/math/lcm-1c7":{"__comp":"17896441","content":"e4f709d1"},"/docs/dev/sql-syntax/functions/math/ln-700":{"__comp":"17896441","content":"ae3eef3e"},"/docs/dev/sql-syntax/functions/math/log-4e6":{"__comp":"17896441","content":"db0d9cb2"},"/docs/dev/sql-syntax/functions/math/log10-09d":{"__comp":"17896441","content":"afebe5f1"},"/docs/dev/sql-syntax/functions/math/log2-204":{"__comp":"17896441","content":"f1257df2"},"/docs/dev/sql-syntax/functions/math/mod-1fe":{"__comp":"17896441","content":"4a9d0f4c"},"/docs/dev/sql-syntax/functions/math/pi-4b0":{"__comp":"17896441","content":"eceb3b9b"},"/docs/dev/sql-syntax/functions/math/power-a7d":{"__comp":"17896441","content":"a7e6874c"},"/docs/dev/sql-syntax/functions/math/radians-09d":{"__comp":"17896441","content":"160faf1d"},"/docs/dev/sql-syntax/functions/math/rand-5c1":{"__comp":"17896441","content":"385623dc"},"/docs/dev/sql-syntax/functions/math/round-73f":{"__comp":"17896441","content":"7e0ce508"},"/docs/dev/sql-syntax/functions/math/sign-da7":{"__comp":"17896441","content":"6870612e"},"/docs/dev/sql-syntax/functions/math/sin-98d":{"__comp":"17896441","content":"9a1c8bc6"},"/docs/dev/sql-syntax/functions/math/sqrt-d79":{"__comp":"17896441","content":"5242ac2d"},"/docs/dev/sql-syntax/functions/math/tan-a32":{"__comp":"17896441","content":"85afcbde"},"/docs/dev/sql-syntax/functions/others/cast-5c2":{"__comp":"17896441","content":"bb43b8ce"},"/docs/dev/sql-syntax/functions/others/generate-uuid-7ff":{"__comp":"17896441","content":"0ea64360"},"/docs/dev/sql-syntax/functions/others/ifnull-bfe":{"__comp":"17896441","content":"fa5466f2"},"/docs/dev/sql-syntax/functions/text/ascii-6f0":{"__comp":"17896441","content":"e06425d1"},"/docs/dev/sql-syntax/functions/text/chr-791":{"__comp":"17896441","content":"8cf2dd9c"},"/docs/dev/sql-syntax/functions/text/concat-2d3":{"__comp":"17896441","content":"a470b55c"},"/docs/dev/sql-syntax/functions/text/concat-ws-7cc":{"__comp":"17896441","content":"c5b25a7c"},"/docs/dev/sql-syntax/functions/text/find-idx-e63":{"__comp":"17896441","content":"d4251823"},"/docs/dev/sql-syntax/functions/text/initcap-d0b":{"__comp":"17896441","content":"06322d53"},"/docs/dev/sql-syntax/functions/text/left-6d7":{"__comp":"17896441","content":"dafe2799"},"/docs/dev/sql-syntax/functions/text/lower-913":{"__comp":"17896441","content":"81f6aa2c"},"/docs/dev/sql-syntax/functions/text/lpad-832":{"__comp":"17896441","content":"97081ee7"},"/docs/dev/sql-syntax/functions/text/ltrim-076":{"__comp":"17896441","content":"007e0817"},"/docs/dev/sql-syntax/functions/text/position-184":{"__comp":"17896441","content":"15868c40"},"/docs/dev/sql-syntax/functions/text/repeat-6c9":{"__comp":"17896441","content":"b57ca7d5"},"/docs/dev/sql-syntax/functions/text/reverse-007":{"__comp":"17896441","content":"ae967838"},"/docs/dev/sql-syntax/functions/text/right-f07":{"__comp":"17896441","content":"5eabd930"},"/docs/dev/sql-syntax/functions/text/rpad-93e":{"__comp":"17896441","content":"7457c448"},"/docs/dev/sql-syntax/functions/text/rtrim-e76":{"__comp":"17896441","content":"c9d1eb08"},"/docs/dev/sql-syntax/functions/text/substr-d8c":{"__comp":"17896441","content":"d8746e52"},"/docs/dev/sql-syntax/functions/text/trim-ce4":{"__comp":"17896441","content":"41718851"},"/docs/dev/sql-syntax/functions/text/upper-6b6":{"__comp":"17896441","content":"b7661aba"},"/docs/dev/sql-syntax/intro-d94":{"__comp":"17896441","content":"31526b20"},"/docs/dev/sql-syntax/statements/data-definition/alter-table-259":{"__comp":"17896441","content":"0c94c658"},"/docs/dev/sql-syntax/statements/data-definition/create-index-ba4":{"__comp":"17896441","content":"0544f90b"},"/docs/dev/sql-syntax/statements/data-definition/create-table-9fd":{"__comp":"17896441","content":"86a1f821"},"/docs/dev/sql-syntax/statements/data-definition/drop-index-69c":{"__comp":"17896441","content":"4aa001c0"},"/docs/dev/sql-syntax/statements/data-definition/drop-table-f80":{"__comp":"17896441","content":"402da695"},"/docs/dev/sql-syntax/statements/data-manipulation/delete-927":{"__comp":"17896441","content":"92dd0956"},"/docs/dev/sql-syntax/statements/data-manipulation/insert-10a":{"__comp":"17896441","content":"df2eb7da"},"/docs/dev/sql-syntax/statements/data-manipulation/update-967":{"__comp":"17896441","content":"8be9dc67"},"/docs/dev/sql-syntax/statements/metadata/data-dictionary-114":{"__comp":"17896441","content":"6c5232c2"},"/docs/dev/sql-syntax/statements/metadata/show-tables-1bf":{"__comp":"17896441","content":"c30ee527"},"/docs/dev/sql-syntax/statements/querying/aggregation-5df":{"__comp":"17896441","content":"3245f64b"},"/docs/dev/sql-syntax/statements/querying/join-796":{"__comp":"17896441","content":"dc8f2f6c"},"/docs/dev/sql-syntax/statements/querying/limit-762":{"__comp":"17896441","content":"b7da1136"},"/docs/dev/sql-syntax/statements/querying/schemaless-afa":{"__comp":"17896441","content":"7310a4fe"},"/docs/dev/sql-syntax/statements/querying/where-bb5":{"__comp":"17896441","content":"2d9479c4"},"/docs/dev/sql-syntax/statements/transaction-411":{"__comp":"17896441","content":"e158c27a"},"/docs/dev/storages/developing-custom-storages/intro-c6d":{"__comp":"17896441","content":"c251e734"},"/docs/dev/storages/developing-custom-storages/store-traits/alter-table-4c5":{"__comp":"17896441","content":"194e858c"},"/docs/dev/storages/developing-custom-storages/store-traits/custom-function-e5b":{"__comp":"17896441","content":"83b912d4"},"/docs/dev/storages/developing-custom-storages/store-traits/custom-function-mut-0cc":{"__comp":"17896441","content":"44f79c8d"},"/docs/dev/storages/developing-custom-storages/store-traits/index-mut-78f":{"__comp":"17896441","content":"5cdfb1f2"},"/docs/dev/storages/developing-custom-storages/store-traits/index-trait-aa3":{"__comp":"17896441","content":"d941076d"},"/docs/dev/storages/developing-custom-storages/store-traits/metadata-2a5":{"__comp":"17896441","content":"e329d2fa"},"/docs/dev/storages/developing-custom-storages/store-traits/store-262":{"__comp":"17896441","content":"482a391c"},"/docs/dev/storages/developing-custom-storages/store-traits/store-mut-853":{"__comp":"17896441","content":"ebe12d94"},"/docs/dev/storages/developing-custom-storages/store-traits/transaction-bd7":{"__comp":"17896441","content":"488157d7"},"/docs/dev/storages/developing-custom-storages/using-test-suite-a37":{"__comp":"17896441","content":"345c600d"},"/docs/dev/storages/intro-8d9":{"__comp":"17896441","content":"b209ab8a"},"/docs/dev/storages/supported-storages/composite-storage-93e":{"__comp":"17896441","content":"67d1434e"},"/docs/dev/storages/supported-storages/idb-storage-787":{"__comp":"17896441","content":"952dfacb"},"/docs/dev/storages/supported-storages/json-storage-207":{"__comp":"17896441","content":"3961e600"},"/docs/dev/storages/supported-storages/memory-storage-695":{"__comp":"17896441","content":"6e772156"},"/docs/dev/storages/supported-storages/shared-memory-storage-418":{"__comp":"17896441","content":"e46b95eb"},"/docs/dev/storages/supported-storages/sled-storage-fb0":{"__comp":"17896441","content":"8d6e802b"},"/docs/dev/storages/supported-storages/web-storage-14a":{"__comp":"17896441","content":"edb9b0b8"}}')}},e=>{e.O(0,[532],(()=>{return t=7221,e(e.s=t);var t}));e.O()}]); \ No newline at end of file diff --git a/docs/dev/assets/js/main.70215770.js.LICENSE.txt b/docs/dev/assets/js/main.6ac6dfb4.js.LICENSE.txt similarity index 100% rename from docs/dev/assets/js/main.70215770.js.LICENSE.txt rename to docs/dev/assets/js/main.6ac6dfb4.js.LICENSE.txt diff --git a/docs/dev/assets/js/main.70215770.js b/docs/dev/assets/js/main.70215770.js deleted file mode 100644 index f22d21e2..00000000 --- a/docs/dev/assets/js/main.70215770.js +++ /dev/null @@ -1,2 +0,0 @@ -/*! For license information please see main.70215770.js.LICENSE.txt */ -(self.webpackChunkdocs=self.webpackChunkdocs||[]).push([[179],{723:(e,t,n)=>{"use strict";n.d(t,{Z:()=>p});var a=n(7294),r=n(7462),o=n(8356),s=n.n(o),i=n(6887);const l={"007e0817":[()=>n.e(9063).then(n.bind(n,3212)),"@site/docs/sql-syntax/functions/text/ltrim.md",3212],"017e736e":[()=>n.e(6685).then(n.bind(n,8301)),"@site/docs/ast-builder/statements/querying/creating-derived-subqueries.md",8301],"01a12966":[()=>n.e(1965).then(n.bind(n,5498)),"@site/docs/getting-started/nodejs.md",5498],"01a85c17":[()=>Promise.all([n.e(532),n.e(4013)]).then(n.bind(n,1223)),"@theme/BlogTagsListPage",1223],"02aa4531":[()=>n.e(5667).then(n.bind(n,2327)),"@site/docs/ast-builder/functions/math/conversion.md",2327],"02bfc02d":[()=>n.e(846).then(n.bind(n,488)),"@site/docs/ast-builder/functions/text/trimming.md",488],"037683de":[()=>n.e(7677).then(n.bind(n,1330)),"@site/docs/ast-builder/statements/data-manipulation/updating-data.md",1330],"0544f90b":[()=>n.e(9600).then(n.bind(n,8435)),"@site/docs/sql-syntax/statements/data-definition/create-index.md",8435],"06322d53":[()=>n.e(1279).then(n.bind(n,9837)),"@site/docs/sql-syntax/functions/text/initcap.md",9837],"07294b24":[()=>n.e(3726).then(n.bind(n,7785)),"@site/docs/ast-builder/functions/text/padding.md",7785],"078a6308":[()=>n.e(3554).then(n.bind(n,7765)),"@site/docs/ast-builder/functions/others/null-handling.md",7765],"0b621d16":[()=>n.e(7462).then(n.bind(n,3701)),"@site/docs/sql-syntax/data-types/decimal.md",3701],"0c18287f":[()=>n.e(3475).then(n.bind(n,194)),"@site/docs/sql-syntax/functions/list-map/append.md",194],"0c94c658":[()=>n.e(3454).then(n.bind(n,141)),"@site/docs/sql-syntax/statements/data-definition/alter-table.md",141],"0ccdbf16":[()=>n.e(5315).then(n.t.bind(n,2853,19)),"~blog/default/docs-dev-blog-tags-nosql-50f-list.json",2853],"0ea64360":[()=>n.e(3372).then(n.bind(n,9767)),"@site/docs/sql-syntax/functions/others/generate-uuid.md",9767],"153137de":[()=>n.e(6199).then(n.t.bind(n,3163,19)),"~blog/default/docs-dev-blog-tags-tdd-09c.json",3163],"15868c40":[()=>n.e(689).then(n.bind(n,8337)),"@site/docs/sql-syntax/functions/text/position.md",8337],"160faf1d":[()=>n.e(2365).then(n.bind(n,2629)),"@site/docs/sql-syntax/functions/math/radians.md",2629],"16815c2a":[()=>n.e(3371).then(n.bind(n,1118)),"@site/docs/ast-builder/statements/querying/data-sorting-and-limiting.md",1118],17896441:[()=>Promise.all([n.e(532),n.e(9785),n.e(7918)]).then(n.bind(n,8945)),"@theme/DocItem",8945],"1798d0b3":[()=>n.e(4046).then(n.bind(n,4872)),"@site/docs/sql-syntax/data-types/bytea.md",4872],"194e858c":[()=>n.e(2305).then(n.bind(n,2507)),"@site/docs/storages/developing-custom-storages/store-traits/alter-table.md",2507],"1a3daba8":[()=>n.e(4945).then(n.bind(n,3711)),"@site/docs/sql-syntax/functions/geometry/point.md",3711],"1b8ca8c3":[()=>n.e(9147).then(n.bind(n,6781)),"@site/docs/sql-syntax/functions/math/floor.md",6781],"1be78505":[()=>Promise.all([n.e(532),n.e(9514)]).then(n.bind(n,9963)),"@theme/DocPage",9963],"1c41eae2":[()=>n.e(4450).then(n.t.bind(n,4469,19)),"/home/runner/work/gluesql/gluesql/docs/.docusaurus/docusaurus-plugin-content-blog/default/plugin-route-context-module-100.json",4469],"1c93e70c":[()=>n.e(8506).then(n.bind(n,5429)),"@site/docs/getting-started/cli.md",5429],"1cdac986":[()=>n.e(2215).then(n.bind(n,5878)),"@site/docs/ast-builder/functions/text/text-manipulation.md",5878],"1ce64703":[()=>n.e(3337).then(n.bind(n,9782)),"@site/docs/ast-builder/functions/math/rounding.md",9782],"1e4e1fb6":[()=>n.e(4909).then(n.t.bind(n,3769,19)),"/home/runner/work/gluesql/gluesql/docs/.docusaurus/docusaurus-plugin-content-docs/default/plugin-route-context-module-100.json",3769],"20e2ece2":[()=>n.e(4785).then(n.bind(n,3700)),"@site/blog/2023-05-30-revolutionizing-databases-by-unifying-query-interfaces.md?truncated=true",3700],"234733fd":[()=>n.e(3188).then(n.bind(n,2830)),"@site/blog/2023-05-27-release-v0.14.md",2830],"23f93eeb":[()=>n.e(7793).then(n.bind(n,6064)),"@site/blog/2023-05-27-release-v0.14.md?truncated=true",6064],25196878:[()=>n.e(1395).then(n.bind(n,1737)),"@site/blog/2023-05-30-test-driven-documentation.md",1737],"26c0a43c":[()=>n.e(7785).then(n.bind(n,6693)),"@site/docs/ast-builder/functions/others/type-conversion.md",6693],"2a4d41ed":[()=>n.e(4004).then(n.bind(n,3386)),"@site/docs/sql-syntax/functions/geometry/get-y.md",3386],"2b265210":[()=>n.e(8142).then(n.bind(n,389)),"@site/docs/ast-builder/expressions/pattern-matching.md",389],"2bed8b6f":[()=>n.e(127).then(n.t.bind(n,3194,19)),"~blog/default/docs-dev-blog-tags-automation-99a-list.json",3194],"2c0d2b92":[()=>n.e(5944).then(n.bind(n,4557)),"@site/docs/sql-syntax/data-types/list.md",4557],"2d9479c4":[()=>n.e(2809).then(n.bind(n,7885)),"@site/docs/sql-syntax/statements/querying/where.md",7885],"2f7bd5c8":[()=>n.e(3058).then(n.bind(n,104)),"@site/docs/sql-syntax/functions/math/cos.md",104],"31526b20":[()=>n.e(9020).then(n.bind(n,6947)),"@site/docs/sql-syntax/intro.md",6947],"31f1dbb1":[()=>n.e(9903).then(n.t.bind(n,1873,19)),"~blog/default/docs-dev-blog-tags-automation-99a.json",1873],"3245f64b":[()=>n.e(6132).then(n.bind(n,3427)),"@site/docs/sql-syntax/statements/querying/aggregation.md",3427],"345c600d":[()=>n.e(1375).then(n.bind(n,160)),"@site/docs/storages/developing-custom-storages/using-test-suite.md",160],"376759eb":[()=>n.e(16).then(n.bind(n,7484)),"@site/docs/ast-builder/statements/data-manipulation/deleting-data.md",7484],"385623dc":[()=>n.e(9643).then(n.bind(n,2621)),"@site/docs/sql-syntax/functions/math/rand.md",2621],"38a882bf":[()=>n.e(9667).then(n.t.bind(n,802,19)),"~blog/default/docs-dev-blog-tags-database-f6d-list.json",802],"3961e600":[()=>n.e(2842).then(n.bind(n,9085)),"@site/docs/storages/supported-storages/json-storage.md",9085],"3cfbc8af":[()=>n.e(2691).then(n.bind(n,4207)),"@site/docs/ast-builder/functions/text/character-conversion.md",4207],"402da695":[()=>n.e(5682).then(n.bind(n,1138)),"@site/docs/sql-syntax/statements/data-definition/drop-table.md",1138],40386700:[()=>n.e(9695).then(n.t.bind(n,2918,19)),"~blog/default/docs-dev-blog-tags-gluesql-5e6-list.json",2918],41718851:[()=>n.e(4244).then(n.bind(n,4245)),"@site/docs/sql-syntax/functions/text/trim.md",4245],44954150:[()=>n.e(3357).then(n.bind(n,8055)),"@site/docs/ast-builder/expressions/operator-based.md",8055],"44f79c8d":[()=>n.e(7123).then(n.bind(n,8261)),"@site/docs/storages/developing-custom-storages/store-traits/custom-function-mut.md",8261],"463dc00f":[()=>n.e(4538).then(n.bind(n,5730)),"@site/docs/ast-builder/functions/date-&-time/formatting.md",5730],"482a391c":[()=>n.e(6508).then(n.bind(n,4364)),"@site/docs/storages/developing-custom-storages/store-traits/store.md",4364],"488157d7":[()=>n.e(9162).then(n.bind(n,2138)),"@site/docs/storages/developing-custom-storages/store-traits/transaction.md",2138],"4a9d0f4c":[()=>n.e(7385).then(n.bind(n,2741)),"@site/docs/sql-syntax/functions/math/mod.md",2741],"4aa001c0":[()=>n.e(1003).then(n.bind(n,2308)),"@site/docs/sql-syntax/statements/data-definition/drop-index.md",2308],"4add0c6c":[()=>n.e(9132).then(n.bind(n,5311)),"@site/docs/ast-builder/intro.md",5311],"4be897c9":[()=>n.e(6741).then(n.bind(n,5066)),"@site/docs/ast-builder/statements/querying/data-injection.md",5066],"4f675ae9":[()=>n.e(7233).then(n.bind(n,1046)),"@site/docs/sql-syntax/functions/datetime/extract.md",1046],"5058a078":[()=>n.e(4746).then(n.bind(n,1822)),"@site/blog/2023-05-30-test-driven-documentation.md?truncated=true",1822],50818478:[()=>n.e(6094).then(n.bind(n,918)),"@site/docs/sql-syntax/data-types/map.md",918],"5242ac2d":[()=>n.e(3317).then(n.bind(n,4871)),"@site/docs/sql-syntax/functions/math/sqrt.md",4871],"54df49be":[()=>n.e(3575).then(n.t.bind(n,5625,19)),"~blog/default/docs-dev-blog-tags-release-note-9fd.json",5625],"56ccfc32":[()=>n.e(7194).then(n.bind(n,1710)),"@site/docs/sql-syntax/functions/math/ceil.md",1710],"5a8c7729":[()=>n.e(3004).then(n.bind(n,8869)),"@site/docs/sql-syntax/functions/math/abs.md",8869],"5cdfb1f2":[()=>n.e(7486).then(n.bind(n,4094)),"@site/docs/storages/developing-custom-storages/store-traits/index-mut.md",4094],"5df6e7df":[()=>n.e(9978).then(n.bind(n,583)),"@site/docs/ast-builder/expressions/nested.md",583],"5eabd930":[()=>n.e(5558).then(n.bind(n,3398)),"@site/docs/sql-syntax/functions/text/right.md",3398],65722401:[()=>n.e(7513).then(n.t.bind(n,8354,19)),"~blog/default/docs-dev-blog-tags-v-0-14-0b1-list.json",8354],"65f7a26b":[()=>n.e(9760).then(n.t.bind(n,7968,19)),"~blog/default/docs-dev-blog-tags-sql-e5f.json",7968],67002961:[()=>n.e(4875).then(n.t.bind(n,1679,19)),"~blog/default/docs-dev-blog-tags-proposal-ab6-list.json",1679],"67d1434e":[()=>n.e(9502).then(n.bind(n,9e3)),"@site/docs/storages/supported-storages/composite-storage.md",9e3],"6870612e":[()=>n.e(1827).then(n.bind(n,6775)),"@site/docs/sql-syntax/functions/math/sign.md",6775],"6875c492":[()=>Promise.all([n.e(532),n.e(9785),n.e(6048),n.e(8610)]).then(n.bind(n,1714)),"@theme/BlogTagsPostsPage",1714],"68c17ba1":[()=>n.e(2616).then(n.bind(n,1)),"@site/docs/sql-syntax/functions/math/asin.md",1],"6ba4a510":[()=>n.e(7518).then(n.bind(n,4510)),"@site/docs/sql-syntax/functions/math/acos.md",4510],"6c5232c2":[()=>n.e(8599).then(n.bind(n,9242)),"@site/docs/sql-syntax/statements/metadata/data-dictionary.md",9242],"6e772156":[()=>n.e(8253).then(n.bind(n,889)),"@site/docs/storages/supported-storages/memory-storage.md",889],"6ff6e7c9":[()=>n.e(8215).then(n.bind(n,410)),"@site/docs/sql-syntax/data-types/interval.md",410],"72c409f7":[()=>n.e(5458).then(n.bind(n,955)),"@site/docs/getting-started/rust.md",955],"7310a4fe":[()=>n.e(2047).then(n.bind(n,9576)),"@site/docs/sql-syntax/statements/querying/schemaless.md",9576],"7457c448":[()=>n.e(4452).then(n.bind(n,8621)),"@site/docs/sql-syntax/functions/text/rpad.md",8621],"768594c0":[()=>n.e(3944).then(n.t.bind(n,2483,19)),"~blog/default/docs-dev-blog-tags-nosql-50f.json",2483],"772fc39d":[()=>n.e(3851).then(n.bind(n,1777)),"@site/blog/2023-05-30-revolutionizing-databases-by-unifying-query-interfaces.md",1777],"77b9a1ed":[()=>n.e(7062).then(n.t.bind(n,1303,19)),"~blog/default/docs-dev-blog-tags-test-driven-documentation-210-list.json",1303],"77cc432a":[()=>n.e(3159).then(n.bind(n,995)),"@site/docs/sql-syntax/functions/list-map/prepend.md",995],"79c85cd0":[()=>n.e(5962).then(n.t.bind(n,2284,19)),"~blog/default/docs-dev-blog-tags-documentation-32b.json",2284],"7d170ab0":[()=>n.e(1768).then(n.bind(n,7232)),"@site/blog/2023-05-29-breaking-the-boundary.md",7232],"7e0ce508":[()=>n.e(3394).then(n.bind(n,8233)),"@site/docs/sql-syntax/functions/math/round.md",8233],"7ea7f008":[()=>n.e(8905).then(n.bind(n,5338)),"@site/docs/ast-builder/functions/date-&-time/date-and-time-extraction.md",5338],"814f3328":[()=>n.e(2535).then(n.t.bind(n,5641,19)),"~blog/default/blog-post-list-prop-default.json",5641],"81bf07f5":[()=>n.e(3367).then(n.bind(n,227)),"@site/docs/ast-builder/functions/list-&-map/list-and-map-concatenation.md",227],"81cb5929":[()=>n.e(3193).then(n.t.bind(n,8232,19)),"~blog/default/docs-dev-blog-feb.json",8232],"81f6aa2c":[()=>n.e(5756).then(n.bind(n,2750)),"@site/docs/sql-syntax/functions/text/lower.md",2750],"83b912d4":[()=>n.e(7449).then(n.bind(n,6153)),"@site/docs/storages/developing-custom-storages/store-traits/custom-function.md",6153],"8417e7a5":[()=>n.e(3768).then(n.bind(n,9950)),"@site/blog/2023-05-29-breaking-the-boundary.md?truncated=true",9950],"85afcbde":[()=>n.e(3390).then(n.bind(n,8475)),"@site/docs/sql-syntax/functions/math/tan.md",8475],"86a1f821":[()=>n.e(9992).then(n.bind(n,603)),"@site/docs/sql-syntax/statements/data-definition/create-table.md",603],"89196f72":[()=>n.e(7219).then(n.bind(n,9571)),"@site/docs/ast-builder/functions/math/special-mathematical.md",9571],"89739c9f":[()=>n.e(6350).then(n.t.bind(n,4943,19)),"~blog/default/docs-dev-blog-tags-tags-74b.json",4943],"89fc5f00":[()=>n.e(2627).then(n.bind(n,6897)),"@site/docs/ast-builder/functions/geometry/distance-calculation.md",6897],"8be9dc67":[()=>n.e(3905).then(n.bind(n,6323)),"@site/docs/sql-syntax/statements/data-manipulation/update.md",6323],"8c7569e5":[()=>n.e(5737).then(n.bind(n,8878)),"@site/docs/ast-builder/functions/date-&-time/current-date-and-time.md",8878],"8cf2dd9c":[()=>n.e(9722).then(n.bind(n,6571)),"@site/docs/sql-syntax/functions/text/chr.md",6571],"8d6e802b":[()=>n.e(5843).then(n.bind(n,7407)),"@site/docs/storages/supported-storages/sled-storage.md",7407],"9017a27d":[()=>n.e(1354).then(n.t.bind(n,9252,19)),"~blog/default/docs-dev-blog-tags-v-0-14-0b1.json",9252],"920bdc78":[()=>n.e(6669).then(n.bind(n,6014)),"@site/docs/sql-syntax/functions/math/div.md",6014],"928a5d6f":[()=>n.e(6489).then(n.bind(n,174)),"@site/docs/sql-syntax/functions/datetime/to-date.md",174],"92dd0956":[()=>n.e(104).then(n.bind(n,5729)),"@site/docs/sql-syntax/statements/data-manipulation/delete.md",5729],"935f2afb":[()=>n.e(53).then(n.t.bind(n,1109,19)),"~docs/default/version-current-metadata-prop-751.json",1109],"93e7cfc5":[()=>n.e(3704).then(n.t.bind(n,6428,19)),"~blog/default/docs-dev-blog-tags-documentation-32b-list.json",6428],"952dfacb":[()=>n.e(6155).then(n.bind(n,9783)),"@site/docs/storages/supported-storages/idb-storage.md",9783],"9624c11c":[()=>n.e(203).then(n.t.bind(n,5350,19)),"~blog/default/docs-dev-blog-tags-chat-gpt-3f4.json",5350],"97081ee7":[()=>n.e(3619).then(n.bind(n,4555)),"@site/docs/sql-syntax/functions/text/lpad.md",4555],"980f8d5e":[()=>n.e(7344).then(n.bind(n,4732)),"@site/docs/ast-builder/functions/math/logarithmic-and-exponential.md",4732],"98306a23":[()=>n.e(5123).then(n.bind(n,74)),"@site/docs/sql-syntax/functions/datetime/now.md",74],"9a1c8bc6":[()=>n.e(7669).then(n.bind(n,5401)),"@site/docs/sql-syntax/functions/math/sin.md",5401],"9a3e57da":[()=>n.e(8894).then(n.bind(n,3717)),"@site/docs/sql-syntax/functions/geometry/get-x.md",3717],"9bbfd40a":[()=>n.e(1788).then(n.t.bind(n,350,19)),"~blog/default/docs-dev-blog-tags-database-f6d.json",350],"9c5158ac":[()=>n.e(1470).then(n.bind(n,7984)),"@site/docs/ast-builder/functions/math/basic-arithmetic.md",7984],"9d02ad31":[()=>n.e(6017).then(n.t.bind(n,5288,19)),"~blog/default/docs-dev-blog-tags-query-interface-47d.json",5288],"9e4087bc":[()=>n.e(3608).then(n.bind(n,3169)),"@theme/BlogArchivePage",3169],a2ab2bad:[()=>n.e(1715).then(n.bind(n,420)),"@site/docs/ast-builder/functions/list-&-map/list-manipulation.md",420],a470b55c:[()=>n.e(6989).then(n.bind(n,2451)),"@site/docs/sql-syntax/functions/text/concat.md",2451],a4bc1622:[()=>n.e(1983).then(n.bind(n,4392)),"@site/docs/ast-builder/expressions/conditional.md",4392],a5971d1a:[()=>n.e(156).then(n.bind(n,4394)),"@site/docs/sql-syntax/data-types/date.md",4394],a6177d3d:[()=>n.e(9818).then(n.t.bind(n,5837,19)),"~blog/default/docs-dev-blog-tags-query-interface-47d-list.json",5837],a6aa9e1f:[()=>Promise.all([n.e(532),n.e(9785),n.e(6048),n.e(3089)]).then(n.bind(n,46)),"@theme/BlogListPage",46],a6b6486c:[()=>n.e(7839).then(n.bind(n,8954)),"@site/docs/ast-builder/functions/geometry/point-creation.md",8954],a7153b78:[()=>n.e(950).then(n.bind(n,3568)),"@site/docs/sql-syntax/functions/datetime/to-time.md",3568],a7e6874c:[()=>n.e(340).then(n.bind(n,3672)),"@site/docs/sql-syntax/functions/math/power.md",3672],a8d11699:[()=>n.e(5391).then(n.bind(n,9291)),"@site/docs/sql-syntax/data-types/timestamp.md",9291],a9e26133:[()=>n.e(2177).then(n.bind(n,119)),"@site/docs/sql-syntax/data-types/inet.md",119],aa1cf9a2:[()=>n.e(9986).then(n.bind(n,4596)),"@site/docs/sql-syntax/data-types/integers.md",4596],acfabe81:[()=>n.e(998).then(n.bind(n,6712)),"@site/docs/ast-builder/functions/date-&-time/conversion.md",6712],ae3eef3e:[()=>n.e(6212).then(n.bind(n,8173)),"@site/docs/sql-syntax/functions/math/ln.md",8173],ae967838:[()=>n.e(4561).then(n.bind(n,4712)),"@site/docs/sql-syntax/functions/text/reverse.md",4712],afebe5f1:[()=>n.e(636).then(n.bind(n,5353)),"@site/docs/sql-syntax/functions/math/log10.md",5353],aff456d7:[()=>n.e(1849).then(n.bind(n,8814)),"@site/docs/sql-syntax/functions/geometry/calc-distance.md",8814],b1f622a1:[()=>n.e(1452).then(n.t.bind(n,7731,19)),"~blog/default/docs-dev-blog-archive-c7c.json",7731],b209ab8a:[()=>n.e(5906).then(n.bind(n,8633)),"@site/docs/storages/intro.md",8633],b3de9677:[()=>n.e(6555).then(n.bind(n,8826)),"@site/docs/ast-builder/statements/querying/data-aggregation.md",8826],b57ca7d5:[()=>n.e(5297).then(n.bind(n,6093)),"@site/docs/sql-syntax/functions/text/repeat.md",6093],b6bceaff:[()=>n.e(3587).then(n.bind(n,6414)),"@site/docs/ast-builder/expressions/value-checking.md",6414],b7661aba:[()=>n.e(9054).then(n.bind(n,5512)),"@site/docs/sql-syntax/functions/text/upper.md",5512],b7da1136:[()=>n.e(3216).then(n.bind(n,9665)),"@site/docs/sql-syntax/statements/querying/limit.md",9665],ba43b2d5:[()=>n.e(7496).then(n.bind(n,3557)),"@site/docs/sql-syntax/functions/math/atan.md",3557],bac2c42d:[()=>n.e(1610).then(n.bind(n,2163)),"@site/docs/ast-builder/statements/data-manipulation/inserting-data.md",2163],bb43b8ce:[()=>n.e(7870).then(n.bind(n,7846)),"@site/docs/sql-syntax/functions/others/cast.md",7846],bfb64759:[()=>n.e(5401).then(n.bind(n,2576)),"@site/docs/sql-syntax/data-types/uuid.md",2576],c251e734:[()=>n.e(5952).then(n.bind(n,5423)),"@site/docs/storages/developing-custom-storages/intro.md",5423],c2e5ab4f:[()=>n.e(3151).then(n.bind(n,2906)),"@site/docs/sql-syntax/functions/datetime/to-timestamp.md",2906],c30ee527:[()=>n.e(9661).then(n.bind(n,3140)),"@site/docs/sql-syntax/statements/metadata/show-tables.md",3140],c377a04b:[()=>n.e(6971).then(n.bind(n,1269)),"@site/docs/index.md",1269],c5b25a7c:[()=>n.e(9266).then(n.bind(n,9027)),"@site/docs/sql-syntax/functions/text/concat-ws.md",9027],c5e834bc:[()=>n.e(9385).then(n.bind(n,6961)),"@site/docs/ast-builder/functions/math/trigonometric.md",6961],c97e0540:[()=>n.e(7332).then(n.bind(n,1745)),"@site/docs/sql-syntax/functions/math/degrees.md",1745],c9d1eb08:[()=>n.e(6448).then(n.bind(n,2218)),"@site/docs/sql-syntax/functions/text/rtrim.md",2218],ccc49370:[()=>Promise.all([n.e(532),n.e(9785),n.e(6048),n.e(6103)]).then(n.bind(n,5203)),"@theme/BlogPostPage",5203],cdaafcc9:[()=>n.e(1500).then(n.bind(n,4570)),"@site/docs/sql-syntax/functions/math/gcd.md",4570],cf518063:[()=>n.e(6979).then(n.bind(n,4077)),"@site/docs/sql-syntax/functions/list-map/concat.md",4077],d077f377:[()=>n.e(1929).then(n.bind(n,4119)),"@site/docs/sql-syntax/data-types/text.md",4119],d4251823:[()=>n.e(4176).then(n.bind(n,692)),"@site/docs/sql-syntax/functions/text/find-idx.md",692],d5aa49f9:[()=>n.e(7901).then(n.bind(n,8991)),"@site/docs/ast-builder/functions/others/unique-identifier.md",8991],d7a493e6:[()=>n.e(3020).then(n.bind(n,3270)),"@site/docs/ast-builder/functions/text/case-conversion.md",3270],d8746e52:[()=>n.e(8697).then(n.bind(n,4524)),"@site/docs/sql-syntax/functions/text/substr.md",4524],d941076d:[()=>n.e(8662).then(n.bind(n,483)),"@site/docs/storages/developing-custom-storages/store-traits/index-trait.md",483],d97b7d4d:[()=>n.e(9586).then(n.bind(n,1078)),"@site/docs/ast-builder/statements/querying/using-preloaded-data.md",1078],daad7c1d:[()=>n.e(2463).then(n.t.bind(n,7641,19)),"~blog/default/docs-dev-blog-tags-gluesql-5e6.json",7641],dafe2799:[()=>n.e(9616).then(n.bind(n,4674)),"@site/docs/sql-syntax/functions/text/left.md",4674],db0d9cb2:[()=>n.e(777).then(n.bind(n,6377)),"@site/docs/sql-syntax/functions/math/log.md",6377],db5d1fe1:[()=>n.e(6044).then(n.t.bind(n,2938,19)),"~blog/default/docs-dev-blog-tags-chat-gpt-3f4-list.json",2938],dc5cc32c:[()=>n.e(6186).then(n.t.bind(n,6354,19)),"~blog/default/docs-dev-blog-tags-tdd-09c-list.json",6354],dc8f2f6c:[()=>n.e(1164).then(n.bind(n,5008)),"@site/docs/sql-syntax/statements/querying/join.md",5008],df2eb7da:[()=>n.e(6694).then(n.bind(n,1443)),"@site/docs/sql-syntax/statements/data-manipulation/insert.md",1443],e06425d1:[()=>n.e(221).then(n.bind(n,7661)),"@site/docs/sql-syntax/functions/text/ascii.md",7661],e10f7c24:[()=>n.e(4213).then(n.bind(n,8438)),"@site/docs/getting-started/javascript-web.md",8438],e158c27a:[()=>n.e(5589).then(n.bind(n,652)),"@site/docs/sql-syntax/statements/transaction.md",652],e329d2fa:[()=>n.e(4792).then(n.bind(n,4908)),"@site/docs/storages/developing-custom-storages/store-traits/metadata.md",4908],e46b95eb:[()=>n.e(5085).then(n.bind(n,3564)),"@site/docs/storages/supported-storages/shared-memory-storage.md",3564],e4f709d1:[()=>n.e(6533).then(n.bind(n,5094)),"@site/docs/sql-syntax/functions/math/lcm.md",5094],e519b4b4:[()=>n.e(9101).then(n.t.bind(n,5588,19)),"~blog/default/docs-dev-blog-tags-proposal-ab6.json",5588],e5f53749:[()=>n.e(930).then(n.bind(n,8967)),"@site/docs/ast-builder/statements/querying/data-joining.md",8967],e68f8ad6:[()=>n.e(2988).then(n.bind(n,2149)),"@site/docs/sql-syntax/data-types/boolean.md",2149],ebe12d94:[()=>n.e(5889).then(n.bind(n,4980)),"@site/docs/storages/developing-custom-storages/store-traits/store-mut.md",4980],ebfca923:[()=>n.e(4637).then(n.t.bind(n,6893,19)),"~blog/default/docs-dev-blog-tags-sql-e5f-list.json",6893],eceb3b9b:[()=>n.e(8851).then(n.bind(n,8338)),"@site/docs/sql-syntax/functions/math/pi.md",8338],edb9b0b8:[()=>n.e(560).then(n.bind(n,5555)),"@site/docs/storages/supported-storages/web-storage.md",5555],ee244d12:[()=>n.e(1530).then(n.bind(n,1895)),"@site/docs/ast-builder/statements/querying/fetching-data-from-storage.md",1895],ee6dd1d2:[()=>n.e(4734).then(n.t.bind(n,4513,19)),"~blog/default/docs-dev-blog-tags-release-note-9fd-list.json",4513],f1257df2:[()=>n.e(7257).then(n.bind(n,6607)),"@site/docs/sql-syntax/functions/math/log2.md",6607],f18bbaf6:[()=>n.e(811).then(n.bind(n,1994)),"@site/docs/sql-syntax/functions/datetime/format.md",1994],f33f2c05:[()=>n.e(6470).then(n.bind(n,9276)),"@site/docs/sql-syntax/data-types/float.md",9276],f6ca3de5:[()=>n.e(4706).then(n.bind(n,4065)),"@site/docs/ast-builder/functions/geometry/coordinate-extraction.md",4065],f81fb924:[()=>n.e(438).then(n.t.bind(n,665,19)),"~blog/default/docs-dev-blog-tags-test-driven-documentation-210.json",665],f914cfe8:[()=>n.e(2690).then(n.bind(n,5756)),"@site/docs/ast-builder/statements/querying/data-selection-and-projection.md",5756],f9553497:[()=>n.e(4033).then(n.bind(n,4176)),"@site/docs/ast-builder/functions/text/position-and-indexing.md",4176],fa5466f2:[()=>n.e(314).then(n.bind(n,9192)),"@site/docs/sql-syntax/functions/others/ifnull.md",9192],faca410e:[()=>n.e(6811).then(n.bind(n,5870)),"@site/docs/sql-syntax/functions/math/exp.md",5870],ff7b8d8e:[()=>n.e(3344).then(n.bind(n,1922)),"@site/docs/sql-syntax/data-types/time.md",1922]};function c(e){let{error:t,retry:n,pastDelay:r}=e;return t?a.createElement("div",{style:{textAlign:"center",color:"#fff",backgroundColor:"#fa383e",borderColor:"#fa383e",borderStyle:"solid",borderRadius:"0.25rem",borderWidth:"1px",boxSizing:"border-box",display:"block",padding:"1rem",flex:"0 0 50%",marginLeft:"25%",marginRight:"25%",marginTop:"5rem",maxWidth:"50%",width:"100%"}},a.createElement("p",null,String(t)),a.createElement("div",null,a.createElement("button",{type:"button",onClick:n},"Retry"))):r?a.createElement("div",{style:{display:"flex",justifyContent:"center",alignItems:"center",height:"100vh"}},a.createElement("svg",{id:"loader",style:{width:128,height:110,position:"absolute",top:"calc(100vh - 64%)"},viewBox:"0 0 45 45",xmlns:"http://www.w3.org/2000/svg",stroke:"#61dafb"},a.createElement("g",{fill:"none",fillRule:"evenodd",transform:"translate(1 1)",strokeWidth:"2"},a.createElement("circle",{cx:"22",cy:"22",r:"6",strokeOpacity:"0"},a.createElement("animate",{attributeName:"r",begin:"1.5s",dur:"3s",values:"6;22",calcMode:"linear",repeatCount:"indefinite"}),a.createElement("animate",{attributeName:"stroke-opacity",begin:"1.5s",dur:"3s",values:"1;0",calcMode:"linear",repeatCount:"indefinite"}),a.createElement("animate",{attributeName:"stroke-width",begin:"1.5s",dur:"3s",values:"2;0",calcMode:"linear",repeatCount:"indefinite"})),a.createElement("circle",{cx:"22",cy:"22",r:"6",strokeOpacity:"0"},a.createElement("animate",{attributeName:"r",begin:"3s",dur:"3s",values:"6;22",calcMode:"linear",repeatCount:"indefinite"}),a.createElement("animate",{attributeName:"stroke-opacity",begin:"3s",dur:"3s",values:"1;0",calcMode:"linear",repeatCount:"indefinite"}),a.createElement("animate",{attributeName:"stroke-width",begin:"3s",dur:"3s",values:"2;0",calcMode:"linear",repeatCount:"indefinite"})),a.createElement("circle",{cx:"22",cy:"22",r:"8"},a.createElement("animate",{attributeName:"r",begin:"0s",dur:"1.5s",values:"6;1;2;3;4;5;6",calcMode:"linear",repeatCount:"indefinite"}))))):null}var u=n(9670),d=n(226);function f(e,t){if("*"===e)return s()({loading:c,loader:()=>n.e(4972).then(n.bind(n,4972)),modules:["@theme/NotFound"],webpack:()=>[4972],render(e,t){const n=e.default;return a.createElement(d.z,{value:{plugin:{name:"native",id:"default"}}},a.createElement(n,t))}});const o=i[`${e}-${t}`],f={},p=[],m=[],g=(0,u.Z)(o);return Object.entries(g).forEach((e=>{let[t,n]=e;const a=l[n];a&&(f[t]=a[0],p.push(a[1]),m.push(a[2]))})),s().Map({loading:c,loader:f,modules:p,webpack:()=>m,render(t,n){const s=JSON.parse(JSON.stringify(o));Object.entries(t).forEach((t=>{let[n,a]=t;const r=a.default;if(!r)throw new Error(`The page component at ${e} doesn't have a default export. This makes it impossible to render anything. Consider default-exporting a React component.`);"object"!=typeof r&&"function"!=typeof r||Object.keys(a).filter((e=>"default"!==e)).forEach((e=>{r[e]=a[e]}));let o=s;const i=n.split(".");i.slice(0,-1).forEach((e=>{o=o[e]})),o[i[i.length-1]]=r}));const i=s.__comp;delete s.__comp;const l=s.__context;return delete s.__context,a.createElement(d.z,{value:l},a.createElement(i,(0,r.Z)({},s,n)))}})}const p=[{path:"/docs/dev/blog",component:f("/docs/dev/blog","9f6"),exact:!0},{path:"/docs/dev/blog/archive",component:f("/docs/dev/blog/archive","f0a"),exact:!0},{path:"/docs/dev/blog/breaking-the-boundary-between-sql-and-nosql",component:f("/docs/dev/blog/breaking-the-boundary-between-sql-and-nosql","150"),exact:!0},{path:"/docs/dev/blog/release-v0.14",component:f("/docs/dev/blog/release-v0.14","d1b"),exact:!0},{path:"/docs/dev/blog/revolutionizing-databases-by-unifying-query-interfaces",component:f("/docs/dev/blog/revolutionizing-databases-by-unifying-query-interfaces","c88"),exact:!0},{path:"/docs/dev/blog/tags",component:f("/docs/dev/blog/tags","946"),exact:!0},{path:"/docs/dev/blog/tags/automation",component:f("/docs/dev/blog/tags/automation","7a5"),exact:!0},{path:"/docs/dev/blog/tags/chat-gpt",component:f("/docs/dev/blog/tags/chat-gpt","65d"),exact:!0},{path:"/docs/dev/blog/tags/database",component:f("/docs/dev/blog/tags/database","53f"),exact:!0},{path:"/docs/dev/blog/tags/documentation",component:f("/docs/dev/blog/tags/documentation","7d2"),exact:!0},{path:"/docs/dev/blog/tags/gluesql",component:f("/docs/dev/blog/tags/gluesql","22b"),exact:!0},{path:"/docs/dev/blog/tags/nosql",component:f("/docs/dev/blog/tags/nosql","582"),exact:!0},{path:"/docs/dev/blog/tags/proposal",component:f("/docs/dev/blog/tags/proposal","5c5"),exact:!0},{path:"/docs/dev/blog/tags/query-interface",component:f("/docs/dev/blog/tags/query-interface","ee0"),exact:!0},{path:"/docs/dev/blog/tags/release-note",component:f("/docs/dev/blog/tags/release-note","991"),exact:!0},{path:"/docs/dev/blog/tags/sql",component:f("/docs/dev/blog/tags/sql","959"),exact:!0},{path:"/docs/dev/blog/tags/tdd",component:f("/docs/dev/blog/tags/tdd","ff0"),exact:!0},{path:"/docs/dev/blog/tags/test-driven-documentation",component:f("/docs/dev/blog/tags/test-driven-documentation","fcc"),exact:!0},{path:"/docs/dev/blog/tags/v-0-14",component:f("/docs/dev/blog/tags/v-0-14","b4d"),exact:!0},{path:"/docs/dev/blog/test-driven-documentation",component:f("/docs/dev/blog/test-driven-documentation","af8"),exact:!0},{path:"/docs/dev/",component:f("/docs/dev/","52e"),routes:[{path:"/docs/dev/",component:f("/docs/dev/","666"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/ast-builder/expressions/conditional",component:f("/docs/dev/ast-builder/expressions/conditional","32d"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/ast-builder/expressions/nested",component:f("/docs/dev/ast-builder/expressions/nested","dcd"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/ast-builder/expressions/operator-based",component:f("/docs/dev/ast-builder/expressions/operator-based","172"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/ast-builder/expressions/pattern-matching",component:f("/docs/dev/ast-builder/expressions/pattern-matching","8b6"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/ast-builder/expressions/value-checking",component:f("/docs/dev/ast-builder/expressions/value-checking","c44"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/ast-builder/functions/date-&-time/conversion",component:f("/docs/dev/ast-builder/functions/date-&-time/conversion","bf0"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/ast-builder/functions/date-&-time/current-date-and-time",component:f("/docs/dev/ast-builder/functions/date-&-time/current-date-and-time","16a"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/ast-builder/functions/date-&-time/date-and-time-extraction",component:f("/docs/dev/ast-builder/functions/date-&-time/date-and-time-extraction","273"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/ast-builder/functions/date-&-time/formatting",component:f("/docs/dev/ast-builder/functions/date-&-time/formatting","b9b"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/ast-builder/functions/geometry/coordinate-extraction",component:f("/docs/dev/ast-builder/functions/geometry/coordinate-extraction","5d6"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/ast-builder/functions/geometry/distance-calculation",component:f("/docs/dev/ast-builder/functions/geometry/distance-calculation","900"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/ast-builder/functions/geometry/point-creation",component:f("/docs/dev/ast-builder/functions/geometry/point-creation","1a3"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/ast-builder/functions/list-&-map/list-and-map-concatenation",component:f("/docs/dev/ast-builder/functions/list-&-map/list-and-map-concatenation","35b"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/ast-builder/functions/list-&-map/list-manipulation",component:f("/docs/dev/ast-builder/functions/list-&-map/list-manipulation","2cf"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/ast-builder/functions/math/basic-arithmetic",component:f("/docs/dev/ast-builder/functions/math/basic-arithmetic","f0a"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/ast-builder/functions/math/conversion",component:f("/docs/dev/ast-builder/functions/math/conversion","7c8"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/ast-builder/functions/math/logarithmic-and-exponential",component:f("/docs/dev/ast-builder/functions/math/logarithmic-and-exponential","fb1"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/ast-builder/functions/math/rounding",component:f("/docs/dev/ast-builder/functions/math/rounding","7ca"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/ast-builder/functions/math/special-mathematical",component:f("/docs/dev/ast-builder/functions/math/special-mathematical","3ee"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/ast-builder/functions/math/trigonometric",component:f("/docs/dev/ast-builder/functions/math/trigonometric","29b"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/ast-builder/functions/others/null-handling",component:f("/docs/dev/ast-builder/functions/others/null-handling","948"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/ast-builder/functions/others/type-conversion",component:f("/docs/dev/ast-builder/functions/others/type-conversion","a77"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/ast-builder/functions/others/unique-identifier",component:f("/docs/dev/ast-builder/functions/others/unique-identifier","0a6"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/ast-builder/functions/text/case-conversion",component:f("/docs/dev/ast-builder/functions/text/case-conversion","605"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/ast-builder/functions/text/character-conversion",component:f("/docs/dev/ast-builder/functions/text/character-conversion","919"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/ast-builder/functions/text/padding",component:f("/docs/dev/ast-builder/functions/text/padding","7b6"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/ast-builder/functions/text/position-and-indexing",component:f("/docs/dev/ast-builder/functions/text/position-and-indexing","1ed"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/ast-builder/functions/text/text-manipulation",component:f("/docs/dev/ast-builder/functions/text/text-manipulation","762"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/ast-builder/functions/text/trimming",component:f("/docs/dev/ast-builder/functions/text/trimming","63b"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/ast-builder/intro",component:f("/docs/dev/ast-builder/intro","06b"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/ast-builder/statements/data-manipulation/deleting-data",component:f("/docs/dev/ast-builder/statements/data-manipulation/deleting-data","9f7"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/ast-builder/statements/data-manipulation/inserting-data",component:f("/docs/dev/ast-builder/statements/data-manipulation/inserting-data","83e"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/ast-builder/statements/data-manipulation/updating-data",component:f("/docs/dev/ast-builder/statements/data-manipulation/updating-data","6c8"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/ast-builder/statements/querying/creating-derived-subqueries",component:f("/docs/dev/ast-builder/statements/querying/creating-derived-subqueries","f4d"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/ast-builder/statements/querying/data-aggregation",component:f("/docs/dev/ast-builder/statements/querying/data-aggregation","5f9"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/ast-builder/statements/querying/data-injection",component:f("/docs/dev/ast-builder/statements/querying/data-injection","a84"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/ast-builder/statements/querying/data-joining",component:f("/docs/dev/ast-builder/statements/querying/data-joining","2c0"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/ast-builder/statements/querying/data-selection-and-projection",component:f("/docs/dev/ast-builder/statements/querying/data-selection-and-projection","34f"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/ast-builder/statements/querying/data-sorting-and-limiting",component:f("/docs/dev/ast-builder/statements/querying/data-sorting-and-limiting","234"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/ast-builder/statements/querying/fetching-data-from-storage",component:f("/docs/dev/ast-builder/statements/querying/fetching-data-from-storage","b2e"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/ast-builder/statements/querying/using-preloaded-data",component:f("/docs/dev/ast-builder/statements/querying/using-preloaded-data","35f"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/getting-started/cli",component:f("/docs/dev/getting-started/cli","f3c"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/getting-started/javascript-web",component:f("/docs/dev/getting-started/javascript-web","ae6"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/getting-started/nodejs",component:f("/docs/dev/getting-started/nodejs","37e"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/getting-started/rust",component:f("/docs/dev/getting-started/rust","3fc"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/data-types/boolean",component:f("/docs/dev/sql-syntax/data-types/boolean","c7f"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/data-types/bytea",component:f("/docs/dev/sql-syntax/data-types/bytea","ed8"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/data-types/date",component:f("/docs/dev/sql-syntax/data-types/date","612"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/data-types/decimal",component:f("/docs/dev/sql-syntax/data-types/decimal","3f2"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/data-types/float",component:f("/docs/dev/sql-syntax/data-types/float","f0c"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/data-types/inet",component:f("/docs/dev/sql-syntax/data-types/inet","5c7"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/data-types/integers",component:f("/docs/dev/sql-syntax/data-types/integers","171"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/data-types/interval",component:f("/docs/dev/sql-syntax/data-types/interval","59c"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/data-types/list",component:f("/docs/dev/sql-syntax/data-types/list","0c2"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/data-types/map",component:f("/docs/dev/sql-syntax/data-types/map","744"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/data-types/text",component:f("/docs/dev/sql-syntax/data-types/text","f2f"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/data-types/time",component:f("/docs/dev/sql-syntax/data-types/time","66e"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/data-types/timestamp",component:f("/docs/dev/sql-syntax/data-types/timestamp","546"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/data-types/uuid",component:f("/docs/dev/sql-syntax/data-types/uuid","5fa"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/datetime/extract",component:f("/docs/dev/sql-syntax/functions/datetime/extract","ae9"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/datetime/format",component:f("/docs/dev/sql-syntax/functions/datetime/format","2c8"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/datetime/now",component:f("/docs/dev/sql-syntax/functions/datetime/now","93b"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/datetime/to-date",component:f("/docs/dev/sql-syntax/functions/datetime/to-date","8b3"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/datetime/to-time",component:f("/docs/dev/sql-syntax/functions/datetime/to-time","b6e"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/datetime/to-timestamp",component:f("/docs/dev/sql-syntax/functions/datetime/to-timestamp","52a"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/geometry/calc-distance",component:f("/docs/dev/sql-syntax/functions/geometry/calc-distance","e9f"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/geometry/get-x",component:f("/docs/dev/sql-syntax/functions/geometry/get-x","2ae"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/geometry/get-y",component:f("/docs/dev/sql-syntax/functions/geometry/get-y","54a"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/geometry/point",component:f("/docs/dev/sql-syntax/functions/geometry/point","12a"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/list-map/append",component:f("/docs/dev/sql-syntax/functions/list-map/append","be2"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/list-map/concat",component:f("/docs/dev/sql-syntax/functions/list-map/concat","cc9"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/list-map/prepend",component:f("/docs/dev/sql-syntax/functions/list-map/prepend","7d8"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/math/abs",component:f("/docs/dev/sql-syntax/functions/math/abs","b85"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/math/acos",component:f("/docs/dev/sql-syntax/functions/math/acos","ec1"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/math/asin",component:f("/docs/dev/sql-syntax/functions/math/asin","c78"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/math/atan",component:f("/docs/dev/sql-syntax/functions/math/atan","ad0"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/math/ceil",component:f("/docs/dev/sql-syntax/functions/math/ceil","0d5"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/math/cos",component:f("/docs/dev/sql-syntax/functions/math/cos","8ae"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/math/degrees",component:f("/docs/dev/sql-syntax/functions/math/degrees","e0e"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/math/div",component:f("/docs/dev/sql-syntax/functions/math/div","048"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/math/exp",component:f("/docs/dev/sql-syntax/functions/math/exp","a31"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/math/floor",component:f("/docs/dev/sql-syntax/functions/math/floor","03a"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/math/gcd",component:f("/docs/dev/sql-syntax/functions/math/gcd","f38"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/math/lcm",component:f("/docs/dev/sql-syntax/functions/math/lcm","1c7"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/math/ln",component:f("/docs/dev/sql-syntax/functions/math/ln","700"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/math/log",component:f("/docs/dev/sql-syntax/functions/math/log","4e6"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/math/log10",component:f("/docs/dev/sql-syntax/functions/math/log10","09d"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/math/log2",component:f("/docs/dev/sql-syntax/functions/math/log2","204"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/math/mod",component:f("/docs/dev/sql-syntax/functions/math/mod","1fe"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/math/pi",component:f("/docs/dev/sql-syntax/functions/math/pi","4b0"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/math/power",component:f("/docs/dev/sql-syntax/functions/math/power","a7d"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/math/radians",component:f("/docs/dev/sql-syntax/functions/math/radians","09d"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/math/rand",component:f("/docs/dev/sql-syntax/functions/math/rand","5c1"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/math/round",component:f("/docs/dev/sql-syntax/functions/math/round","73f"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/math/sign",component:f("/docs/dev/sql-syntax/functions/math/sign","da7"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/math/sin",component:f("/docs/dev/sql-syntax/functions/math/sin","98d"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/math/sqrt",component:f("/docs/dev/sql-syntax/functions/math/sqrt","d79"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/math/tan",component:f("/docs/dev/sql-syntax/functions/math/tan","a32"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/others/cast",component:f("/docs/dev/sql-syntax/functions/others/cast","5c2"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/others/generate-uuid",component:f("/docs/dev/sql-syntax/functions/others/generate-uuid","7ff"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/others/ifnull",component:f("/docs/dev/sql-syntax/functions/others/ifnull","bfe"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/text/ascii",component:f("/docs/dev/sql-syntax/functions/text/ascii","6f0"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/text/chr",component:f("/docs/dev/sql-syntax/functions/text/chr","791"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/text/concat",component:f("/docs/dev/sql-syntax/functions/text/concat","2d3"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/text/concat-ws",component:f("/docs/dev/sql-syntax/functions/text/concat-ws","7cc"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/text/find-idx",component:f("/docs/dev/sql-syntax/functions/text/find-idx","e63"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/text/initcap",component:f("/docs/dev/sql-syntax/functions/text/initcap","d0b"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/text/left",component:f("/docs/dev/sql-syntax/functions/text/left","6d7"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/text/lower",component:f("/docs/dev/sql-syntax/functions/text/lower","913"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/text/lpad",component:f("/docs/dev/sql-syntax/functions/text/lpad","832"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/text/ltrim",component:f("/docs/dev/sql-syntax/functions/text/ltrim","076"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/text/position",component:f("/docs/dev/sql-syntax/functions/text/position","184"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/text/repeat",component:f("/docs/dev/sql-syntax/functions/text/repeat","6c9"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/text/reverse",component:f("/docs/dev/sql-syntax/functions/text/reverse","007"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/text/right",component:f("/docs/dev/sql-syntax/functions/text/right","f07"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/text/rpad",component:f("/docs/dev/sql-syntax/functions/text/rpad","93e"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/text/rtrim",component:f("/docs/dev/sql-syntax/functions/text/rtrim","e76"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/text/substr",component:f("/docs/dev/sql-syntax/functions/text/substr","d8c"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/text/trim",component:f("/docs/dev/sql-syntax/functions/text/trim","ce4"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/functions/text/upper",component:f("/docs/dev/sql-syntax/functions/text/upper","6b6"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/intro",component:f("/docs/dev/sql-syntax/intro","d94"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/statements/data-definition/alter-table",component:f("/docs/dev/sql-syntax/statements/data-definition/alter-table","259"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/statements/data-definition/create-index",component:f("/docs/dev/sql-syntax/statements/data-definition/create-index","ba4"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/statements/data-definition/create-table",component:f("/docs/dev/sql-syntax/statements/data-definition/create-table","9fd"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/statements/data-definition/drop-index",component:f("/docs/dev/sql-syntax/statements/data-definition/drop-index","69c"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/statements/data-definition/drop-table",component:f("/docs/dev/sql-syntax/statements/data-definition/drop-table","f80"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/statements/data-manipulation/delete",component:f("/docs/dev/sql-syntax/statements/data-manipulation/delete","927"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/statements/data-manipulation/insert",component:f("/docs/dev/sql-syntax/statements/data-manipulation/insert","10a"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/statements/data-manipulation/update",component:f("/docs/dev/sql-syntax/statements/data-manipulation/update","967"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/statements/metadata/data-dictionary",component:f("/docs/dev/sql-syntax/statements/metadata/data-dictionary","114"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/statements/metadata/show-tables",component:f("/docs/dev/sql-syntax/statements/metadata/show-tables","1bf"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/statements/querying/aggregation",component:f("/docs/dev/sql-syntax/statements/querying/aggregation","5df"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/statements/querying/join",component:f("/docs/dev/sql-syntax/statements/querying/join","796"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/statements/querying/limit",component:f("/docs/dev/sql-syntax/statements/querying/limit","762"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/statements/querying/schemaless",component:f("/docs/dev/sql-syntax/statements/querying/schemaless","afa"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/statements/querying/where",component:f("/docs/dev/sql-syntax/statements/querying/where","bb5"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/sql-syntax/statements/transaction",component:f("/docs/dev/sql-syntax/statements/transaction","411"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/storages/developing-custom-storages/intro",component:f("/docs/dev/storages/developing-custom-storages/intro","c6d"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/storages/developing-custom-storages/store-traits/alter-table",component:f("/docs/dev/storages/developing-custom-storages/store-traits/alter-table","4c5"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/storages/developing-custom-storages/store-traits/custom-function",component:f("/docs/dev/storages/developing-custom-storages/store-traits/custom-function","e5b"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/storages/developing-custom-storages/store-traits/custom-function-mut",component:f("/docs/dev/storages/developing-custom-storages/store-traits/custom-function-mut","0cc"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/storages/developing-custom-storages/store-traits/index-mut",component:f("/docs/dev/storages/developing-custom-storages/store-traits/index-mut","78f"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/storages/developing-custom-storages/store-traits/index-trait",component:f("/docs/dev/storages/developing-custom-storages/store-traits/index-trait","aa3"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/storages/developing-custom-storages/store-traits/metadata",component:f("/docs/dev/storages/developing-custom-storages/store-traits/metadata","2a5"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/storages/developing-custom-storages/store-traits/store",component:f("/docs/dev/storages/developing-custom-storages/store-traits/store","262"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/storages/developing-custom-storages/store-traits/store-mut",component:f("/docs/dev/storages/developing-custom-storages/store-traits/store-mut","853"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/storages/developing-custom-storages/store-traits/transaction",component:f("/docs/dev/storages/developing-custom-storages/store-traits/transaction","bd7"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/storages/developing-custom-storages/using-test-suite",component:f("/docs/dev/storages/developing-custom-storages/using-test-suite","a37"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/storages/intro",component:f("/docs/dev/storages/intro","8d9"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/storages/supported-storages/composite-storage",component:f("/docs/dev/storages/supported-storages/composite-storage","93e"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/storages/supported-storages/idb-storage",component:f("/docs/dev/storages/supported-storages/idb-storage","787"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/storages/supported-storages/json-storage",component:f("/docs/dev/storages/supported-storages/json-storage","207"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/storages/supported-storages/memory-storage",component:f("/docs/dev/storages/supported-storages/memory-storage","695"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/storages/supported-storages/shared-memory-storage",component:f("/docs/dev/storages/supported-storages/shared-memory-storage","418"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/storages/supported-storages/sled-storage",component:f("/docs/dev/storages/supported-storages/sled-storage","fb0"),exact:!0,sidebar:"autoSidebar"},{path:"/docs/dev/storages/supported-storages/web-storage",component:f("/docs/dev/storages/supported-storages/web-storage","14a"),exact:!0,sidebar:"autoSidebar"}]},{path:"*",component:f("*")}]},8934:(e,t,n)=>{"use strict";n.d(t,{_:()=>r,t:()=>o});var a=n(7294);const r=a.createContext(!1);function o(e){let{children:t}=e;const[n,o]=(0,a.useState)(!1);return(0,a.useEffect)((()=>{o(!0)}),[]),a.createElement(r.Provider,{value:n},t)}},9383:(e,t,n)=>{"use strict";var a=n(7294),r=n(3935),o=n(3727),s=n(405),i=n(412);const l=[n(2497),n(3310),n(8320),n(2295)];var c=n(723),u=n(6550),d=n(8790);function f(e){let{children:t}=e;return a.createElement(a.Fragment,null,t)}var p=n(7462),m=n(5742),g=n(2263),h=n(4996),b=n(6668),v=n(1944),y=n(4711),x=n(9727),w=n(3320),S=n(197);function E(){const{i18n:{defaultLocale:e,localeConfigs:t}}=(0,g.Z)(),n=(0,y.l)();return a.createElement(m.Z,null,Object.entries(t).map((e=>{let[t,{htmlLang:r}]=e;return a.createElement("link",{key:t,rel:"alternate",href:n.createUrl({locale:t,fullyQualified:!0}),hrefLang:r})})),a.createElement("link",{rel:"alternate",href:n.createUrl({locale:e,fullyQualified:!0}),hrefLang:"x-default"}))}function k(e){let{permalink:t}=e;const{siteConfig:{url:n}}=(0,g.Z)(),r=function(){const{siteConfig:{url:e}}=(0,g.Z)(),{pathname:t}=(0,u.TH)();return e+(0,h.Z)(t)}(),o=t?`${n}${t}`:r;return a.createElement(m.Z,null,a.createElement("meta",{property:"og:url",content:o}),a.createElement("link",{rel:"canonical",href:o}))}function _(){const{i18n:{currentLocale:e}}=(0,g.Z)(),{metadata:t,image:n}=(0,b.L)();return a.createElement(a.Fragment,null,a.createElement(m.Z,null,a.createElement("meta",{name:"twitter:card",content:"summary_large_image"}),a.createElement("body",{className:x.h})),n&&a.createElement(v.d,{image:n}),a.createElement(k,null),a.createElement(E,null),a.createElement(S.Z,{tag:w.HX,locale:e}),a.createElement(m.Z,null,t.map(((e,t)=>a.createElement("meta",(0,p.Z)({key:t},e))))))}const C=new Map;function T(e){if(C.has(e.pathname))return{...e,pathname:C.get(e.pathname)};if((0,d.f)(c.Z,e.pathname).some((e=>{let{route:t}=e;return!0===t.exact})))return C.set(e.pathname,e.pathname),e;const t=e.pathname.trim().replace(/(?:\/index)?\.html$/,"")||"/";return C.set(e.pathname,t),{...e,pathname:t}}var q=n(8934),A=n(8940);function L(e){for(var t=arguments.length,n=new Array(t>1?t-1:0),a=1;a<t;a++)n[a-1]=arguments[a];const r=l.map((t=>{const a=t.default?.[e]??t[e];return a?.(...n)}));return()=>r.forEach((e=>e?.()))}const N=function(e){let{children:t,location:n,previousLocation:r}=e;return(0,a.useLayoutEffect)((()=>{r!==n&&(!function(e){let{location:t,previousLocation:n}=e;if(!n)return;const a=t.pathname===n.pathname,r=t.hash===n.hash,o=t.search===n.search;if(a&&r&&!o)return;const{hash:s}=t;if(s){const e=decodeURIComponent(s.substring(1)),t=document.getElementById(e);t?.scrollIntoView()}else window.scrollTo(0,0)}({location:n,previousLocation:r}),L("onRouteDidUpdate",{previousLocation:r,location:n}))}),[r,n]),t};function O(e){const t=Array.from(new Set([e,decodeURI(e)])).map((e=>(0,d.f)(c.Z,e))).flat();return Promise.all(t.map((e=>e.route.component.preload?.())))}class P extends a.Component{previousLocation;routeUpdateCleanupCb;constructor(e){super(e),this.previousLocation=null,this.routeUpdateCleanupCb=i.Z.canUseDOM?L("onRouteUpdate",{previousLocation:null,location:this.props.location}):()=>{},this.state={nextRouteHasLoaded:!0}}shouldComponentUpdate(e,t){if(e.location===this.props.location)return t.nextRouteHasLoaded;const n=e.location;return this.previousLocation=this.props.location,this.setState({nextRouteHasLoaded:!1}),this.routeUpdateCleanupCb=L("onRouteUpdate",{previousLocation:this.previousLocation,location:n}),O(n.pathname).then((()=>{this.routeUpdateCleanupCb(),this.setState({nextRouteHasLoaded:!0})})).catch((e=>{console.warn(e),window.location.reload()})),!1}render(){const{children:e,location:t}=this.props;return a.createElement(N,{previousLocation:this.previousLocation,location:t},a.createElement(u.AW,{location:t,render:()=>e}))}}const I=P,R="__docusaurus-base-url-issue-banner-container",M="__docusaurus-base-url-issue-banner",D="__docusaurus-base-url-issue-banner-suggestion-container",F="__DOCUSAURUS_INSERT_BASEURL_BANNER";function B(e){return`\nwindow['${F}'] = true;\n\ndocument.addEventListener('DOMContentLoaded', maybeInsertBanner);\n\nfunction maybeInsertBanner() {\n var shouldInsert = window['${F}'];\n shouldInsert && insertBanner();\n}\n\nfunction insertBanner() {\n var bannerContainer = document.getElementById('${R}');\n if (!bannerContainer) {\n return;\n }\n var bannerHtml = ${JSON.stringify(function(e){return`\n<div id="${M}" style="border: thick solid red; background-color: rgb(255, 230, 179); margin: 20px; padding: 20px; font-size: 20px;">\n <p style="font-weight: bold; font-size: 30px;">Your Docusaurus site did not load properly.</p>\n <p>A very common reason is a wrong site <a href="https://docusaurus.io/docs/docusaurus.config.js/#baseUrl" style="font-weight: bold;">baseUrl configuration</a>.</p>\n <p>Current configured baseUrl = <span style="font-weight: bold; color: red;">${e}</span> ${"/"===e?" (default value)":""}</p>\n <p>We suggest trying baseUrl = <span id="${D}" style="font-weight: bold; color: green;"></span></p>\n</div>\n`}(e)).replace(/</g,"\\<")};\n bannerContainer.innerHTML = bannerHtml;\n var suggestionContainer = document.getElementById('${D}');\n var actualHomePagePath = window.location.pathname;\n var suggestedBaseUrl = actualHomePagePath.substr(-1) === '/'\n ? actualHomePagePath\n : actualHomePagePath + '/';\n suggestionContainer.innerHTML = suggestedBaseUrl;\n}\n`}function j(){const{siteConfig:{baseUrl:e}}=(0,g.Z)();return(0,a.useLayoutEffect)((()=>{window[F]=!1}),[]),a.createElement(a.Fragment,null,!i.Z.canUseDOM&&a.createElement(m.Z,null,a.createElement("script",null,B(e))),a.createElement("div",{id:R}))}function z(){const{siteConfig:{baseUrl:e,baseUrlIssueBanner:t}}=(0,g.Z)(),{pathname:n}=(0,u.TH)();return t&&n===e?a.createElement(j,null):null}function $(){const{siteConfig:{favicon:e,title:t,noIndex:n},i18n:{currentLocale:r,localeConfigs:o}}=(0,g.Z)(),s=(0,h.Z)(e),{htmlLang:i,direction:l}=o[r];return a.createElement(m.Z,null,a.createElement("html",{lang:i,dir:l}),a.createElement("title",null,t),a.createElement("meta",{property:"og:title",content:t}),a.createElement("meta",{name:"viewport",content:"width=device-width, initial-scale=1.0"}),n&&a.createElement("meta",{name:"robots",content:"noindex, nofollow"}),e&&a.createElement("link",{rel:"icon",href:s}))}var U=n(4763);function Z(){const e=(0,d.H)(c.Z),t=(0,u.TH)();return a.createElement(U.Z,null,a.createElement(A.M,null,a.createElement(q.t,null,a.createElement(f,null,a.createElement($,null),a.createElement(_,null),a.createElement(z,null),a.createElement(I,{location:T(t)},e)))))}var H=n(6887);const V=function(e){try{return document.createElement("link").relList.supports(e)}catch{return!1}}("prefetch")?function(e){return new Promise(((t,n)=>{if("undefined"==typeof document)return void n();const a=document.createElement("link");a.setAttribute("rel","prefetch"),a.setAttribute("href",e),a.onload=()=>t(),a.onerror=()=>n();const r=document.getElementsByTagName("head")[0]??document.getElementsByName("script")[0]?.parentNode;r?.appendChild(a)}))}:function(e){return new Promise(((t,n)=>{const a=new XMLHttpRequest;a.open("GET",e,!0),a.withCredentials=!0,a.onload=()=>{200===a.status?t():n()},a.send(null)}))};var W=n(9670);const G=new Set,Y=new Set,K=()=>navigator.connection?.effectiveType.includes("2g")||navigator.connection?.saveData,Q={prefetch(e){if(!(e=>!K()&&!Y.has(e)&&!G.has(e))(e))return!1;G.add(e);const t=(0,d.f)(c.Z,e).flatMap((e=>{return t=e.route.path,Object.entries(H).filter((e=>{let[n]=e;return n.replace(/-[^-]+$/,"")===t})).flatMap((e=>{let[,t]=e;return Object.values((0,W.Z)(t))}));var t}));return Promise.all(t.map((e=>{const t=n.gca(e);return t&&!t.includes("undefined")?V(t).catch((()=>{})):Promise.resolve()})))},preload:e=>!!(e=>!K()&&!Y.has(e))(e)&&(Y.add(e),O(e))},X=Object.freeze(Q);if(i.Z.canUseDOM){window.docusaurus=X;const e=r.hydrate;O(window.location.pathname).then((()=>{e(a.createElement(s.B6,null,a.createElement(o.VK,null,a.createElement(Z,null))),document.getElementById("__docusaurus"))}))}},8940:(e,t,n)=>{"use strict";n.d(t,{_:()=>u,M:()=>d});var a=n(7294),r=n(6809);const o=JSON.parse('{"docusaurus-plugin-content-docs":{"default":{"path":"/docs/dev/","versions":[{"name":"current","label":"Next","isLast":true,"path":"/docs/dev/","mainDocId":"index","docs":[{"id":"ast-builder/expressions/conditional","path":"/docs/dev/ast-builder/expressions/conditional","sidebar":"autoSidebar"},{"id":"ast-builder/expressions/nested","path":"/docs/dev/ast-builder/expressions/nested","sidebar":"autoSidebar"},{"id":"ast-builder/expressions/operator-based","path":"/docs/dev/ast-builder/expressions/operator-based","sidebar":"autoSidebar"},{"id":"ast-builder/expressions/pattern-matching","path":"/docs/dev/ast-builder/expressions/pattern-matching","sidebar":"autoSidebar"},{"id":"ast-builder/expressions/value-checking","path":"/docs/dev/ast-builder/expressions/value-checking","sidebar":"autoSidebar"},{"id":"ast-builder/functions/date-&-time/conversion","path":"/docs/dev/ast-builder/functions/date-&-time/conversion","sidebar":"autoSidebar"},{"id":"ast-builder/functions/date-&-time/current-date-and-time","path":"/docs/dev/ast-builder/functions/date-&-time/current-date-and-time","sidebar":"autoSidebar"},{"id":"ast-builder/functions/date-&-time/date-and-time-extraction","path":"/docs/dev/ast-builder/functions/date-&-time/date-and-time-extraction","sidebar":"autoSidebar"},{"id":"ast-builder/functions/date-&-time/formatting","path":"/docs/dev/ast-builder/functions/date-&-time/formatting","sidebar":"autoSidebar"},{"id":"ast-builder/functions/geometry/coordinate-extraction","path":"/docs/dev/ast-builder/functions/geometry/coordinate-extraction","sidebar":"autoSidebar"},{"id":"ast-builder/functions/geometry/distance-calculation","path":"/docs/dev/ast-builder/functions/geometry/distance-calculation","sidebar":"autoSidebar"},{"id":"ast-builder/functions/geometry/point-creation","path":"/docs/dev/ast-builder/functions/geometry/point-creation","sidebar":"autoSidebar"},{"id":"ast-builder/functions/list-&-map/list-and-map-concatenation","path":"/docs/dev/ast-builder/functions/list-&-map/list-and-map-concatenation","sidebar":"autoSidebar"},{"id":"ast-builder/functions/list-&-map/list-manipulation","path":"/docs/dev/ast-builder/functions/list-&-map/list-manipulation","sidebar":"autoSidebar"},{"id":"ast-builder/functions/math/basic-arithmetic","path":"/docs/dev/ast-builder/functions/math/basic-arithmetic","sidebar":"autoSidebar"},{"id":"ast-builder/functions/math/conversion","path":"/docs/dev/ast-builder/functions/math/conversion","sidebar":"autoSidebar"},{"id":"ast-builder/functions/math/logarithmic-and-exponential","path":"/docs/dev/ast-builder/functions/math/logarithmic-and-exponential","sidebar":"autoSidebar"},{"id":"ast-builder/functions/math/rounding","path":"/docs/dev/ast-builder/functions/math/rounding","sidebar":"autoSidebar"},{"id":"ast-builder/functions/math/special-mathematical","path":"/docs/dev/ast-builder/functions/math/special-mathematical","sidebar":"autoSidebar"},{"id":"ast-builder/functions/math/trigonometric","path":"/docs/dev/ast-builder/functions/math/trigonometric","sidebar":"autoSidebar"},{"id":"ast-builder/functions/others/null-handling","path":"/docs/dev/ast-builder/functions/others/null-handling","sidebar":"autoSidebar"},{"id":"ast-builder/functions/others/type-conversion","path":"/docs/dev/ast-builder/functions/others/type-conversion","sidebar":"autoSidebar"},{"id":"ast-builder/functions/others/unique-identifier","path":"/docs/dev/ast-builder/functions/others/unique-identifier","sidebar":"autoSidebar"},{"id":"ast-builder/functions/text/case-conversion","path":"/docs/dev/ast-builder/functions/text/case-conversion","sidebar":"autoSidebar"},{"id":"ast-builder/functions/text/character-conversion","path":"/docs/dev/ast-builder/functions/text/character-conversion","sidebar":"autoSidebar"},{"id":"ast-builder/functions/text/padding","path":"/docs/dev/ast-builder/functions/text/padding","sidebar":"autoSidebar"},{"id":"ast-builder/functions/text/position-and-indexing","path":"/docs/dev/ast-builder/functions/text/position-and-indexing","sidebar":"autoSidebar"},{"id":"ast-builder/functions/text/text-manipulation","path":"/docs/dev/ast-builder/functions/text/text-manipulation","sidebar":"autoSidebar"},{"id":"ast-builder/functions/text/trimming","path":"/docs/dev/ast-builder/functions/text/trimming","sidebar":"autoSidebar"},{"id":"ast-builder/intro","path":"/docs/dev/ast-builder/intro","sidebar":"autoSidebar"},{"id":"ast-builder/statements/data-manipulation/deleting-data","path":"/docs/dev/ast-builder/statements/data-manipulation/deleting-data","sidebar":"autoSidebar"},{"id":"ast-builder/statements/data-manipulation/inserting-data","path":"/docs/dev/ast-builder/statements/data-manipulation/inserting-data","sidebar":"autoSidebar"},{"id":"ast-builder/statements/data-manipulation/updating-data","path":"/docs/dev/ast-builder/statements/data-manipulation/updating-data","sidebar":"autoSidebar"},{"id":"ast-builder/statements/querying/creating-derived-subqueries","path":"/docs/dev/ast-builder/statements/querying/creating-derived-subqueries","sidebar":"autoSidebar"},{"id":"ast-builder/statements/querying/data-aggregation","path":"/docs/dev/ast-builder/statements/querying/data-aggregation","sidebar":"autoSidebar"},{"id":"ast-builder/statements/querying/data-injection","path":"/docs/dev/ast-builder/statements/querying/data-injection","sidebar":"autoSidebar"},{"id":"ast-builder/statements/querying/data-joining","path":"/docs/dev/ast-builder/statements/querying/data-joining","sidebar":"autoSidebar"},{"id":"ast-builder/statements/querying/data-selection-and-projection","path":"/docs/dev/ast-builder/statements/querying/data-selection-and-projection","sidebar":"autoSidebar"},{"id":"ast-builder/statements/querying/data-sorting-and-limiting","path":"/docs/dev/ast-builder/statements/querying/data-sorting-and-limiting","sidebar":"autoSidebar"},{"id":"ast-builder/statements/querying/fetching-data-from-storage","path":"/docs/dev/ast-builder/statements/querying/fetching-data-from-storage","sidebar":"autoSidebar"},{"id":"ast-builder/statements/querying/using-preloaded-data","path":"/docs/dev/ast-builder/statements/querying/using-preloaded-data","sidebar":"autoSidebar"},{"id":"getting-started/cli","path":"/docs/dev/getting-started/cli","sidebar":"autoSidebar"},{"id":"getting-started/javascript-web","path":"/docs/dev/getting-started/javascript-web","sidebar":"autoSidebar"},{"id":"getting-started/nodejs","path":"/docs/dev/getting-started/nodejs","sidebar":"autoSidebar"},{"id":"getting-started/rust","path":"/docs/dev/getting-started/rust","sidebar":"autoSidebar"},{"id":"index","path":"/docs/dev/","sidebar":"autoSidebar"},{"id":"sql-syntax/data-types/boolean","path":"/docs/dev/sql-syntax/data-types/boolean","sidebar":"autoSidebar"},{"id":"sql-syntax/data-types/bytea","path":"/docs/dev/sql-syntax/data-types/bytea","sidebar":"autoSidebar"},{"id":"sql-syntax/data-types/date","path":"/docs/dev/sql-syntax/data-types/date","sidebar":"autoSidebar"},{"id":"sql-syntax/data-types/decimal","path":"/docs/dev/sql-syntax/data-types/decimal","sidebar":"autoSidebar"},{"id":"sql-syntax/data-types/float","path":"/docs/dev/sql-syntax/data-types/float","sidebar":"autoSidebar"},{"id":"sql-syntax/data-types/inet","path":"/docs/dev/sql-syntax/data-types/inet","sidebar":"autoSidebar"},{"id":"sql-syntax/data-types/integers","path":"/docs/dev/sql-syntax/data-types/integers","sidebar":"autoSidebar"},{"id":"sql-syntax/data-types/interval","path":"/docs/dev/sql-syntax/data-types/interval","sidebar":"autoSidebar"},{"id":"sql-syntax/data-types/list","path":"/docs/dev/sql-syntax/data-types/list","sidebar":"autoSidebar"},{"id":"sql-syntax/data-types/map","path":"/docs/dev/sql-syntax/data-types/map","sidebar":"autoSidebar"},{"id":"sql-syntax/data-types/text","path":"/docs/dev/sql-syntax/data-types/text","sidebar":"autoSidebar"},{"id":"sql-syntax/data-types/time","path":"/docs/dev/sql-syntax/data-types/time","sidebar":"autoSidebar"},{"id":"sql-syntax/data-types/timestamp","path":"/docs/dev/sql-syntax/data-types/timestamp","sidebar":"autoSidebar"},{"id":"sql-syntax/data-types/uuid","path":"/docs/dev/sql-syntax/data-types/uuid","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/datetime/extract","path":"/docs/dev/sql-syntax/functions/datetime/extract","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/datetime/format","path":"/docs/dev/sql-syntax/functions/datetime/format","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/datetime/now","path":"/docs/dev/sql-syntax/functions/datetime/now","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/datetime/to-date","path":"/docs/dev/sql-syntax/functions/datetime/to-date","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/datetime/to-time","path":"/docs/dev/sql-syntax/functions/datetime/to-time","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/datetime/to-timestamp","path":"/docs/dev/sql-syntax/functions/datetime/to-timestamp","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/geometry/calc-distance","path":"/docs/dev/sql-syntax/functions/geometry/calc-distance","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/geometry/get-x","path":"/docs/dev/sql-syntax/functions/geometry/get-x","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/geometry/get-y","path":"/docs/dev/sql-syntax/functions/geometry/get-y","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/geometry/point","path":"/docs/dev/sql-syntax/functions/geometry/point","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/list-map/append","path":"/docs/dev/sql-syntax/functions/list-map/append","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/list-map/concat","path":"/docs/dev/sql-syntax/functions/list-map/concat","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/list-map/prepend","path":"/docs/dev/sql-syntax/functions/list-map/prepend","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/math/abs","path":"/docs/dev/sql-syntax/functions/math/abs","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/math/acos","path":"/docs/dev/sql-syntax/functions/math/acos","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/math/asin","path":"/docs/dev/sql-syntax/functions/math/asin","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/math/atan","path":"/docs/dev/sql-syntax/functions/math/atan","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/math/ceil","path":"/docs/dev/sql-syntax/functions/math/ceil","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/math/cos","path":"/docs/dev/sql-syntax/functions/math/cos","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/math/degrees","path":"/docs/dev/sql-syntax/functions/math/degrees","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/math/div","path":"/docs/dev/sql-syntax/functions/math/div","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/math/exp","path":"/docs/dev/sql-syntax/functions/math/exp","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/math/floor","path":"/docs/dev/sql-syntax/functions/math/floor","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/math/gcd","path":"/docs/dev/sql-syntax/functions/math/gcd","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/math/lcm","path":"/docs/dev/sql-syntax/functions/math/lcm","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/math/ln","path":"/docs/dev/sql-syntax/functions/math/ln","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/math/log","path":"/docs/dev/sql-syntax/functions/math/log","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/math/log10","path":"/docs/dev/sql-syntax/functions/math/log10","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/math/log2","path":"/docs/dev/sql-syntax/functions/math/log2","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/math/mod","path":"/docs/dev/sql-syntax/functions/math/mod","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/math/pi","path":"/docs/dev/sql-syntax/functions/math/pi","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/math/power","path":"/docs/dev/sql-syntax/functions/math/power","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/math/radians","path":"/docs/dev/sql-syntax/functions/math/radians","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/math/rand","path":"/docs/dev/sql-syntax/functions/math/rand","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/math/round","path":"/docs/dev/sql-syntax/functions/math/round","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/math/sign","path":"/docs/dev/sql-syntax/functions/math/sign","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/math/sin","path":"/docs/dev/sql-syntax/functions/math/sin","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/math/sqrt","path":"/docs/dev/sql-syntax/functions/math/sqrt","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/math/tan","path":"/docs/dev/sql-syntax/functions/math/tan","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/others/cast","path":"/docs/dev/sql-syntax/functions/others/cast","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/others/generate-uuid","path":"/docs/dev/sql-syntax/functions/others/generate-uuid","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/others/ifnull","path":"/docs/dev/sql-syntax/functions/others/ifnull","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/text/ascii","path":"/docs/dev/sql-syntax/functions/text/ascii","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/text/chr","path":"/docs/dev/sql-syntax/functions/text/chr","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/text/concat","path":"/docs/dev/sql-syntax/functions/text/concat","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/text/concat-ws","path":"/docs/dev/sql-syntax/functions/text/concat-ws","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/text/find-idx","path":"/docs/dev/sql-syntax/functions/text/find-idx","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/text/initcap","path":"/docs/dev/sql-syntax/functions/text/initcap","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/text/left","path":"/docs/dev/sql-syntax/functions/text/left","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/text/lower","path":"/docs/dev/sql-syntax/functions/text/lower","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/text/lpad","path":"/docs/dev/sql-syntax/functions/text/lpad","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/text/ltrim","path":"/docs/dev/sql-syntax/functions/text/ltrim","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/text/position","path":"/docs/dev/sql-syntax/functions/text/position","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/text/repeat","path":"/docs/dev/sql-syntax/functions/text/repeat","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/text/reverse","path":"/docs/dev/sql-syntax/functions/text/reverse","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/text/right","path":"/docs/dev/sql-syntax/functions/text/right","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/text/rpad","path":"/docs/dev/sql-syntax/functions/text/rpad","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/text/rtrim","path":"/docs/dev/sql-syntax/functions/text/rtrim","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/text/substr","path":"/docs/dev/sql-syntax/functions/text/substr","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/text/trim","path":"/docs/dev/sql-syntax/functions/text/trim","sidebar":"autoSidebar"},{"id":"sql-syntax/functions/text/upper","path":"/docs/dev/sql-syntax/functions/text/upper","sidebar":"autoSidebar"},{"id":"sql-syntax/intro","path":"/docs/dev/sql-syntax/intro","sidebar":"autoSidebar"},{"id":"sql-syntax/statements/data-definition/alter-table","path":"/docs/dev/sql-syntax/statements/data-definition/alter-table","sidebar":"autoSidebar"},{"id":"sql-syntax/statements/data-definition/create-index","path":"/docs/dev/sql-syntax/statements/data-definition/create-index","sidebar":"autoSidebar"},{"id":"sql-syntax/statements/data-definition/create-table","path":"/docs/dev/sql-syntax/statements/data-definition/create-table","sidebar":"autoSidebar"},{"id":"sql-syntax/statements/data-definition/drop-index","path":"/docs/dev/sql-syntax/statements/data-definition/drop-index","sidebar":"autoSidebar"},{"id":"sql-syntax/statements/data-definition/drop-table","path":"/docs/dev/sql-syntax/statements/data-definition/drop-table","sidebar":"autoSidebar"},{"id":"sql-syntax/statements/data-manipulation/delete","path":"/docs/dev/sql-syntax/statements/data-manipulation/delete","sidebar":"autoSidebar"},{"id":"sql-syntax/statements/data-manipulation/insert","path":"/docs/dev/sql-syntax/statements/data-manipulation/insert","sidebar":"autoSidebar"},{"id":"sql-syntax/statements/data-manipulation/update","path":"/docs/dev/sql-syntax/statements/data-manipulation/update","sidebar":"autoSidebar"},{"id":"sql-syntax/statements/metadata/data-dictionary","path":"/docs/dev/sql-syntax/statements/metadata/data-dictionary","sidebar":"autoSidebar"},{"id":"sql-syntax/statements/metadata/show-tables","path":"/docs/dev/sql-syntax/statements/metadata/show-tables","sidebar":"autoSidebar"},{"id":"sql-syntax/statements/querying/aggregation","path":"/docs/dev/sql-syntax/statements/querying/aggregation","sidebar":"autoSidebar"},{"id":"sql-syntax/statements/querying/join","path":"/docs/dev/sql-syntax/statements/querying/join","sidebar":"autoSidebar"},{"id":"sql-syntax/statements/querying/limit","path":"/docs/dev/sql-syntax/statements/querying/limit","sidebar":"autoSidebar"},{"id":"sql-syntax/statements/querying/schemaless","path":"/docs/dev/sql-syntax/statements/querying/schemaless","sidebar":"autoSidebar"},{"id":"sql-syntax/statements/querying/where","path":"/docs/dev/sql-syntax/statements/querying/where","sidebar":"autoSidebar"},{"id":"sql-syntax/statements/transaction","path":"/docs/dev/sql-syntax/statements/transaction","sidebar":"autoSidebar"},{"id":"storages/developing-custom-storages/intro","path":"/docs/dev/storages/developing-custom-storages/intro","sidebar":"autoSidebar"},{"id":"storages/developing-custom-storages/store-traits/alter-table","path":"/docs/dev/storages/developing-custom-storages/store-traits/alter-table","sidebar":"autoSidebar"},{"id":"storages/developing-custom-storages/store-traits/custom-function","path":"/docs/dev/storages/developing-custom-storages/store-traits/custom-function","sidebar":"autoSidebar"},{"id":"storages/developing-custom-storages/store-traits/custom-function-mut","path":"/docs/dev/storages/developing-custom-storages/store-traits/custom-function-mut","sidebar":"autoSidebar"},{"id":"storages/developing-custom-storages/store-traits/index-mut","path":"/docs/dev/storages/developing-custom-storages/store-traits/index-mut","sidebar":"autoSidebar"},{"id":"storages/developing-custom-storages/store-traits/index-trait","path":"/docs/dev/storages/developing-custom-storages/store-traits/index-trait","sidebar":"autoSidebar"},{"id":"storages/developing-custom-storages/store-traits/metadata","path":"/docs/dev/storages/developing-custom-storages/store-traits/metadata","sidebar":"autoSidebar"},{"id":"storages/developing-custom-storages/store-traits/store","path":"/docs/dev/storages/developing-custom-storages/store-traits/store","sidebar":"autoSidebar"},{"id":"storages/developing-custom-storages/store-traits/store-mut","path":"/docs/dev/storages/developing-custom-storages/store-traits/store-mut","sidebar":"autoSidebar"},{"id":"storages/developing-custom-storages/store-traits/transaction","path":"/docs/dev/storages/developing-custom-storages/store-traits/transaction","sidebar":"autoSidebar"},{"id":"storages/developing-custom-storages/using-test-suite","path":"/docs/dev/storages/developing-custom-storages/using-test-suite","sidebar":"autoSidebar"},{"id":"storages/intro","path":"/docs/dev/storages/intro","sidebar":"autoSidebar"},{"id":"storages/supported-storages/composite-storage","path":"/docs/dev/storages/supported-storages/composite-storage","sidebar":"autoSidebar"},{"id":"storages/supported-storages/idb-storage","path":"/docs/dev/storages/supported-storages/idb-storage","sidebar":"autoSidebar"},{"id":"storages/supported-storages/json-storage","path":"/docs/dev/storages/supported-storages/json-storage","sidebar":"autoSidebar"},{"id":"storages/supported-storages/memory-storage","path":"/docs/dev/storages/supported-storages/memory-storage","sidebar":"autoSidebar"},{"id":"storages/supported-storages/shared-memory-storage","path":"/docs/dev/storages/supported-storages/shared-memory-storage","sidebar":"autoSidebar"},{"id":"storages/supported-storages/sled-storage","path":"/docs/dev/storages/supported-storages/sled-storage","sidebar":"autoSidebar"},{"id":"storages/supported-storages/web-storage","path":"/docs/dev/storages/supported-storages/web-storage","sidebar":"autoSidebar"}],"draftIds":[],"sidebars":{"autoSidebar":{"link":{"path":"/docs/dev/","label":"index"}}}}],"breadcrumbs":true}}}'),s=JSON.parse('{"defaultLocale":"en","locales":["en"],"path":"i18n","currentLocale":"en","localeConfigs":{"en":{"label":"English","direction":"ltr","htmlLang":"en","calendar":"gregory","path":"en"}}}');var i=n(7529);const l=JSON.parse('{"docusaurusVersion":"2.4.1","siteVersion":"0.0.0","pluginVersions":{"docusaurus-plugin-content-docs":{"type":"package","name":"@docusaurus/plugin-content-docs","version":"2.4.1"},"docusaurus-plugin-content-blog":{"type":"package","name":"@docusaurus/plugin-content-blog","version":"2.4.1"},"docusaurus-plugin-sitemap":{"type":"package","name":"@docusaurus/plugin-sitemap","version":"2.4.1"},"docusaurus-theme-classic":{"type":"package","name":"@docusaurus/theme-classic","version":"2.4.1"}}}'),c={siteConfig:r.default,siteMetadata:l,globalData:o,i18n:s,codeTranslations:i},u=a.createContext(c);function d(e){let{children:t}=e;return a.createElement(u.Provider,{value:c},t)}},4763:(e,t,n)=>{"use strict";n.d(t,{Z:()=>f});var a=n(7294),r=n(412),o=n(5742),s=n(8780),i=n(7961);function l(e){let{error:t,tryAgain:n}=e;return a.createElement("div",{style:{display:"flex",flexDirection:"column",justifyContent:"center",alignItems:"flex-start",minHeight:"100vh",width:"100%",maxWidth:"80ch",fontSize:"20px",margin:"0 auto",padding:"1rem"}},a.createElement("h1",{style:{fontSize:"3rem"}},"This page crashed"),a.createElement("button",{type:"button",onClick:n,style:{margin:"1rem 0",fontSize:"2rem",cursor:"pointer",borderRadius:20,padding:"1rem"}},"Try again"),a.createElement(c,{error:t}))}function c(e){let{error:t}=e;const n=(0,s.getErrorCausalChain)(t).map((e=>e.message)).join("\n\nCause:\n");return a.createElement("p",{style:{whiteSpace:"pre-wrap"}},n)}function u(e){let{error:t,tryAgain:n}=e;return a.createElement(f,{fallback:()=>a.createElement(l,{error:t,tryAgain:n})},a.createElement(o.Z,null,a.createElement("title",null,"Page Error")),a.createElement(i.Z,null,a.createElement(l,{error:t,tryAgain:n})))}const d=e=>a.createElement(u,e);class f extends a.Component{constructor(e){super(e),this.state={error:null}}componentDidCatch(e){r.Z.canUseDOM&&this.setState({error:e})}render(){const{children:e}=this.props,{error:t}=this.state;if(t){const e={error:t,tryAgain:()=>this.setState({error:null})};return(this.props.fallback??d)(e)}return e??null}}},412:(e,t,n)=>{"use strict";n.d(t,{Z:()=>r});const a="undefined"!=typeof window&&"document"in window&&"createElement"in window.document,r={canUseDOM:a,canUseEventListeners:a&&("addEventListener"in window||"attachEvent"in window),canUseIntersectionObserver:a&&"IntersectionObserver"in window,canUseViewport:a&&"screen"in window}},5742:(e,t,n)=>{"use strict";n.d(t,{Z:()=>o});var a=n(7294),r=n(405);function o(e){return a.createElement(r.ql,e)}},9960:(e,t,n)=>{"use strict";n.d(t,{Z:()=>p});var a=n(7462),r=n(7294),o=n(3727),s=n(8780),i=n(2263),l=n(3919),c=n(412);const u=r.createContext({collectLink:()=>{}});var d=n(4996);function f(e,t){let{isNavLink:n,to:f,href:p,activeClassName:m,isActive:g,"data-noBrokenLinkCheck":h,autoAddBaseUrl:b=!0,...v}=e;const{siteConfig:{trailingSlash:y,baseUrl:x}}=(0,i.Z)(),{withBaseUrl:w}=(0,d.C)(),S=(0,r.useContext)(u),E=(0,r.useRef)(null);(0,r.useImperativeHandle)(t,(()=>E.current));const k=f||p;const _=(0,l.Z)(k),C=k?.replace("pathname://","");let T=void 0!==C?(q=C,b&&(e=>e.startsWith("/"))(q)?w(q):q):void 0;var q;T&&_&&(T=(0,s.applyTrailingSlash)(T,{trailingSlash:y,baseUrl:x}));const A=(0,r.useRef)(!1),L=n?o.OL:o.rU,N=c.Z.canUseIntersectionObserver,O=(0,r.useRef)(),P=()=>{A.current||null==T||(window.docusaurus.preload(T),A.current=!0)};(0,r.useEffect)((()=>(!N&&_&&null!=T&&window.docusaurus.prefetch(T),()=>{N&&O.current&&O.current.disconnect()})),[O,T,N,_]);const I=T?.startsWith("#")??!1,R=!T||!_||I;return R||h||S.collectLink(T),R?r.createElement("a",(0,a.Z)({ref:E,href:T},k&&!_&&{target:"_blank",rel:"noopener noreferrer"},v)):r.createElement(L,(0,a.Z)({},v,{onMouseEnter:P,onTouchStart:P,innerRef:e=>{E.current=e,N&&e&&_&&(O.current=new window.IntersectionObserver((t=>{t.forEach((t=>{e===t.target&&(t.isIntersecting||t.intersectionRatio>0)&&(O.current.unobserve(e),O.current.disconnect(),null!=T&&window.docusaurus.prefetch(T))}))})),O.current.observe(e))},to:T},n&&{isActive:g,activeClassName:m}))}const p=r.forwardRef(f)},1875:(e,t,n)=>{"use strict";n.d(t,{Z:()=>a});const a=()=>null},5999:(e,t,n)=>{"use strict";n.d(t,{Z:()=>l,I:()=>i});var a=n(7294);function r(e,t){const n=e.split(/(\{\w+\})/).map(((e,n)=>{if(n%2==1){const n=t?.[e.slice(1,-1)];if(void 0!==n)return n}return e}));return n.some((e=>(0,a.isValidElement)(e)))?n.map(((e,t)=>(0,a.isValidElement)(e)?a.cloneElement(e,{key:t}):e)).filter((e=>""!==e)):n.join("")}var o=n(7529);function s(e){let{id:t,message:n}=e;if(void 0===t&&void 0===n)throw new Error("Docusaurus translation declarations must have at least a translation id or a default translation message");return o[t??n]??n??t}function i(e,t){let{message:n,id:a}=e;return r(s({message:n,id:a}),t)}function l(e){let{children:t,id:n,values:o}=e;if(t&&"string"!=typeof t)throw console.warn("Illegal <Translate> children",t),new Error("The Docusaurus <Translate> component only accept simple string values");const i=s({message:t,id:n});return a.createElement(a.Fragment,null,r(i,o))}},9935:(e,t,n)=>{"use strict";n.d(t,{m:()=>a});const a="default"},3919:(e,t,n)=>{"use strict";function a(e){return/^(?:\w*:|\/\/)/.test(e)}function r(e){return void 0!==e&&!a(e)}n.d(t,{Z:()=>r,b:()=>a})},4996:(e,t,n)=>{"use strict";n.d(t,{C:()=>s,Z:()=>i});var a=n(7294),r=n(2263),o=n(3919);function s(){const{siteConfig:{baseUrl:e,url:t}}=(0,r.Z)(),n=(0,a.useCallback)(((n,a)=>function(e,t,n,a){let{forcePrependBaseUrl:r=!1,absolute:s=!1}=void 0===a?{}:a;if(!n||n.startsWith("#")||(0,o.b)(n))return n;if(r)return t+n.replace(/^\//,"");if(n===t.replace(/\/$/,""))return t;const i=n.startsWith(t)?n:t+n.replace(/^\//,"");return s?e+i:i}(t,e,n,a)),[t,e]);return{withBaseUrl:n}}function i(e,t){void 0===t&&(t={});const{withBaseUrl:n}=s();return n(e,t)}},2263:(e,t,n)=>{"use strict";n.d(t,{Z:()=>o});var a=n(7294),r=n(8940);function o(){return(0,a.useContext)(r._)}},2389:(e,t,n)=>{"use strict";n.d(t,{Z:()=>o});var a=n(7294),r=n(8934);function o(){return(0,a.useContext)(r._)}},9670:(e,t,n)=>{"use strict";n.d(t,{Z:()=>r});const a=e=>"object"==typeof e&&!!e&&Object.keys(e).length>0;function r(e){const t={};return function e(n,r){Object.entries(n).forEach((n=>{let[o,s]=n;const i=r?`${r}.${o}`:o;a(s)?e(s,i):t[i]=s}))}(e),t}},226:(e,t,n)=>{"use strict";n.d(t,{_:()=>r,z:()=>o});var a=n(7294);const r=a.createContext(null);function o(e){let{children:t,value:n}=e;const o=a.useContext(r),s=(0,a.useMemo)((()=>function(e){let{parent:t,value:n}=e;if(!t){if(!n)throw new Error("Unexpected: no Docusaurus route context found");if(!("plugin"in n))throw new Error("Unexpected: Docusaurus topmost route context has no `plugin` attribute");return n}const a={...t.data,...n?.data};return{plugin:t.plugin,data:a}}({parent:o,value:n})),[o,n]);return a.createElement(r.Provider,{value:s},t)}},143:(e,t,n)=>{"use strict";n.d(t,{Iw:()=>g,gA:()=>f,_r:()=>u,Jo:()=>h,zh:()=>d,yW:()=>m,gB:()=>p});var a=n(6550),r=n(2263),o=n(9935);function s(e,t){void 0===t&&(t={});const n=function(){const{globalData:e}=(0,r.Z)();return e}()[e];if(!n&&t.failfast)throw new Error(`Docusaurus plugin global data not found for "${e}" plugin.`);return n}const i=e=>e.versions.find((e=>e.isLast));function l(e,t){const n=function(e,t){const n=i(e);return[...e.versions.filter((e=>e!==n)),n].find((e=>!!(0,a.LX)(t,{path:e.path,exact:!1,strict:!1})))}(e,t),r=n?.docs.find((e=>!!(0,a.LX)(t,{path:e.path,exact:!0,strict:!1})));return{activeVersion:n,activeDoc:r,alternateDocVersions:r?function(t){const n={};return e.versions.forEach((e=>{e.docs.forEach((a=>{a.id===t&&(n[e.name]=a)}))})),n}(r.id):{}}}const c={},u=()=>s("docusaurus-plugin-content-docs")??c,d=e=>function(e,t,n){void 0===t&&(t=o.m),void 0===n&&(n={});const a=s(e),r=a?.[t];if(!r&&n.failfast)throw new Error(`Docusaurus plugin global data not found for "${e}" plugin with id "${t}".`);return r}("docusaurus-plugin-content-docs",e,{failfast:!0});function f(e){void 0===e&&(e={});const t=u(),{pathname:n}=(0,a.TH)();return function(e,t,n){void 0===n&&(n={});const r=Object.entries(e).sort(((e,t)=>t[1].path.localeCompare(e[1].path))).find((e=>{let[,n]=e;return!!(0,a.LX)(t,{path:n.path,exact:!1,strict:!1})})),o=r?{pluginId:r[0],pluginData:r[1]}:void 0;if(!o&&n.failfast)throw new Error(`Can't find active docs plugin for "${t}" pathname, while it was expected to be found. Maybe you tried to use a docs feature that can only be used on a docs-related page? Existing docs plugin paths are: ${Object.values(e).map((e=>e.path)).join(", ")}`);return o}(t,n,e)}function p(e){return d(e).versions}function m(e){const t=d(e);return i(t)}function g(e){const t=d(e),{pathname:n}=(0,a.TH)();return l(t,n)}function h(e){const t=d(e),{pathname:n}=(0,a.TH)();return function(e,t){const n=i(e);return{latestDocSuggestion:l(e,t).alternateDocVersions[n.name],latestVersionSuggestion:n}}(t,n)}},8320:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>o});var a=n(4865),r=n.n(a);r().configure({showSpinner:!1});const o={onRouteUpdate(e){let{location:t,previousLocation:n}=e;if(n&&t.pathname!==n.pathname){const e=window.setTimeout((()=>{r().start()}),200);return()=>window.clearTimeout(e)}},onRouteDidUpdate(){r().done()}}},3310:(e,t,n)=>{"use strict";n.r(t);var a=n(7410),r=n(6809);!function(e){const{themeConfig:{prism:t}}=r.default,{additionalLanguages:a}=t;globalThis.Prism=e,a.forEach((e=>{n(6045)(`./prism-${e}`)})),delete globalThis.Prism}(a.Z)},9471:(e,t,n)=>{"use strict";n.d(t,{Z:()=>o});var a=n(7294);const r={iconExternalLink:"iconExternalLink_nPIU"};function o(e){let{width:t=13.5,height:n=13.5}=e;return a.createElement("svg",{width:t,height:n,"aria-hidden":"true",viewBox:"0 0 24 24",className:r.iconExternalLink},a.createElement("path",{fill:"currentColor",d:"M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"}))}},7961:(e,t,n)=>{"use strict";n.d(t,{Z:()=>dt});var a=n(7294),r=n(6010),o=n(4763),s=n(1944),i=n(7462),l=n(6550),c=n(5999),u=n(5936);const d="__docusaurus_skipToContent_fallback";function f(e){e.setAttribute("tabindex","-1"),e.focus(),e.removeAttribute("tabindex")}function p(){const e=(0,a.useRef)(null),{action:t}=(0,l.k6)(),n=(0,a.useCallback)((e=>{e.preventDefault();const t=document.querySelector("main:first-of-type")??document.getElementById(d);t&&f(t)}),[]);return(0,u.S)((n=>{let{location:a}=n;e.current&&!a.hash&&"PUSH"===t&&f(e.current)})),{containerRef:e,onClick:n}}const m=(0,c.I)({id:"theme.common.skipToMainContent",description:"The skip to content label used for accessibility, allowing to rapidly navigate to main content with keyboard tab/enter navigation",message:"Skip to main content"});function g(e){const t=e.children??m,{containerRef:n,onClick:r}=p();return a.createElement("div",{ref:n,role:"region","aria-label":m},a.createElement("a",(0,i.Z)({},e,{href:`#${d}`,onClick:r}),t))}var h=n(5281),b=n(9727);const v={skipToContent:"skipToContent_fXgn"};function y(){return a.createElement(g,{className:v.skipToContent})}var x=n(6668),w=n(9689);function S(e){let{width:t=21,height:n=21,color:r="currentColor",strokeWidth:o=1.2,className:s,...l}=e;return a.createElement("svg",(0,i.Z)({viewBox:"0 0 15 15",width:t,height:n},l),a.createElement("g",{stroke:r,strokeWidth:o},a.createElement("path",{d:"M.75.75l13.5 13.5M14.25.75L.75 14.25"})))}const E={closeButton:"closeButton_CVFx"};function k(e){return a.createElement("button",(0,i.Z)({type:"button","aria-label":(0,c.I)({id:"theme.AnnouncementBar.closeButtonAriaLabel",message:"Close",description:"The ARIA label for close button of announcement bar"})},e,{className:(0,r.Z)("clean-btn close",E.closeButton,e.className)}),a.createElement(S,{width:14,height:14,strokeWidth:3.1}))}const _={content:"content_knG7"};function C(e){const{announcementBar:t}=(0,x.L)(),{content:n}=t;return a.createElement("div",(0,i.Z)({},e,{className:(0,r.Z)(_.content,e.className),dangerouslySetInnerHTML:{__html:n}}))}const T={announcementBar:"announcementBar_mb4j",announcementBarPlaceholder:"announcementBarPlaceholder_vyr4",announcementBarClose:"announcementBarClose_gvF7",announcementBarContent:"announcementBarContent_xLdY"};function q(){const{announcementBar:e}=(0,x.L)(),{isActive:t,close:n}=(0,w.nT)();if(!t)return null;const{backgroundColor:r,textColor:o,isCloseable:s}=e;return a.createElement("div",{className:T.announcementBar,style:{backgroundColor:r,color:o},role:"banner"},s&&a.createElement("div",{className:T.announcementBarPlaceholder}),a.createElement(C,{className:T.announcementBarContent}),s&&a.createElement(k,{onClick:n,className:T.announcementBarClose}))}var A=n(2961),L=n(2466);var N=n(902),O=n(3102);const P=a.createContext(null);function I(e){let{children:t}=e;const n=function(){const e=(0,A.e)(),t=(0,O.HY)(),[n,r]=(0,a.useState)(!1),o=null!==t.component,s=(0,N.D9)(o);return(0,a.useEffect)((()=>{o&&!s&&r(!0)}),[o,s]),(0,a.useEffect)((()=>{o?e.shown||r(!0):r(!1)}),[e.shown,o]),(0,a.useMemo)((()=>[n,r]),[n])}();return a.createElement(P.Provider,{value:n},t)}function R(e){if(e.component){const t=e.component;return a.createElement(t,e.props)}}function M(){const e=(0,a.useContext)(P);if(!e)throw new N.i6("NavbarSecondaryMenuDisplayProvider");const[t,n]=e,r=(0,a.useCallback)((()=>n(!1)),[n]),o=(0,O.HY)();return(0,a.useMemo)((()=>({shown:t,hide:r,content:R(o)})),[r,o,t])}function D(e){let{header:t,primaryMenu:n,secondaryMenu:o}=e;const{shown:s}=M();return a.createElement("div",{className:"navbar-sidebar"},t,a.createElement("div",{className:(0,r.Z)("navbar-sidebar__items",{"navbar-sidebar__items--show-secondary":s})},a.createElement("div",{className:"navbar-sidebar__item menu"},n),a.createElement("div",{className:"navbar-sidebar__item menu"},o)))}var F=n(2949),B=n(2389);function j(e){return a.createElement("svg",(0,i.Z)({viewBox:"0 0 24 24",width:24,height:24},e),a.createElement("path",{fill:"currentColor",d:"M12,9c1.65,0,3,1.35,3,3s-1.35,3-3,3s-3-1.35-3-3S10.35,9,12,9 M12,7c-2.76,0-5,2.24-5,5s2.24,5,5,5s5-2.24,5-5 S14.76,7,12,7L12,7z M2,13l2,0c0.55,0,1-0.45,1-1s-0.45-1-1-1l-2,0c-0.55,0-1,0.45-1,1S1.45,13,2,13z M20,13l2,0c0.55,0,1-0.45,1-1 s-0.45-1-1-1l-2,0c-0.55,0-1,0.45-1,1S19.45,13,20,13z M11,2v2c0,0.55,0.45,1,1,1s1-0.45,1-1V2c0-0.55-0.45-1-1-1S11,1.45,11,2z M11,20v2c0,0.55,0.45,1,1,1s1-0.45,1-1v-2c0-0.55-0.45-1-1-1C11.45,19,11,19.45,11,20z M5.99,4.58c-0.39-0.39-1.03-0.39-1.41,0 c-0.39,0.39-0.39,1.03,0,1.41l1.06,1.06c0.39,0.39,1.03,0.39,1.41,0s0.39-1.03,0-1.41L5.99,4.58z M18.36,16.95 c-0.39-0.39-1.03-0.39-1.41,0c-0.39,0.39-0.39,1.03,0,1.41l1.06,1.06c0.39,0.39,1.03,0.39,1.41,0c0.39-0.39,0.39-1.03,0-1.41 L18.36,16.95z M19.42,5.99c0.39-0.39,0.39-1.03,0-1.41c-0.39-0.39-1.03-0.39-1.41,0l-1.06,1.06c-0.39,0.39-0.39,1.03,0,1.41 s1.03,0.39,1.41,0L19.42,5.99z M7.05,18.36c0.39-0.39,0.39-1.03,0-1.41c-0.39-0.39-1.03-0.39-1.41,0l-1.06,1.06 c-0.39,0.39-0.39,1.03,0,1.41s1.03,0.39,1.41,0L7.05,18.36z"}))}function z(e){return a.createElement("svg",(0,i.Z)({viewBox:"0 0 24 24",width:24,height:24},e),a.createElement("path",{fill:"currentColor",d:"M9.37,5.51C9.19,6.15,9.1,6.82,9.1,7.5c0,4.08,3.32,7.4,7.4,7.4c0.68,0,1.35-0.09,1.99-0.27C17.45,17.19,14.93,19,12,19 c-3.86,0-7-3.14-7-7C5,9.07,6.81,6.55,9.37,5.51z M12,3c-4.97,0-9,4.03-9,9s4.03,9,9,9s9-4.03,9-9c0-0.46-0.04-0.92-0.1-1.36 c-0.98,1.37-2.58,2.26-4.4,2.26c-2.98,0-5.4-2.42-5.4-5.4c0-1.81,0.89-3.42,2.26-4.4C12.92,3.04,12.46,3,12,3L12,3z"}))}const $={toggle:"toggle_vylO",toggleButton:"toggleButton_gllP",darkToggleIcon:"darkToggleIcon_wfgR",lightToggleIcon:"lightToggleIcon_pyhR",toggleButtonDisabled:"toggleButtonDisabled_aARS"};function U(e){let{className:t,buttonClassName:n,value:o,onChange:s}=e;const i=(0,B.Z)(),l=(0,c.I)({message:"Switch between dark and light mode (currently {mode})",id:"theme.colorToggle.ariaLabel",description:"The ARIA label for the navbar color mode toggle"},{mode:"dark"===o?(0,c.I)({message:"dark mode",id:"theme.colorToggle.ariaLabel.mode.dark",description:"The name for the dark color mode"}):(0,c.I)({message:"light mode",id:"theme.colorToggle.ariaLabel.mode.light",description:"The name for the light color mode"})});return a.createElement("div",{className:(0,r.Z)($.toggle,t)},a.createElement("button",{className:(0,r.Z)("clean-btn",$.toggleButton,!i&&$.toggleButtonDisabled,n),type:"button",onClick:()=>s("dark"===o?"light":"dark"),disabled:!i,title:l,"aria-label":l,"aria-live":"polite"},a.createElement(j,{className:(0,r.Z)($.toggleIcon,$.lightToggleIcon)}),a.createElement(z,{className:(0,r.Z)($.toggleIcon,$.darkToggleIcon)})))}const Z=a.memo(U),H={darkNavbarColorModeToggle:"darkNavbarColorModeToggle_X3D1"};function V(e){let{className:t}=e;const n=(0,x.L)().navbar.style,r=(0,x.L)().colorMode.disableSwitch,{colorMode:o,setColorMode:s}=(0,F.I)();return r?null:a.createElement(Z,{className:t,buttonClassName:"dark"===n?H.darkNavbarColorModeToggle:void 0,value:o,onChange:s})}var W=n(1327);function G(){return a.createElement(W.Z,{className:"navbar__brand",imageClassName:"navbar__logo",titleClassName:"navbar__title text--truncate"})}function Y(){const e=(0,A.e)();return a.createElement("button",{type:"button","aria-label":(0,c.I)({id:"theme.docs.sidebar.closeSidebarButtonAriaLabel",message:"Close navigation bar",description:"The ARIA label for close button of mobile sidebar"}),className:"clean-btn navbar-sidebar__close",onClick:()=>e.toggle()},a.createElement(S,{color:"var(--ifm-color-emphasis-600)"}))}function K(){return a.createElement("div",{className:"navbar-sidebar__brand"},a.createElement(G,null),a.createElement(V,{className:"margin-right--md"}),a.createElement(Y,null))}var Q=n(9960),X=n(4996),J=n(3919);function ee(e,t){return void 0!==e&&void 0!==t&&new RegExp(e,"gi").test(t)}var te=n(9471);function ne(e){let{activeBasePath:t,activeBaseRegex:n,to:r,href:o,label:s,html:l,isDropdownLink:c,prependBaseUrlToHref:u,...d}=e;const f=(0,X.Z)(r),p=(0,X.Z)(t),m=(0,X.Z)(o,{forcePrependBaseUrl:!0}),g=s&&o&&!(0,J.Z)(o),h=l?{dangerouslySetInnerHTML:{__html:l}}:{children:a.createElement(a.Fragment,null,s,g&&a.createElement(te.Z,c&&{width:12,height:12}))};return o?a.createElement(Q.Z,(0,i.Z)({href:u?m:o},d,h)):a.createElement(Q.Z,(0,i.Z)({to:f,isNavLink:!0},(t||n)&&{isActive:(e,t)=>n?ee(n,t.pathname):t.pathname.startsWith(p)},d,h))}function ae(e){let{className:t,isDropdownItem:n=!1,...o}=e;const s=a.createElement(ne,(0,i.Z)({className:(0,r.Z)(n?"dropdown__link":"navbar__item navbar__link",t),isDropdownLink:n},o));return n?a.createElement("li",null,s):s}function re(e){let{className:t,isDropdownItem:n,...o}=e;return a.createElement("li",{className:"menu__list-item"},a.createElement(ne,(0,i.Z)({className:(0,r.Z)("menu__link",t)},o)))}function oe(e){let{mobile:t=!1,position:n,...r}=e;const o=t?re:ae;return a.createElement(o,(0,i.Z)({},r,{activeClassName:r.activeClassName??(t?"menu__link--active":"navbar__link--active")}))}var se=n(6043),ie=n(8596),le=n(2263);function ce(e,t){return e.some((e=>function(e,t){return!!(0,ie.Mg)(e.to,t)||!!ee(e.activeBaseRegex,t)||!(!e.activeBasePath||!t.startsWith(e.activeBasePath))}(e,t)))}function ue(e){let{items:t,position:n,className:o,onClick:s,...l}=e;const c=(0,a.useRef)(null),[u,d]=(0,a.useState)(!1);return(0,a.useEffect)((()=>{const e=e=>{c.current&&!c.current.contains(e.target)&&d(!1)};return document.addEventListener("mousedown",e),document.addEventListener("touchstart",e),document.addEventListener("focusin",e),()=>{document.removeEventListener("mousedown",e),document.removeEventListener("touchstart",e),document.removeEventListener("focusin",e)}}),[c]),a.createElement("div",{ref:c,className:(0,r.Z)("navbar__item","dropdown","dropdown--hoverable",{"dropdown--right":"right"===n,"dropdown--show":u})},a.createElement(ne,(0,i.Z)({"aria-haspopup":"true","aria-expanded":u,role:"button",href:l.to?void 0:"#",className:(0,r.Z)("navbar__link",o)},l,{onClick:l.to?void 0:e=>e.preventDefault(),onKeyDown:e=>{"Enter"===e.key&&(e.preventDefault(),d(!u))}}),l.children??l.label),a.createElement("ul",{className:"dropdown__menu"},t.map(((e,t)=>a.createElement(ke,(0,i.Z)({isDropdownItem:!0,activeClassName:"dropdown__link--active"},e,{key:t}))))))}function de(e){let{items:t,className:n,position:o,onClick:s,...c}=e;const u=function(){const{siteConfig:{baseUrl:e}}=(0,le.Z)(),{pathname:t}=(0,l.TH)();return t.replace(e,"/")}(),d=ce(t,u),{collapsed:f,toggleCollapsed:p,setCollapsed:m}=(0,se.u)({initialState:()=>!d});return(0,a.useEffect)((()=>{d&&m(!d)}),[u,d,m]),a.createElement("li",{className:(0,r.Z)("menu__list-item",{"menu__list-item--collapsed":f})},a.createElement(ne,(0,i.Z)({role:"button",className:(0,r.Z)("menu__link menu__link--sublist menu__link--sublist-caret",n)},c,{onClick:e=>{e.preventDefault(),p()}}),c.children??c.label),a.createElement(se.z,{lazy:!0,as:"ul",className:"menu__list",collapsed:f},t.map(((e,t)=>a.createElement(ke,(0,i.Z)({mobile:!0,isDropdownItem:!0,onClick:s,activeClassName:"menu__link--active"},e,{key:t}))))))}function fe(e){let{mobile:t=!1,...n}=e;const r=t?de:ue;return a.createElement(r,n)}var pe=n(4711);function me(e){let{width:t=20,height:n=20,...r}=e;return a.createElement("svg",(0,i.Z)({viewBox:"0 0 24 24",width:t,height:n,"aria-hidden":!0},r),a.createElement("path",{fill:"currentColor",d:"M12.87 15.07l-2.54-2.51.03-.03c1.74-1.94 2.98-4.17 3.71-6.53H17V4h-7V2H8v2H1v1.99h11.17C11.5 7.92 10.44 9.75 9 11.35 8.07 10.32 7.3 9.19 6.69 8h-2c.73 1.63 1.73 3.17 2.98 4.56l-5.09 5.02L4 19l5-5 3.11 3.11.76-2.04zM18.5 10h-2L12 22h2l1.12-3h4.75L21 22h2l-4.5-12zm-2.62 7l1.62-4.33L19.12 17h-3.24z"}))}const ge="iconLanguage_nlXk";var he=n(1875);const be={searchBox:"searchBox_ZlJk"};function ve(e){let{children:t,className:n}=e;return a.createElement("div",{className:(0,r.Z)(n,be.searchBox)},t)}var ye=n(143),xe=n(2802);var we=n(373);const Se=e=>e.docs.find((t=>t.id===e.mainDocId));const Ee={default:oe,localeDropdown:function(e){let{mobile:t,dropdownItemsBefore:n,dropdownItemsAfter:r,...o}=e;const{i18n:{currentLocale:s,locales:u,localeConfigs:d}}=(0,le.Z)(),f=(0,pe.l)(),{search:p,hash:m}=(0,l.TH)(),g=[...n,...u.map((e=>{const n=`${`pathname://${f.createUrl({locale:e,fullyQualified:!1})}`}${p}${m}`;return{label:d[e].label,lang:d[e].htmlLang,to:n,target:"_self",autoAddBaseUrl:!1,className:e===s?t?"menu__link--active":"dropdown__link--active":""}})),...r],h=t?(0,c.I)({message:"Languages",id:"theme.navbar.mobileLanguageDropdown.label",description:"The label for the mobile language switcher dropdown"}):d[s].label;return a.createElement(fe,(0,i.Z)({},o,{mobile:t,label:a.createElement(a.Fragment,null,a.createElement(me,{className:ge}),h),items:g}))},search:function(e){let{mobile:t,className:n}=e;return t?null:a.createElement(ve,{className:n},a.createElement(he.Z,null))},dropdown:fe,html:function(e){let{value:t,className:n,mobile:o=!1,isDropdownItem:s=!1}=e;const i=s?"li":"div";return a.createElement(i,{className:(0,r.Z)({navbar__item:!o&&!s,"menu__list-item":o},n),dangerouslySetInnerHTML:{__html:t}})},doc:function(e){let{docId:t,label:n,docsPluginId:r,...o}=e;const{activeDoc:s}=(0,ye.Iw)(r),l=(0,xe.vY)(t,r);return null===l?null:a.createElement(oe,(0,i.Z)({exact:!0},o,{isActive:()=>s?.path===l.path||!!s?.sidebar&&s.sidebar===l.sidebar,label:n??l.id,to:l.path}))},docSidebar:function(e){let{sidebarId:t,label:n,docsPluginId:r,...o}=e;const{activeDoc:s}=(0,ye.Iw)(r),l=(0,xe.oz)(t,r).link;if(!l)throw new Error(`DocSidebarNavbarItem: Sidebar with ID "${t}" doesn't have anything to be linked to.`);return a.createElement(oe,(0,i.Z)({exact:!0},o,{isActive:()=>s?.sidebar===t,label:n??l.label,to:l.path}))},docsVersion:function(e){let{label:t,to:n,docsPluginId:r,...o}=e;const s=(0,xe.lO)(r)[0],l=t??s.label,c=n??(e=>e.docs.find((t=>t.id===e.mainDocId)))(s).path;return a.createElement(oe,(0,i.Z)({},o,{label:l,to:c}))},docsVersionDropdown:function(e){let{mobile:t,docsPluginId:n,dropdownActiveClassDisabled:r,dropdownItemsBefore:o,dropdownItemsAfter:s,...u}=e;const{search:d,hash:f}=(0,l.TH)(),p=(0,ye.Iw)(n),m=(0,ye.gB)(n),{savePreferredVersionName:g}=(0,we.J)(n),h=[...o,...m.map((e=>{const t=p.alternateDocVersions[e.name]??Se(e);return{label:e.label,to:`${t.path}${d}${f}`,isActive:()=>e===p.activeVersion,onClick:()=>g(e.name)}})),...s],b=(0,xe.lO)(n)[0],v=t&&h.length>1?(0,c.I)({id:"theme.navbar.mobileVersionsDropdown.label",message:"Versions",description:"The label for the navbar versions dropdown on mobile view"}):b.label,y=t&&h.length>1?void 0:Se(b).path;return h.length<=1?a.createElement(oe,(0,i.Z)({},u,{mobile:t,label:v,to:y,isActive:r?()=>!1:void 0})):a.createElement(fe,(0,i.Z)({},u,{mobile:t,label:v,to:y,items:h,isActive:r?()=>!1:void 0}))}};function ke(e){let{type:t,...n}=e;const r=function(e,t){return e&&"default"!==e?e:"items"in t?"dropdown":"default"}(t,n),o=Ee[r];if(!o)throw new Error(`No NavbarItem component found for type "${t}".`);return a.createElement(o,n)}function _e(){const e=(0,A.e)(),t=(0,x.L)().navbar.items;return a.createElement("ul",{className:"menu__list"},t.map(((t,n)=>a.createElement(ke,(0,i.Z)({mobile:!0},t,{onClick:()=>e.toggle(),key:n})))))}function Ce(e){return a.createElement("button",(0,i.Z)({},e,{type:"button",className:"clean-btn navbar-sidebar__back"}),a.createElement(c.Z,{id:"theme.navbar.mobileSidebarSecondaryMenu.backButtonLabel",description:"The label of the back button to return to main menu, inside the mobile navbar sidebar secondary menu (notably used to display the docs sidebar)"},"\u2190 Back to main menu"))}function Te(){const e=0===(0,x.L)().navbar.items.length,t=M();return a.createElement(a.Fragment,null,!e&&a.createElement(Ce,{onClick:()=>t.hide()}),t.content)}function qe(){const e=(0,A.e)();var t;return void 0===(t=e.shown)&&(t=!0),(0,a.useEffect)((()=>(document.body.style.overflow=t?"hidden":"visible",()=>{document.body.style.overflow="visible"})),[t]),e.shouldRender?a.createElement(D,{header:a.createElement(K,null),primaryMenu:a.createElement(_e,null),secondaryMenu:a.createElement(Te,null)}):null}const Ae={navbarHideable:"navbarHideable_m1mJ",navbarHidden:"navbarHidden_jGov"};function Le(e){return a.createElement("div",(0,i.Z)({role:"presentation"},e,{className:(0,r.Z)("navbar-sidebar__backdrop",e.className)}))}function Ne(e){let{children:t}=e;const{navbar:{hideOnScroll:n,style:o}}=(0,x.L)(),s=(0,A.e)(),{navbarRef:i,isNavbarVisible:l}=function(e){const[t,n]=(0,a.useState)(e),r=(0,a.useRef)(!1),o=(0,a.useRef)(0),s=(0,a.useCallback)((e=>{null!==e&&(o.current=e.getBoundingClientRect().height)}),[]);return(0,L.RF)(((t,a)=>{let{scrollY:s}=t;if(!e)return;if(s<o.current)return void n(!0);if(r.current)return void(r.current=!1);const i=a?.scrollY,l=document.documentElement.scrollHeight-o.current,c=window.innerHeight;i&&s>=i?n(!1):s+c<l&&n(!0)})),(0,u.S)((t=>{if(!e)return;const a=t.location.hash;if(a?document.getElementById(a.substring(1)):void 0)return r.current=!0,void n(!1);n(!0)})),{navbarRef:s,isNavbarVisible:t}}(n);return a.createElement("nav",{ref:i,"aria-label":(0,c.I)({id:"theme.NavBar.navAriaLabel",message:"Main",description:"The ARIA label for the main navigation"}),className:(0,r.Z)("navbar","navbar--fixed-top",n&&[Ae.navbarHideable,!l&&Ae.navbarHidden],{"navbar--dark":"dark"===o,"navbar--primary":"primary"===o,"navbar-sidebar--show":s.shown})},t,a.createElement(Le,{onClick:s.toggle}),a.createElement(qe,null))}var Oe=n(8780);const Pe={errorBoundaryError:"errorBoundaryError_a6uf"};function Ie(e){return a.createElement("button",(0,i.Z)({type:"button"},e),a.createElement(c.Z,{id:"theme.ErrorPageContent.tryAgain",description:"The label of the button to try again rendering when the React error boundary captures an error"},"Try again"))}function Re(e){let{error:t}=e;const n=(0,Oe.getErrorCausalChain)(t).map((e=>e.message)).join("\n\nCause:\n");return a.createElement("p",{className:Pe.errorBoundaryError},n)}class Me extends a.Component{componentDidCatch(e,t){throw this.props.onError(e,t)}render(){return this.props.children}}const De="right";function Fe(e){let{width:t=30,height:n=30,className:r,...o}=e;return a.createElement("svg",(0,i.Z)({className:r,width:t,height:n,viewBox:"0 0 30 30","aria-hidden":"true"},o),a.createElement("path",{stroke:"currentColor",strokeLinecap:"round",strokeMiterlimit:"10",strokeWidth:"2",d:"M4 7h22M4 15h22M4 23h22"}))}function Be(){const{toggle:e,shown:t}=(0,A.e)();return a.createElement("button",{onClick:e,"aria-label":(0,c.I)({id:"theme.docs.sidebar.toggleSidebarButtonAriaLabel",message:"Toggle navigation bar",description:"The ARIA label for hamburger menu button of mobile navigation"}),"aria-expanded":t,className:"navbar__toggle clean-btn",type:"button"},a.createElement(Fe,null))}const je={colorModeToggle:"colorModeToggle_DEke"};function ze(e){let{items:t}=e;return a.createElement(a.Fragment,null,t.map(((e,t)=>a.createElement(Me,{key:t,onError:t=>new Error(`A theme navbar item failed to render.\nPlease double-check the following navbar item (themeConfig.navbar.items) of your Docusaurus config:\n${JSON.stringify(e,null,2)}`,{cause:t})},a.createElement(ke,e)))))}function $e(e){let{left:t,right:n}=e;return a.createElement("div",{className:"navbar__inner"},a.createElement("div",{className:"navbar__items"},t),a.createElement("div",{className:"navbar__items navbar__items--right"},n))}function Ue(){const e=(0,A.e)(),t=(0,x.L)().navbar.items,[n,r]=function(e){function t(e){return"left"===(e.position??De)}return[e.filter(t),e.filter((e=>!t(e)))]}(t),o=t.find((e=>"search"===e.type));return a.createElement($e,{left:a.createElement(a.Fragment,null,!e.disabled&&a.createElement(Be,null),a.createElement(G,null),a.createElement(ze,{items:n})),right:a.createElement(a.Fragment,null,a.createElement(ze,{items:r}),a.createElement(V,{className:je.colorModeToggle}),!o&&a.createElement(ve,null,a.createElement(he.Z,null)))})}function Ze(){return a.createElement(Ne,null,a.createElement(Ue,null))}function He(e){let{item:t}=e;const{to:n,href:r,label:o,prependBaseUrlToHref:s,...l}=t,c=(0,X.Z)(n),u=(0,X.Z)(r,{forcePrependBaseUrl:!0});return a.createElement(Q.Z,(0,i.Z)({className:"footer__link-item"},r?{href:s?u:r}:{to:c},l),o,r&&!(0,J.Z)(r)&&a.createElement(te.Z,null))}function Ve(e){let{item:t}=e;return t.html?a.createElement("li",{className:"footer__item",dangerouslySetInnerHTML:{__html:t.html}}):a.createElement("li",{key:t.href??t.to,className:"footer__item"},a.createElement(He,{item:t}))}function We(e){let{column:t}=e;return a.createElement("div",{className:"col footer__col"},a.createElement("div",{className:"footer__title"},t.title),a.createElement("ul",{className:"footer__items clean-list"},t.items.map(((e,t)=>a.createElement(Ve,{key:t,item:e})))))}function Ge(e){let{columns:t}=e;return a.createElement("div",{className:"row footer__links"},t.map(((e,t)=>a.createElement(We,{key:t,column:e}))))}function Ye(){return a.createElement("span",{className:"footer__link-separator"},"\xb7")}function Ke(e){let{item:t}=e;return t.html?a.createElement("span",{className:"footer__link-item",dangerouslySetInnerHTML:{__html:t.html}}):a.createElement(He,{item:t})}function Qe(e){let{links:t}=e;return a.createElement("div",{className:"footer__links text--center"},a.createElement("div",{className:"footer__links"},t.map(((e,n)=>a.createElement(a.Fragment,{key:n},a.createElement(Ke,{item:e}),t.length!==n+1&&a.createElement(Ye,null))))))}function Xe(e){let{links:t}=e;return function(e){return"title"in e[0]}(t)?a.createElement(Ge,{columns:t}):a.createElement(Qe,{links:t})}var Je=n(941);const et={footerLogoLink:"footerLogoLink_BH7S"};function tt(e){let{logo:t}=e;const{withBaseUrl:n}=(0,X.C)(),o={light:n(t.src),dark:n(t.srcDark??t.src)};return a.createElement(Je.Z,{className:(0,r.Z)("footer__logo",t.className),alt:t.alt,sources:o,width:t.width,height:t.height,style:t.style})}function nt(e){let{logo:t}=e;return t.href?a.createElement(Q.Z,{href:t.href,className:et.footerLogoLink,target:t.target},a.createElement(tt,{logo:t})):a.createElement(tt,{logo:t})}function at(e){let{copyright:t}=e;return a.createElement("div",{className:"footer__copyright",dangerouslySetInnerHTML:{__html:t}})}function rt(e){let{style:t,links:n,logo:o,copyright:s}=e;return a.createElement("footer",{className:(0,r.Z)("footer",{"footer--dark":"dark"===t})},a.createElement("div",{className:"container container-fluid"},n,(o||s)&&a.createElement("div",{className:"footer__bottom text--center"},o&&a.createElement("div",{className:"margin-bottom--sm"},o),s)))}function ot(){const{footer:e}=(0,x.L)();if(!e)return null;const{copyright:t,links:n,logo:r,style:o}=e;return a.createElement(rt,{style:o,links:n&&n.length>0&&a.createElement(Xe,{links:n}),logo:r&&a.createElement(nt,{logo:r}),copyright:t&&a.createElement(at,{copyright:t})})}const st=a.memo(ot),it=(0,N.Qc)([F.S,w.pl,L.OC,we.L5,s.VC,function(e){let{children:t}=e;return a.createElement(O.n2,null,a.createElement(A.M,null,a.createElement(I,null,t)))}]);function lt(e){let{children:t}=e;return a.createElement(it,null,t)}function ct(e){let{error:t,tryAgain:n}=e;return a.createElement("main",{className:"container margin-vert--xl"},a.createElement("div",{className:"row"},a.createElement("div",{className:"col col--6 col--offset-3"},a.createElement("h1",{className:"hero__title"},a.createElement(c.Z,{id:"theme.ErrorPageContent.title",description:"The title of the fallback page when the page crashed"},"This page crashed.")),a.createElement("div",{className:"margin-vert--lg"},a.createElement(Ie,{onClick:n,className:"button button--primary shadow--lw"})),a.createElement("hr",null),a.createElement("div",{className:"margin-vert--md"},a.createElement(Re,{error:t})))))}const ut={mainWrapper:"mainWrapper_z2l0"};function dt(e){const{children:t,noFooter:n,wrapperClassName:i,title:l,description:c}=e;return(0,b.t)(),a.createElement(lt,null,a.createElement(s.d,{title:l,description:c}),a.createElement(y,null),a.createElement(q,null),a.createElement(Ze,null),a.createElement("div",{id:d,className:(0,r.Z)(h.k.wrapper.main,ut.mainWrapper,i)},a.createElement(o.Z,{fallback:e=>a.createElement(ct,e)},t)),!n&&a.createElement(st,null))}},1327:(e,t,n)=>{"use strict";n.d(t,{Z:()=>d});var a=n(7462),r=n(7294),o=n(9960),s=n(4996),i=n(2263),l=n(6668),c=n(941);function u(e){let{logo:t,alt:n,imageClassName:a}=e;const o={light:(0,s.Z)(t.src),dark:(0,s.Z)(t.srcDark||t.src)},i=r.createElement(c.Z,{className:t.className,sources:o,height:t.height,width:t.width,alt:n,style:t.style});return a?r.createElement("div",{className:a},i):i}function d(e){const{siteConfig:{title:t}}=(0,i.Z)(),{navbar:{title:n,logo:c}}=(0,l.L)(),{imageClassName:d,titleClassName:f,...p}=e,m=(0,s.Z)(c?.href||"/"),g=n?"":t,h=c?.alt??g;return r.createElement(o.Z,(0,a.Z)({to:m},p,c?.target&&{target:c.target}),c&&r.createElement(u,{logo:c,alt:h,imageClassName:d}),null!=n&&r.createElement("b",{className:f},n))}},197:(e,t,n)=>{"use strict";n.d(t,{Z:()=>o});var a=n(7294),r=n(5742);function o(e){let{locale:t,version:n,tag:o}=e;const s=t;return a.createElement(r.Z,null,t&&a.createElement("meta",{name:"docusaurus_locale",content:t}),n&&a.createElement("meta",{name:"docusaurus_version",content:n}),o&&a.createElement("meta",{name:"docusaurus_tag",content:o}),s&&a.createElement("meta",{name:"docsearch:language",content:s}),n&&a.createElement("meta",{name:"docsearch:version",content:n}),o&&a.createElement("meta",{name:"docsearch:docusaurus_tag",content:o}))}},941:(e,t,n)=>{"use strict";n.d(t,{Z:()=>c});var a=n(7462),r=n(7294),o=n(6010),s=n(2389),i=n(2949);const l={themedImage:"themedImage_ToTc","themedImage--light":"themedImage--light_HNdA","themedImage--dark":"themedImage--dark_i4oU"};function c(e){const t=(0,s.Z)(),{colorMode:n}=(0,i.I)(),{sources:c,className:u,alt:d,...f}=e,p=t?"dark"===n?["dark"]:["light"]:["light","dark"];return r.createElement(r.Fragment,null,p.map((e=>r.createElement("img",(0,a.Z)({key:e,src:c[e],alt:d,className:(0,o.Z)(l.themedImage,l[`themedImage--${e}`],u)},f)))))}},6043:(e,t,n)=>{"use strict";n.d(t,{u:()=>l,z:()=>h});var a=n(7462),r=n(7294),o=n(412),s=n(1442);const i="ease-in-out";function l(e){let{initialState:t}=e;const[n,a]=(0,r.useState)(t??!1),o=(0,r.useCallback)((()=>{a((e=>!e))}),[]);return{collapsed:n,setCollapsed:a,toggleCollapsed:o}}const c={display:"none",overflow:"hidden",height:"0px"},u={display:"block",overflow:"visible",height:"auto"};function d(e,t){const n=t?c:u;e.style.display=n.display,e.style.overflow=n.overflow,e.style.height=n.height}function f(e){let{collapsibleRef:t,collapsed:n,animation:a}=e;const o=(0,r.useRef)(!1);(0,r.useEffect)((()=>{const e=t.current;function r(){const t=e.scrollHeight,n=a?.duration??function(e){if((0,s.n)())return 1;const t=e/36;return Math.round(10*(4+15*t**.25+t/5))}(t);return{transition:`height ${n}ms ${a?.easing??i}`,height:`${t}px`}}function l(){const t=r();e.style.transition=t.transition,e.style.height=t.height}if(!o.current)return d(e,n),void(o.current=!0);return e.style.willChange="height",function(){const t=requestAnimationFrame((()=>{n?(l(),requestAnimationFrame((()=>{e.style.height=c.height,e.style.overflow=c.overflow}))):(e.style.display="block",requestAnimationFrame((()=>{l()})))}));return()=>cancelAnimationFrame(t)}()}),[t,n,a])}function p(e){if(!o.Z.canUseDOM)return e?c:u}function m(e){let{as:t="div",collapsed:n,children:a,animation:o,onCollapseTransitionEnd:s,className:i,disableSSRStyle:l}=e;const c=(0,r.useRef)(null);return f({collapsibleRef:c,collapsed:n,animation:o}),r.createElement(t,{ref:c,style:l?void 0:p(n),onTransitionEnd:e=>{"height"===e.propertyName&&(d(c.current,n),s?.(n))},className:i},a)}function g(e){let{collapsed:t,...n}=e;const[o,s]=(0,r.useState)(!t),[i,l]=(0,r.useState)(t);return(0,r.useLayoutEffect)((()=>{t||s(!0)}),[t]),(0,r.useLayoutEffect)((()=>{o&&l(t)}),[o,t]),o?r.createElement(m,(0,a.Z)({},n,{collapsed:i})):null}function h(e){let{lazy:t,...n}=e;const a=t?g:m;return r.createElement(a,n)}},9689:(e,t,n)=>{"use strict";n.d(t,{nT:()=>m,pl:()=>p});var a=n(7294),r=n(2389),o=n(12),s=n(902),i=n(6668);const l=(0,o.WA)("docusaurus.announcement.dismiss"),c=(0,o.WA)("docusaurus.announcement.id"),u=()=>"true"===l.get(),d=e=>l.set(String(e)),f=a.createContext(null);function p(e){let{children:t}=e;const n=function(){const{announcementBar:e}=(0,i.L)(),t=(0,r.Z)(),[n,o]=(0,a.useState)((()=>!!t&&u()));(0,a.useEffect)((()=>{o(u())}),[]);const s=(0,a.useCallback)((()=>{d(!0),o(!0)}),[]);return(0,a.useEffect)((()=>{if(!e)return;const{id:t}=e;let n=c.get();"annoucement-bar"===n&&(n="announcement-bar");const a=t!==n;c.set(t),a&&d(!1),!a&&u()||o(!1)}),[e]),(0,a.useMemo)((()=>({isActive:!!e&&!n,close:s})),[e,n,s])}();return a.createElement(f.Provider,{value:n},t)}function m(){const e=(0,a.useContext)(f);if(!e)throw new s.i6("AnnouncementBarProvider");return e}},2949:(e,t,n)=>{"use strict";n.d(t,{I:()=>h,S:()=>g});var a=n(7294),r=n(412),o=n(902),s=n(12),i=n(6668);const l=a.createContext(void 0),c="theme",u=(0,s.WA)(c),d={light:"light",dark:"dark"},f=e=>e===d.dark?d.dark:d.light,p=e=>r.Z.canUseDOM?f(document.documentElement.getAttribute("data-theme")):f(e),m=e=>{u.set(f(e))};function g(e){let{children:t}=e;const n=function(){const{colorMode:{defaultMode:e,disableSwitch:t,respectPrefersColorScheme:n}}=(0,i.L)(),[r,o]=(0,a.useState)(p(e));(0,a.useEffect)((()=>{t&&u.del()}),[t]);const s=(0,a.useCallback)((function(t,a){void 0===a&&(a={});const{persist:r=!0}=a;t?(o(t),r&&m(t)):(o(n?window.matchMedia("(prefers-color-scheme: dark)").matches?d.dark:d.light:e),u.del())}),[n,e]);(0,a.useEffect)((()=>{document.documentElement.setAttribute("data-theme",f(r))}),[r]),(0,a.useEffect)((()=>{if(t)return;const e=e=>{if(e.key!==c)return;const t=u.get();null!==t&&s(f(t))};return window.addEventListener("storage",e),()=>window.removeEventListener("storage",e)}),[t,s]);const l=(0,a.useRef)(!1);return(0,a.useEffect)((()=>{if(t&&!n)return;const e=window.matchMedia("(prefers-color-scheme: dark)"),a=()=>{window.matchMedia("print").matches||l.current?l.current=window.matchMedia("print").matches:s(null)};return e.addListener(a),()=>e.removeListener(a)}),[s,t,n]),(0,a.useMemo)((()=>({colorMode:r,setColorMode:s,get isDarkTheme(){return r===d.dark},setLightTheme(){s(d.light)},setDarkTheme(){s(d.dark)}})),[r,s])}();return a.createElement(l.Provider,{value:n},t)}function h(){const e=(0,a.useContext)(l);if(null==e)throw new o.i6("ColorModeProvider","Please see https://docusaurus.io/docs/api/themes/configuration#use-color-mode.");return e}},373:(e,t,n)=>{"use strict";n.d(t,{J:()=>v,L5:()=>h});var a=n(7294),r=n(143),o=n(9935),s=n(6668),i=n(2802),l=n(902),c=n(12);const u=e=>`docs-preferred-version-${e}`,d={save:(e,t,n)=>{(0,c.WA)(u(e),{persistence:t}).set(n)},read:(e,t)=>(0,c.WA)(u(e),{persistence:t}).get(),clear:(e,t)=>{(0,c.WA)(u(e),{persistence:t}).del()}},f=e=>Object.fromEntries(e.map((e=>[e,{preferredVersionName:null}])));const p=a.createContext(null);function m(){const e=(0,r._r)(),t=(0,s.L)().docs.versionPersistence,n=(0,a.useMemo)((()=>Object.keys(e)),[e]),[o,i]=(0,a.useState)((()=>f(n)));(0,a.useEffect)((()=>{i(function(e){let{pluginIds:t,versionPersistence:n,allDocsData:a}=e;function r(e){const t=d.read(e,n);return a[e].versions.some((e=>e.name===t))?{preferredVersionName:t}:(d.clear(e,n),{preferredVersionName:null})}return Object.fromEntries(t.map((e=>[e,r(e)])))}({allDocsData:e,versionPersistence:t,pluginIds:n}))}),[e,t,n]);return[o,(0,a.useMemo)((()=>({savePreferredVersion:function(e,n){d.save(e,t,n),i((t=>({...t,[e]:{preferredVersionName:n}})))}})),[t])]}function g(e){let{children:t}=e;const n=m();return a.createElement(p.Provider,{value:n},t)}function h(e){let{children:t}=e;return i.cE?a.createElement(g,null,t):a.createElement(a.Fragment,null,t)}function b(){const e=(0,a.useContext)(p);if(!e)throw new l.i6("DocsPreferredVersionContextProvider");return e}function v(e){void 0===e&&(e=o.m);const t=(0,r.zh)(e),[n,s]=b(),{preferredVersionName:i}=n[e];return{preferredVersion:t.versions.find((e=>e.name===i))??null,savePreferredVersionName:(0,a.useCallback)((t=>{s.savePreferredVersion(e,t)}),[s,e])}}},1116:(e,t,n)=>{"use strict";n.d(t,{V:()=>l,b:()=>i});var a=n(7294),r=n(902);const o=Symbol("EmptyContext"),s=a.createContext(o);function i(e){let{children:t,name:n,items:r}=e;const o=(0,a.useMemo)((()=>n&&r?{name:n,items:r}:null),[n,r]);return a.createElement(s.Provider,{value:o},t)}function l(){const e=(0,a.useContext)(s);if(e===o)throw new r.i6("DocsSidebarProvider");return e}},2961:(e,t,n)=>{"use strict";n.d(t,{M:()=>f,e:()=>p});var a=n(7294),r=n(3102),o=n(7524),s=n(6550),i=(n(1688),n(902));function l(e){!function(e){const t=(0,s.k6)(),n=(0,i.zX)(e);(0,a.useEffect)((()=>t.block(((e,t)=>n(e,t)))),[t,n])}(((t,n)=>{if("POP"===n)return e(t,n)}))}var c=n(6668);const u=a.createContext(void 0);function d(){const e=function(){const e=(0,r.HY)(),{items:t}=(0,c.L)().navbar;return 0===t.length&&!e.component}(),t=(0,o.i)(),n=!e&&"mobile"===t,[s,i]=(0,a.useState)(!1);l((()=>{if(s)return i(!1),!1}));const u=(0,a.useCallback)((()=>{i((e=>!e))}),[]);return(0,a.useEffect)((()=>{"desktop"===t&&i(!1)}),[t]),(0,a.useMemo)((()=>({disabled:e,shouldRender:n,toggle:u,shown:s})),[e,n,u,s])}function f(e){let{children:t}=e;const n=d();return a.createElement(u.Provider,{value:n},t)}function p(){const e=a.useContext(u);if(void 0===e)throw new i.i6("NavbarMobileSidebarProvider");return e}},3102:(e,t,n)=>{"use strict";n.d(t,{HY:()=>i,Zo:()=>l,n2:()=>s});var a=n(7294),r=n(902);const o=a.createContext(null);function s(e){let{children:t}=e;const n=(0,a.useState)({component:null,props:null});return a.createElement(o.Provider,{value:n},t)}function i(){const e=(0,a.useContext)(o);if(!e)throw new r.i6("NavbarSecondaryMenuContentProvider");return e[0]}function l(e){let{component:t,props:n}=e;const s=(0,a.useContext)(o);if(!s)throw new r.i6("NavbarSecondaryMenuContentProvider");const[,i]=s,l=(0,r.Ql)(n);return(0,a.useEffect)((()=>{i({component:t,props:l})}),[i,t,l]),(0,a.useEffect)((()=>()=>i({component:null,props:null})),[i]),null}},9727:(e,t,n)=>{"use strict";n.d(t,{h:()=>r,t:()=>o});var a=n(7294);const r="navigation-with-keyboard";function o(){(0,a.useEffect)((()=>{function e(e){"keydown"===e.type&&"Tab"===e.key&&document.body.classList.add(r),"mousedown"===e.type&&document.body.classList.remove(r)}return document.addEventListener("keydown",e),document.addEventListener("mousedown",e),()=>{document.body.classList.remove(r),document.removeEventListener("keydown",e),document.removeEventListener("mousedown",e)}}),[])}},7524:(e,t,n)=>{"use strict";n.d(t,{i:()=>c});var a=n(7294),r=n(412);const o={desktop:"desktop",mobile:"mobile",ssr:"ssr"},s=996;function i(){return r.Z.canUseDOM?window.innerWidth>s?o.desktop:o.mobile:o.ssr}const l=!1;function c(){const[e,t]=(0,a.useState)((()=>l?"ssr":i()));return(0,a.useEffect)((()=>{function e(){t(i())}const n=l?window.setTimeout(e,1e3):void 0;return window.addEventListener("resize",e),()=>{window.removeEventListener("resize",e),clearTimeout(n)}}),[]),e}},5281:(e,t,n)=>{"use strict";n.d(t,{k:()=>a});const a={page:{blogListPage:"blog-list-page",blogPostPage:"blog-post-page",blogTagsListPage:"blog-tags-list-page",blogTagPostListPage:"blog-tags-post-list-page",docsDocPage:"docs-doc-page",docsTagsListPage:"docs-tags-list-page",docsTagDocListPage:"docs-tags-doc-list-page",mdxPage:"mdx-page"},wrapper:{main:"main-wrapper",blogPages:"blog-wrapper",docsPages:"docs-wrapper",mdxPages:"mdx-wrapper"},common:{editThisPage:"theme-edit-this-page",lastUpdated:"theme-last-updated",backToTopButton:"theme-back-to-top-button",codeBlock:"theme-code-block",admonition:"theme-admonition",admonitionType:e=>`theme-admonition-${e}`},layout:{},docs:{docVersionBanner:"theme-doc-version-banner",docVersionBadge:"theme-doc-version-badge",docBreadcrumbs:"theme-doc-breadcrumbs",docMarkdown:"theme-doc-markdown",docTocMobile:"theme-doc-toc-mobile",docTocDesktop:"theme-doc-toc-desktop",docFooter:"theme-doc-footer",docFooterTagsRow:"theme-doc-footer-tags-row",docFooterEditMetaRow:"theme-doc-footer-edit-meta-row",docSidebarContainer:"theme-doc-sidebar-container",docSidebarMenu:"theme-doc-sidebar-menu",docSidebarItemCategory:"theme-doc-sidebar-item-category",docSidebarItemLink:"theme-doc-sidebar-item-link",docSidebarItemCategoryLevel:e=>`theme-doc-sidebar-item-category-level-${e}`,docSidebarItemLinkLevel:e=>`theme-doc-sidebar-item-link-level-${e}`},blog:{}}},1442:(e,t,n)=>{"use strict";function a(){return window.matchMedia("(prefers-reduced-motion: reduce)").matches}n.d(t,{n:()=>a})},2802:(e,t,n)=>{"use strict";n.d(t,{Wl:()=>f,_F:()=>g,cE:()=>d,hI:()=>w,lO:()=>v,vY:()=>x,oz:()=>y,s1:()=>b});var a=n(7294),r=n(6550),o=n(8790),s=n(143),i=n(373),l=n(1116);function c(e){return Array.from(new Set(e))}var u=n(8596);const d=!!s._r;function f(e){if(e.href)return e.href;for(const t of e.items){if("link"===t.type)return t.href;if("category"===t.type){const e=f(t);if(e)return e}}}const p=(e,t)=>void 0!==e&&(0,u.Mg)(e,t),m=(e,t)=>e.some((e=>g(e,t)));function g(e,t){return"link"===e.type?p(e.href,t):"category"===e.type&&(p(e.href,t)||m(e.items,t))}function h(e){let{sidebarItems:t,pathname:n,onlyCategories:a=!1}=e;const r=[];return function e(t){for(const o of t)if("category"===o.type&&((0,u.Mg)(o.href,n)||e(o.items))||"link"===o.type&&(0,u.Mg)(o.href,n)){return a&&"category"!==o.type||r.unshift(o),!0}return!1}(t),r}function b(){const e=(0,l.V)(),{pathname:t}=(0,r.TH)(),n=(0,s.gA)()?.pluginData.breadcrumbs;return!1!==n&&e?h({sidebarItems:e.items,pathname:t}):null}function v(e){const{activeVersion:t}=(0,s.Iw)(e),{preferredVersion:n}=(0,i.J)(e),r=(0,s.yW)(e);return(0,a.useMemo)((()=>c([t,n,r].filter(Boolean))),[t,n,r])}function y(e,t){const n=v(t);return(0,a.useMemo)((()=>{const t=n.flatMap((e=>e.sidebars?Object.entries(e.sidebars):[])),a=t.find((t=>t[0]===e));if(!a)throw new Error(`Can't find any sidebar with id "${e}" in version${n.length>1?"s":""} ${n.map((e=>e.name)).join(", ")}".\nAvailable sidebar ids are:\n- ${t.map((e=>e[0])).join("\n- ")}`);return a[1]}),[e,n])}function x(e,t){const n=v(t);return(0,a.useMemo)((()=>{const t=n.flatMap((e=>e.docs)),a=t.find((t=>t.id===e));if(!a){if(n.flatMap((e=>e.draftIds)).includes(e))return null;throw new Error(`Couldn't find any doc with id "${e}" in version${n.length>1?"s":""} "${n.map((e=>e.name)).join(", ")}".\nAvailable doc ids are:\n- ${c(t.map((e=>e.id))).join("\n- ")}`)}return a}),[e,n])}function w(e){let{route:t,versionMetadata:n}=e;const a=(0,r.TH)(),s=t.routes,i=s.find((e=>(0,r.LX)(a.pathname,e)));if(!i)return null;const l=i.sidebar,c=l?n.docsSidebars[l]:void 0;return{docElement:(0,o.H)(s),sidebarName:l,sidebarItems:c}}},1944:(e,t,n)=>{"use strict";n.d(t,{FG:()=>f,d:()=>u,VC:()=>p});var a=n(7294),r=n(6010),o=n(5742),s=n(226);function i(){const e=a.useContext(s._);if(!e)throw new Error("Unexpected: no Docusaurus route context found");return e}var l=n(4996),c=n(2263);function u(e){let{title:t,description:n,keywords:r,image:s,children:i}=e;const u=function(e){const{siteConfig:t}=(0,c.Z)(),{title:n,titleDelimiter:a}=t;return e?.trim().length?`${e.trim()} ${a} ${n}`:n}(t),{withBaseUrl:d}=(0,l.C)(),f=s?d(s,{absolute:!0}):void 0;return a.createElement(o.Z,null,t&&a.createElement("title",null,u),t&&a.createElement("meta",{property:"og:title",content:u}),n&&a.createElement("meta",{name:"description",content:n}),n&&a.createElement("meta",{property:"og:description",content:n}),r&&a.createElement("meta",{name:"keywords",content:Array.isArray(r)?r.join(","):r}),f&&a.createElement("meta",{property:"og:image",content:f}),f&&a.createElement("meta",{name:"twitter:image",content:f}),i)}const d=a.createContext(void 0);function f(e){let{className:t,children:n}=e;const s=a.useContext(d),i=(0,r.Z)(s,t);return a.createElement(d.Provider,{value:i},a.createElement(o.Z,null,a.createElement("html",{className:i})),n)}function p(e){let{children:t}=e;const n=i(),o=`plugin-${n.plugin.name.replace(/docusaurus-(?:plugin|theme)-(?:content-)?/gi,"")}`;const s=`plugin-id-${n.plugin.id}`;return a.createElement(f,{className:(0,r.Z)(o,s)},t)}},902:(e,t,n)=>{"use strict";n.d(t,{D9:()=>s,Qc:()=>c,Ql:()=>l,i6:()=>i,zX:()=>o});var a=n(7294);const r=n(412).Z.canUseDOM?a.useLayoutEffect:a.useEffect;function o(e){const t=(0,a.useRef)(e);return r((()=>{t.current=e}),[e]),(0,a.useCallback)((function(){return t.current(...arguments)}),[])}function s(e){const t=(0,a.useRef)();return r((()=>{t.current=e})),t.current}class i extends Error{constructor(e,t){super(),this.name="ReactContextError",this.message=`Hook ${this.stack?.split("\n")[1]?.match(/at (?:\w+\.)?(?<name>\w+)/)?.groups.name??""} is called outside the <${e}>. ${t??""}`}}function l(e){const t=Object.entries(e);return t.sort(((e,t)=>e[0].localeCompare(t[0]))),(0,a.useMemo)((()=>e),t.flat())}function c(e){return t=>{let{children:n}=t;return a.createElement(a.Fragment,null,e.reduceRight(((e,t)=>a.createElement(t,null,e)),n))}}},8596:(e,t,n)=>{"use strict";n.d(t,{Mg:()=>s,Ns:()=>i});var a=n(7294),r=n(723),o=n(2263);function s(e,t){const n=e=>(!e||e.endsWith("/")?e:`${e}/`)?.toLowerCase();return n(e)===n(t)}function i(){const{baseUrl:e}=(0,o.Z)().siteConfig;return(0,a.useMemo)((()=>function(e){let{baseUrl:t,routes:n}=e;function a(e){return e.path===t&&!0===e.exact}function r(e){return e.path===t&&!e.exact}return function e(t){if(0===t.length)return;return t.find(a)||e(t.filter(r).flatMap((e=>e.routes??[])))}(n)}({routes:r.Z,baseUrl:e})),[e])}},2466:(e,t,n)=>{"use strict";n.d(t,{Ct:()=>f,OC:()=>l,RF:()=>d});var a=n(7294),r=n(412),o=n(2389),s=n(902);const i=a.createContext(void 0);function l(e){let{children:t}=e;const n=function(){const e=(0,a.useRef)(!0);return(0,a.useMemo)((()=>({scrollEventsEnabledRef:e,enableScrollEvents:()=>{e.current=!0},disableScrollEvents:()=>{e.current=!1}})),[])}();return a.createElement(i.Provider,{value:n},t)}function c(){const e=(0,a.useContext)(i);if(null==e)throw new s.i6("ScrollControllerProvider");return e}const u=()=>r.Z.canUseDOM?{scrollX:window.pageXOffset,scrollY:window.pageYOffset}:null;function d(e,t){void 0===t&&(t=[]);const{scrollEventsEnabledRef:n}=c(),r=(0,a.useRef)(u()),o=(0,s.zX)(e);(0,a.useEffect)((()=>{const e=()=>{if(!n.current)return;const e=u();o(e,r.current),r.current=e},t={passive:!0};return e(),window.addEventListener("scroll",e,t),()=>window.removeEventListener("scroll",e,t)}),[o,n,...t])}function f(){const e=(0,a.useRef)(null),t=(0,o.Z)()&&"smooth"===getComputedStyle(document.documentElement).scrollBehavior;return{startScroll:n=>{e.current=t?function(e){return window.scrollTo({top:e,behavior:"smooth"}),()=>{}}(n):function(e){let t=null;const n=document.documentElement.scrollTop>e;return function a(){const r=document.documentElement.scrollTop;(n&&r>e||!n&&r<e)&&(t=requestAnimationFrame(a),window.scrollTo(0,Math.floor(.85*(r-e))+e))}(),()=>t&&cancelAnimationFrame(t)}(n)},cancelScroll:()=>e.current?.()}}},3320:(e,t,n)=>{"use strict";n.d(t,{HX:()=>a,os:()=>r});n(2263);const a="default";function r(e,t){return`docs-${e}-${t}`}},12:(e,t,n)=>{"use strict";n.d(t,{WA:()=>l});n(7294),n(1688);const a="localStorage";function r(e){let{key:t,oldValue:n,newValue:a,storage:r}=e;if(n===a)return;const o=document.createEvent("StorageEvent");o.initStorageEvent("storage",!1,!1,t,n,a,window.location.href,r),window.dispatchEvent(o)}function o(e){if(void 0===e&&(e=a),"undefined"==typeof window)throw new Error("Browser storage is not available on Node.js/Docusaurus SSR process.");if("none"===e)return null;try{return window[e]}catch(n){return t=n,s||(console.warn("Docusaurus browser storage is not available.\nPossible reasons: running Docusaurus in an iframe, in an incognito browser session, or using too strict browser privacy settings.",t),s=!0),null}var t}let s=!1;const i={get:()=>null,set:()=>{},del:()=>{},listen:()=>()=>{}};function l(e,t){if("undefined"==typeof window)return function(e){function t(){throw new Error(`Illegal storage API usage for storage key "${e}".\nDocusaurus storage APIs are not supposed to be called on the server-rendering process.\nPlease only call storage APIs in effects and event handlers.`)}return{get:t,set:t,del:t,listen:t}}(e);const n=o(t?.persistence);return null===n?i:{get:()=>{try{return n.getItem(e)}catch(t){return console.error(`Docusaurus storage error, can't get key=${e}`,t),null}},set:t=>{try{const a=n.getItem(e);n.setItem(e,t),r({key:e,oldValue:a,newValue:t,storage:n})}catch(a){console.error(`Docusaurus storage error, can't set ${e}=${t}`,a)}},del:()=>{try{const t=n.getItem(e);n.removeItem(e),r({key:e,oldValue:t,newValue:null,storage:n})}catch(t){console.error(`Docusaurus storage error, can't delete key=${e}`,t)}},listen:t=>{try{const a=a=>{a.storageArea===n&&a.key===e&&t(a)};return window.addEventListener("storage",a),()=>window.removeEventListener("storage",a)}catch(a){return console.error(`Docusaurus storage error, can't listen for changes of key=${e}`,a),()=>{}}}}}},4711:(e,t,n)=>{"use strict";n.d(t,{l:()=>o});var a=n(2263),r=n(6550);function o(){const{siteConfig:{baseUrl:e,url:t},i18n:{defaultLocale:n,currentLocale:o}}=(0,a.Z)(),{pathname:s}=(0,r.TH)(),i=o===n?e:e.replace(`/${o}/`,"/"),l=s.replace(e,"");return{createUrl:function(e){let{locale:a,fullyQualified:r}=e;return`${r?t:""}${function(e){return e===n?`${i}`:`${i}${e}/`}(a)}${l}`}}}},5936:(e,t,n)=>{"use strict";n.d(t,{S:()=>s});var a=n(7294),r=n(6550),o=n(902);function s(e){const t=(0,r.TH)(),n=(0,o.D9)(t),s=(0,o.zX)(e);(0,a.useEffect)((()=>{n&&t!==n&&s({location:t,previousLocation:n})}),[s,t,n])}},6668:(e,t,n)=>{"use strict";n.d(t,{L:()=>r});var a=n(2263);function r(){return(0,a.Z)().siteConfig.themeConfig}},8802:(e,t)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(e,t){const{trailingSlash:n,baseUrl:a}=t;if(e.startsWith("#"))return e;if(void 0===n)return e;const[r]=e.split(/[#?]/),o="/"===r||r===a?r:(s=r,n?function(e){return e.endsWith("/")?e:`${e}/`}(s):function(e){return e.endsWith("/")?e.slice(0,-1):e}(s));var s;return e.replace(r,o)}},4143:(e,t)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.getErrorCausalChain=void 0,t.getErrorCausalChain=function e(t){return t.cause?[t,...e(t.cause)]:[t]}},8780:function(e,t,n){"use strict";var a=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.getErrorCausalChain=t.applyTrailingSlash=t.blogPostContainerID=void 0,t.blogPostContainerID="__blog-post-container";var r=n(8802);Object.defineProperty(t,"applyTrailingSlash",{enumerable:!0,get:function(){return a(r).default}});var o=n(4143);Object.defineProperty(t,"getErrorCausalChain",{enumerable:!0,get:function(){return o.getErrorCausalChain}})},6010:(e,t,n)=>{"use strict";function a(e){var t,n,r="";if("string"==typeof e||"number"==typeof e)r+=e;else if("object"==typeof e)if(Array.isArray(e))for(t=0;t<e.length;t++)e[t]&&(n=a(e[t]))&&(r&&(r+=" "),r+=n);else for(t in e)e[t]&&(r&&(r+=" "),r+=t);return r}n.d(t,{Z:()=>r});const r=function(){for(var e,t,n=0,r="";n<arguments.length;)(e=arguments[n++])&&(t=a(e))&&(r&&(r+=" "),r+=t);return r}},9318:(e,t,n)=>{"use strict";n.d(t,{lX:()=>x,q_:()=>C,ob:()=>p,PP:()=>q,Ep:()=>f});var a=n(7462);function r(e){return"/"===e.charAt(0)}function o(e,t){for(var n=t,a=n+1,r=e.length;a<r;n+=1,a+=1)e[n]=e[a];e.pop()}const s=function(e,t){void 0===t&&(t="");var n,a=e&&e.split("/")||[],s=t&&t.split("/")||[],i=e&&r(e),l=t&&r(t),c=i||l;if(e&&r(e)?s=a:a.length&&(s.pop(),s=s.concat(a)),!s.length)return"/";if(s.length){var u=s[s.length-1];n="."===u||".."===u||""===u}else n=!1;for(var d=0,f=s.length;f>=0;f--){var p=s[f];"."===p?o(s,f):".."===p?(o(s,f),d++):d&&(o(s,f),d--)}if(!c)for(;d--;d)s.unshift("..");!c||""===s[0]||s[0]&&r(s[0])||s.unshift("");var m=s.join("/");return n&&"/"!==m.substr(-1)&&(m+="/"),m};var i=n(8776);function l(e){return"/"===e.charAt(0)?e:"/"+e}function c(e){return"/"===e.charAt(0)?e.substr(1):e}function u(e,t){return function(e,t){return 0===e.toLowerCase().indexOf(t.toLowerCase())&&-1!=="/?#".indexOf(e.charAt(t.length))}(e,t)?e.substr(t.length):e}function d(e){return"/"===e.charAt(e.length-1)?e.slice(0,-1):e}function f(e){var t=e.pathname,n=e.search,a=e.hash,r=t||"/";return n&&"?"!==n&&(r+="?"===n.charAt(0)?n:"?"+n),a&&"#"!==a&&(r+="#"===a.charAt(0)?a:"#"+a),r}function p(e,t,n,r){var o;"string"==typeof e?(o=function(e){var t=e||"/",n="",a="",r=t.indexOf("#");-1!==r&&(a=t.substr(r),t=t.substr(0,r));var o=t.indexOf("?");return-1!==o&&(n=t.substr(o),t=t.substr(0,o)),{pathname:t,search:"?"===n?"":n,hash:"#"===a?"":a}}(e),o.state=t):(void 0===(o=(0,a.Z)({},e)).pathname&&(o.pathname=""),o.search?"?"!==o.search.charAt(0)&&(o.search="?"+o.search):o.search="",o.hash?"#"!==o.hash.charAt(0)&&(o.hash="#"+o.hash):o.hash="",void 0!==t&&void 0===o.state&&(o.state=t));try{o.pathname=decodeURI(o.pathname)}catch(i){throw i instanceof URIError?new URIError('Pathname "'+o.pathname+'" could not be decoded. This is likely caused by an invalid percent-encoding.'):i}return n&&(o.key=n),r?o.pathname?"/"!==o.pathname.charAt(0)&&(o.pathname=s(o.pathname,r.pathname)):o.pathname=r.pathname:o.pathname||(o.pathname="/"),o}function m(){var e=null;var t=[];return{setPrompt:function(t){return e=t,function(){e===t&&(e=null)}},confirmTransitionTo:function(t,n,a,r){if(null!=e){var o="function"==typeof e?e(t,n):e;"string"==typeof o?"function"==typeof a?a(o,r):r(!0):r(!1!==o)}else r(!0)},appendListener:function(e){var n=!0;function a(){n&&e.apply(void 0,arguments)}return t.push(a),function(){n=!1,t=t.filter((function(e){return e!==a}))}},notifyListeners:function(){for(var e=arguments.length,n=new Array(e),a=0;a<e;a++)n[a]=arguments[a];t.forEach((function(e){return e.apply(void 0,n)}))}}}var g=!("undefined"==typeof window||!window.document||!window.document.createElement);function h(e,t){t(window.confirm(e))}var b="popstate",v="hashchange";function y(){try{return window.history.state||{}}catch(e){return{}}}function x(e){void 0===e&&(e={}),g||(0,i.Z)(!1);var t,n=window.history,r=(-1===(t=window.navigator.userAgent).indexOf("Android 2.")&&-1===t.indexOf("Android 4.0")||-1===t.indexOf("Mobile Safari")||-1!==t.indexOf("Chrome")||-1!==t.indexOf("Windows Phone"))&&window.history&&"pushState"in window.history,o=!(-1===window.navigator.userAgent.indexOf("Trident")),s=e,c=s.forceRefresh,x=void 0!==c&&c,w=s.getUserConfirmation,S=void 0===w?h:w,E=s.keyLength,k=void 0===E?6:E,_=e.basename?d(l(e.basename)):"";function C(e){var t=e||{},n=t.key,a=t.state,r=window.location,o=r.pathname+r.search+r.hash;return _&&(o=u(o,_)),p(o,a,n)}function T(){return Math.random().toString(36).substr(2,k)}var q=m();function A(e){(0,a.Z)(z,e),z.length=n.length,q.notifyListeners(z.location,z.action)}function L(e){(function(e){return void 0===e.state&&-1===navigator.userAgent.indexOf("CriOS")})(e)||P(C(e.state))}function N(){P(C(y()))}var O=!1;function P(e){if(O)O=!1,A();else{q.confirmTransitionTo(e,"POP",S,(function(t){t?A({action:"POP",location:e}):function(e){var t=z.location,n=R.indexOf(t.key);-1===n&&(n=0);var a=R.indexOf(e.key);-1===a&&(a=0);var r=n-a;r&&(O=!0,D(r))}(e)}))}}var I=C(y()),R=[I.key];function M(e){return _+f(e)}function D(e){n.go(e)}var F=0;function B(e){1===(F+=e)&&1===e?(window.addEventListener(b,L),o&&window.addEventListener(v,N)):0===F&&(window.removeEventListener(b,L),o&&window.removeEventListener(v,N))}var j=!1;var z={length:n.length,action:"POP",location:I,createHref:M,push:function(e,t){var a="PUSH",o=p(e,t,T(),z.location);q.confirmTransitionTo(o,a,S,(function(e){if(e){var t=M(o),s=o.key,i=o.state;if(r)if(n.pushState({key:s,state:i},null,t),x)window.location.href=t;else{var l=R.indexOf(z.location.key),c=R.slice(0,l+1);c.push(o.key),R=c,A({action:a,location:o})}else window.location.href=t}}))},replace:function(e,t){var a="REPLACE",o=p(e,t,T(),z.location);q.confirmTransitionTo(o,a,S,(function(e){if(e){var t=M(o),s=o.key,i=o.state;if(r)if(n.replaceState({key:s,state:i},null,t),x)window.location.replace(t);else{var l=R.indexOf(z.location.key);-1!==l&&(R[l]=o.key),A({action:a,location:o})}else window.location.replace(t)}}))},go:D,goBack:function(){D(-1)},goForward:function(){D(1)},block:function(e){void 0===e&&(e=!1);var t=q.setPrompt(e);return j||(B(1),j=!0),function(){return j&&(j=!1,B(-1)),t()}},listen:function(e){var t=q.appendListener(e);return B(1),function(){B(-1),t()}}};return z}var w="hashchange",S={hashbang:{encodePath:function(e){return"!"===e.charAt(0)?e:"!/"+c(e)},decodePath:function(e){return"!"===e.charAt(0)?e.substr(1):e}},noslash:{encodePath:c,decodePath:l},slash:{encodePath:l,decodePath:l}};function E(e){var t=e.indexOf("#");return-1===t?e:e.slice(0,t)}function k(){var e=window.location.href,t=e.indexOf("#");return-1===t?"":e.substring(t+1)}function _(e){window.location.replace(E(window.location.href)+"#"+e)}function C(e){void 0===e&&(e={}),g||(0,i.Z)(!1);var t=window.history,n=(window.navigator.userAgent.indexOf("Firefox"),e),r=n.getUserConfirmation,o=void 0===r?h:r,s=n.hashType,c=void 0===s?"slash":s,b=e.basename?d(l(e.basename)):"",v=S[c],y=v.encodePath,x=v.decodePath;function C(){var e=x(k());return b&&(e=u(e,b)),p(e)}var T=m();function q(e){(0,a.Z)(j,e),j.length=t.length,T.notifyListeners(j.location,j.action)}var A=!1,L=null;function N(){var e,t,n=k(),a=y(n);if(n!==a)_(a);else{var r=C(),s=j.location;if(!A&&(t=r,(e=s).pathname===t.pathname&&e.search===t.search&&e.hash===t.hash))return;if(L===f(r))return;L=null,function(e){if(A)A=!1,q();else{var t="POP";T.confirmTransitionTo(e,t,o,(function(n){n?q({action:t,location:e}):function(e){var t=j.location,n=R.lastIndexOf(f(t));-1===n&&(n=0);var a=R.lastIndexOf(f(e));-1===a&&(a=0);var r=n-a;r&&(A=!0,M(r))}(e)}))}}(r)}}var O=k(),P=y(O);O!==P&&_(P);var I=C(),R=[f(I)];function M(e){t.go(e)}var D=0;function F(e){1===(D+=e)&&1===e?window.addEventListener(w,N):0===D&&window.removeEventListener(w,N)}var B=!1;var j={length:t.length,action:"POP",location:I,createHref:function(e){var t=document.querySelector("base"),n="";return t&&t.getAttribute("href")&&(n=E(window.location.href)),n+"#"+y(b+f(e))},push:function(e,t){var n="PUSH",a=p(e,void 0,void 0,j.location);T.confirmTransitionTo(a,n,o,(function(e){if(e){var t=f(a),r=y(b+t);if(k()!==r){L=t,function(e){window.location.hash=e}(r);var o=R.lastIndexOf(f(j.location)),s=R.slice(0,o+1);s.push(t),R=s,q({action:n,location:a})}else q()}}))},replace:function(e,t){var n="REPLACE",a=p(e,void 0,void 0,j.location);T.confirmTransitionTo(a,n,o,(function(e){if(e){var t=f(a),r=y(b+t);k()!==r&&(L=t,_(r));var o=R.indexOf(f(j.location));-1!==o&&(R[o]=t),q({action:n,location:a})}}))},go:M,goBack:function(){M(-1)},goForward:function(){M(1)},block:function(e){void 0===e&&(e=!1);var t=T.setPrompt(e);return B||(F(1),B=!0),function(){return B&&(B=!1,F(-1)),t()}},listen:function(e){var t=T.appendListener(e);return F(1),function(){F(-1),t()}}};return j}function T(e,t,n){return Math.min(Math.max(e,t),n)}function q(e){void 0===e&&(e={});var t=e,n=t.getUserConfirmation,r=t.initialEntries,o=void 0===r?["/"]:r,s=t.initialIndex,i=void 0===s?0:s,l=t.keyLength,c=void 0===l?6:l,u=m();function d(e){(0,a.Z)(x,e),x.length=x.entries.length,u.notifyListeners(x.location,x.action)}function g(){return Math.random().toString(36).substr(2,c)}var h=T(i,0,o.length-1),b=o.map((function(e){return p(e,void 0,"string"==typeof e?g():e.key||g())})),v=f;function y(e){var t=T(x.index+e,0,x.entries.length-1),a=x.entries[t];u.confirmTransitionTo(a,"POP",n,(function(e){e?d({action:"POP",location:a,index:t}):d()}))}var x={length:b.length,action:"POP",location:b[h],index:h,entries:b,createHref:v,push:function(e,t){var a="PUSH",r=p(e,t,g(),x.location);u.confirmTransitionTo(r,a,n,(function(e){if(e){var t=x.index+1,n=x.entries.slice(0);n.length>t?n.splice(t,n.length-t,r):n.push(r),d({action:a,location:r,index:t,entries:n})}}))},replace:function(e,t){var a="REPLACE",r=p(e,t,g(),x.location);u.confirmTransitionTo(r,a,n,(function(e){e&&(x.entries[x.index]=r,d({action:a,location:r}))}))},go:y,goBack:function(){y(-1)},goForward:function(){y(1)},canGo:function(e){var t=x.index+e;return t>=0&&t<x.entries.length},block:function(e){return void 0===e&&(e=!1),u.setPrompt(e)},listen:function(e){return u.appendListener(e)}};return x}},8679:(e,t,n)=>{"use strict";var a=n(9864),r={childContextTypes:!0,contextType:!0,contextTypes:!0,defaultProps:!0,displayName:!0,getDefaultProps:!0,getDerivedStateFromError:!0,getDerivedStateFromProps:!0,mixins:!0,propTypes:!0,type:!0},o={name:!0,length:!0,prototype:!0,caller:!0,callee:!0,arguments:!0,arity:!0},s={$$typeof:!0,compare:!0,defaultProps:!0,displayName:!0,propTypes:!0,type:!0},i={};function l(e){return a.isMemo(e)?s:i[e.$$typeof]||r}i[a.ForwardRef]={$$typeof:!0,render:!0,defaultProps:!0,displayName:!0,propTypes:!0},i[a.Memo]=s;var c=Object.defineProperty,u=Object.getOwnPropertyNames,d=Object.getOwnPropertySymbols,f=Object.getOwnPropertyDescriptor,p=Object.getPrototypeOf,m=Object.prototype;e.exports=function e(t,n,a){if("string"!=typeof n){if(m){var r=p(n);r&&r!==m&&e(t,r,a)}var s=u(n);d&&(s=s.concat(d(n)));for(var i=l(t),g=l(n),h=0;h<s.length;++h){var b=s[h];if(!(o[b]||a&&a[b]||g&&g[b]||i&&i[b])){var v=f(n,b);try{c(t,b,v)}catch(y){}}}}return t}},1143:e=>{"use strict";e.exports=function(e,t,n,a,r,o,s,i){if(!e){var l;if(void 0===t)l=new Error("Minified exception occurred; use the non-minified dev environment for the full error message and additional helpful warnings.");else{var c=[n,a,r,o,s,i],u=0;(l=new Error(t.replace(/%s/g,(function(){return c[u++]})))).name="Invariant Violation"}throw l.framesToPop=1,l}}},5826:e=>{e.exports=Array.isArray||function(e){return"[object Array]"==Object.prototype.toString.call(e)}},2497:(e,t,n)=>{"use strict";n.r(t)},2295:(e,t,n)=>{"use strict";n.r(t)},4865:function(e,t,n){var a,r;a=function(){var e,t,n={version:"0.2.0"},a=n.settings={minimum:.08,easing:"ease",positionUsing:"",speed:200,trickle:!0,trickleRate:.02,trickleSpeed:800,showSpinner:!0,barSelector:'[role="bar"]',spinnerSelector:'[role="spinner"]',parent:"body",template:'<div class="bar" role="bar"><div class="peg"></div></div><div class="spinner" role="spinner"><div class="spinner-icon"></div></div>'};function r(e,t,n){return e<t?t:e>n?n:e}function o(e){return 100*(-1+e)}function s(e,t,n){var r;return(r="translate3d"===a.positionUsing?{transform:"translate3d("+o(e)+"%,0,0)"}:"translate"===a.positionUsing?{transform:"translate("+o(e)+"%,0)"}:{"margin-left":o(e)+"%"}).transition="all "+t+"ms "+n,r}n.configure=function(e){var t,n;for(t in e)void 0!==(n=e[t])&&e.hasOwnProperty(t)&&(a[t]=n);return this},n.status=null,n.set=function(e){var t=n.isStarted();e=r(e,a.minimum,1),n.status=1===e?null:e;var o=n.render(!t),c=o.querySelector(a.barSelector),u=a.speed,d=a.easing;return o.offsetWidth,i((function(t){""===a.positionUsing&&(a.positionUsing=n.getPositioningCSS()),l(c,s(e,u,d)),1===e?(l(o,{transition:"none",opacity:1}),o.offsetWidth,setTimeout((function(){l(o,{transition:"all "+u+"ms linear",opacity:0}),setTimeout((function(){n.remove(),t()}),u)}),u)):setTimeout(t,u)})),this},n.isStarted=function(){return"number"==typeof n.status},n.start=function(){n.status||n.set(0);var e=function(){setTimeout((function(){n.status&&(n.trickle(),e())}),a.trickleSpeed)};return a.trickle&&e(),this},n.done=function(e){return e||n.status?n.inc(.3+.5*Math.random()).set(1):this},n.inc=function(e){var t=n.status;return t?("number"!=typeof e&&(e=(1-t)*r(Math.random()*t,.1,.95)),t=r(t+e,0,.994),n.set(t)):n.start()},n.trickle=function(){return n.inc(Math.random()*a.trickleRate)},e=0,t=0,n.promise=function(a){return a&&"resolved"!==a.state()?(0===t&&n.start(),e++,t++,a.always((function(){0==--t?(e=0,n.done()):n.set((e-t)/e)})),this):this},n.render=function(e){if(n.isRendered())return document.getElementById("nprogress");u(document.documentElement,"nprogress-busy");var t=document.createElement("div");t.id="nprogress",t.innerHTML=a.template;var r,s=t.querySelector(a.barSelector),i=e?"-100":o(n.status||0),c=document.querySelector(a.parent);return l(s,{transition:"all 0 linear",transform:"translate3d("+i+"%,0,0)"}),a.showSpinner||(r=t.querySelector(a.spinnerSelector))&&p(r),c!=document.body&&u(c,"nprogress-custom-parent"),c.appendChild(t),t},n.remove=function(){d(document.documentElement,"nprogress-busy"),d(document.querySelector(a.parent),"nprogress-custom-parent");var e=document.getElementById("nprogress");e&&p(e)},n.isRendered=function(){return!!document.getElementById("nprogress")},n.getPositioningCSS=function(){var e=document.body.style,t="WebkitTransform"in e?"Webkit":"MozTransform"in e?"Moz":"msTransform"in e?"ms":"OTransform"in e?"O":"";return t+"Perspective"in e?"translate3d":t+"Transform"in e?"translate":"margin"};var i=function(){var e=[];function t(){var n=e.shift();n&&n(t)}return function(n){e.push(n),1==e.length&&t()}}(),l=function(){var e=["Webkit","O","Moz","ms"],t={};function n(e){return e.replace(/^-ms-/,"ms-").replace(/-([\da-z])/gi,(function(e,t){return t.toUpperCase()}))}function a(t){var n=document.body.style;if(t in n)return t;for(var a,r=e.length,o=t.charAt(0).toUpperCase()+t.slice(1);r--;)if((a=e[r]+o)in n)return a;return t}function r(e){return e=n(e),t[e]||(t[e]=a(e))}function o(e,t,n){t=r(t),e.style[t]=n}return function(e,t){var n,a,r=arguments;if(2==r.length)for(n in t)void 0!==(a=t[n])&&t.hasOwnProperty(n)&&o(e,n,a);else o(e,r[1],r[2])}}();function c(e,t){return("string"==typeof e?e:f(e)).indexOf(" "+t+" ")>=0}function u(e,t){var n=f(e),a=n+t;c(n,t)||(e.className=a.substring(1))}function d(e,t){var n,a=f(e);c(e,t)&&(n=a.replace(" "+t+" "," "),e.className=n.substring(1,n.length-1))}function f(e){return(" "+(e.className||"")+" ").replace(/\s+/gi," ")}function p(e){e&&e.parentNode&&e.parentNode.removeChild(e)}return n},void 0===(r="function"==typeof a?a.call(t,n,t,e):a)||(e.exports=r)},7418:e=>{"use strict";var t=Object.getOwnPropertySymbols,n=Object.prototype.hasOwnProperty,a=Object.prototype.propertyIsEnumerable;e.exports=function(){try{if(!Object.assign)return!1;var e=new String("abc");if(e[5]="de","5"===Object.getOwnPropertyNames(e)[0])return!1;for(var t={},n=0;n<10;n++)t["_"+String.fromCharCode(n)]=n;if("0123456789"!==Object.getOwnPropertyNames(t).map((function(e){return t[e]})).join(""))return!1;var a={};return"abcdefghijklmnopqrst".split("").forEach((function(e){a[e]=e})),"abcdefghijklmnopqrst"===Object.keys(Object.assign({},a)).join("")}catch(r){return!1}}()?Object.assign:function(e,r){for(var o,s,i=function(e){if(null==e)throw new TypeError("Object.assign cannot be called with null or undefined");return Object(e)}(e),l=1;l<arguments.length;l++){for(var c in o=Object(arguments[l]))n.call(o,c)&&(i[c]=o[c]);if(t){s=t(o);for(var u=0;u<s.length;u++)a.call(o,s[u])&&(i[s[u]]=o[s[u]])}}return i}},7410:(e,t,n)=>{"use strict";n.d(t,{Z:()=>o});var a=function(){var e=/(?:^|\s)lang(?:uage)?-([\w-]+)(?=\s|$)/i,t=0,n={},a={util:{encode:function e(t){return t instanceof r?new r(t.type,e(t.content),t.alias):Array.isArray(t)?t.map(e):t.replace(/&/g,"&").replace(/</g,"<").replace(/\u00a0/g," ")},type:function(e){return Object.prototype.toString.call(e).slice(8,-1)},objId:function(e){return e.__id||Object.defineProperty(e,"__id",{value:++t}),e.__id},clone:function e(t,n){var r,o;switch(n=n||{},a.util.type(t)){case"Object":if(o=a.util.objId(t),n[o])return n[o];for(var s in r={},n[o]=r,t)t.hasOwnProperty(s)&&(r[s]=e(t[s],n));return r;case"Array":return o=a.util.objId(t),n[o]?n[o]:(r=[],n[o]=r,t.forEach((function(t,a){r[a]=e(t,n)})),r);default:return t}},getLanguage:function(t){for(;t;){var n=e.exec(t.className);if(n)return n[1].toLowerCase();t=t.parentElement}return"none"},setLanguage:function(t,n){t.className=t.className.replace(RegExp(e,"gi"),""),t.classList.add("language-"+n)},isActive:function(e,t,n){for(var a="no-"+t;e;){var r=e.classList;if(r.contains(t))return!0;if(r.contains(a))return!1;e=e.parentElement}return!!n}},languages:{plain:n,plaintext:n,text:n,txt:n,extend:function(e,t){var n=a.util.clone(a.languages[e]);for(var r in t)n[r]=t[r];return n},insertBefore:function(e,t,n,r){var o=(r=r||a.languages)[e],s={};for(var i in o)if(o.hasOwnProperty(i)){if(i==t)for(var l in n)n.hasOwnProperty(l)&&(s[l]=n[l]);n.hasOwnProperty(i)||(s[i]=o[i])}var c=r[e];return r[e]=s,a.languages.DFS(a.languages,(function(t,n){n===c&&t!=e&&(this[t]=s)})),s},DFS:function e(t,n,r,o){o=o||{};var s=a.util.objId;for(var i in t)if(t.hasOwnProperty(i)){n.call(t,i,t[i],r||i);var l=t[i],c=a.util.type(l);"Object"!==c||o[s(l)]?"Array"!==c||o[s(l)]||(o[s(l)]=!0,e(l,n,i,o)):(o[s(l)]=!0,e(l,n,null,o))}}},plugins:{},highlight:function(e,t,n){var o={code:e,grammar:t,language:n};return a.hooks.run("before-tokenize",o),o.tokens=a.tokenize(o.code,o.grammar),a.hooks.run("after-tokenize",o),r.stringify(a.util.encode(o.tokens),o.language)},tokenize:function(e,t){var n=t.rest;if(n){for(var a in n)t[a]=n[a];delete t.rest}var r=new i;return l(r,r.head,e),s(e,r,t,r.head,0),function(e){var t=[],n=e.head.next;for(;n!==e.tail;)t.push(n.value),n=n.next;return t}(r)},hooks:{all:{},add:function(e,t){var n=a.hooks.all;n[e]=n[e]||[],n[e].push(t)},run:function(e,t){var n=a.hooks.all[e];if(n&&n.length)for(var r,o=0;r=n[o++];)r(t)}},Token:r};function r(e,t,n,a){this.type=e,this.content=t,this.alias=n,this.length=0|(a||"").length}function o(e,t,n,a){e.lastIndex=t;var r=e.exec(n);if(r&&a&&r[1]){var o=r[1].length;r.index+=o,r[0]=r[0].slice(o)}return r}function s(e,t,n,i,u,d){for(var f in n)if(n.hasOwnProperty(f)&&n[f]){var p=n[f];p=Array.isArray(p)?p:[p];for(var m=0;m<p.length;++m){if(d&&d.cause==f+","+m)return;var g=p[m],h=g.inside,b=!!g.lookbehind,v=!!g.greedy,y=g.alias;if(v&&!g.pattern.global){var x=g.pattern.toString().match(/[imsuy]*$/)[0];g.pattern=RegExp(g.pattern.source,x+"g")}for(var w=g.pattern||g,S=i.next,E=u;S!==t.tail&&!(d&&E>=d.reach);E+=S.value.length,S=S.next){var k=S.value;if(t.length>e.length)return;if(!(k instanceof r)){var _,C=1;if(v){if(!(_=o(w,E,e,b))||_.index>=e.length)break;var T=_.index,q=_.index+_[0].length,A=E;for(A+=S.value.length;T>=A;)A+=(S=S.next).value.length;if(E=A-=S.value.length,S.value instanceof r)continue;for(var L=S;L!==t.tail&&(A<q||"string"==typeof L.value);L=L.next)C++,A+=L.value.length;C--,k=e.slice(E,A),_.index-=E}else if(!(_=o(w,0,k,b)))continue;T=_.index;var N=_[0],O=k.slice(0,T),P=k.slice(T+N.length),I=E+k.length;d&&I>d.reach&&(d.reach=I);var R=S.prev;if(O&&(R=l(t,R,O),E+=O.length),c(t,R,C),S=l(t,R,new r(f,h?a.tokenize(N,h):N,y,N)),P&&l(t,S,P),C>1){var M={cause:f+","+m,reach:I};s(e,t,n,S.prev,E,M),d&&M.reach>d.reach&&(d.reach=M.reach)}}}}}}function i(){var e={value:null,prev:null,next:null},t={value:null,prev:e,next:null};e.next=t,this.head=e,this.tail=t,this.length=0}function l(e,t,n){var a=t.next,r={value:n,prev:t,next:a};return t.next=r,a.prev=r,e.length++,r}function c(e,t,n){for(var a=t.next,r=0;r<n&&a!==e.tail;r++)a=a.next;t.next=a,a.prev=t,e.length-=r}return r.stringify=function e(t,n){if("string"==typeof t)return t;if(Array.isArray(t)){var r="";return t.forEach((function(t){r+=e(t,n)})),r}var o={type:t.type,content:e(t.content,n),tag:"span",classes:["token",t.type],attributes:{},language:n},s=t.alias;s&&(Array.isArray(s)?Array.prototype.push.apply(o.classes,s):o.classes.push(s)),a.hooks.run("wrap",o);var i="";for(var l in o.attributes)i+=" "+l+'="'+(o.attributes[l]||"").replace(/"/g,""")+'"';return"<"+o.tag+' class="'+o.classes.join(" ")+'"'+i+">"+o.content+"</"+o.tag+">"},a}(),r=a;a.default=a,r.languages.markup={comment:{pattern:/<!--(?:(?!<!--)[\s\S])*?-->/,greedy:!0},prolog:{pattern:/<\?[\s\S]+?\?>/,greedy:!0},doctype:{pattern:/<!DOCTYPE(?:[^>"'[\]]|"[^"]*"|'[^']*')+(?:\[(?:[^<"'\]]|"[^"]*"|'[^']*'|<(?!!--)|<!--(?:[^-]|-(?!->))*-->)*\]\s*)?>/i,greedy:!0,inside:{"internal-subset":{pattern:/(^[^\[]*\[)[\s\S]+(?=\]>$)/,lookbehind:!0,greedy:!0,inside:null},string:{pattern:/"[^"]*"|'[^']*'/,greedy:!0},punctuation:/^<!|>$|[[\]]/,"doctype-tag":/^DOCTYPE/i,name:/[^\s<>'"]+/}},cdata:{pattern:/<!\[CDATA\[[\s\S]*?\]\]>/i,greedy:!0},tag:{pattern:/<\/?(?!\d)[^\s>\/=$<%]+(?:\s(?:\s*[^\s>\/=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))|(?=[\s/>])))+)?\s*\/?>/,greedy:!0,inside:{tag:{pattern:/^<\/?[^\s>\/]+/,inside:{punctuation:/^<\/?/,namespace:/^[^\s>\/:]+:/}},"special-attr":[],"attr-value":{pattern:/=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+)/,inside:{punctuation:[{pattern:/^=/,alias:"attr-equals"},/"|'/]}},punctuation:/\/?>/,"attr-name":{pattern:/[^\s>\/]+/,inside:{namespace:/^[^\s>\/:]+:/}}}},entity:[{pattern:/&[\da-z]{1,8};/i,alias:"named-entity"},/&#x?[\da-f]{1,8};/i]},r.languages.markup.tag.inside["attr-value"].inside.entity=r.languages.markup.entity,r.languages.markup.doctype.inside["internal-subset"].inside=r.languages.markup,r.hooks.add("wrap",(function(e){"entity"===e.type&&(e.attributes.title=e.content.replace(/&/,"&"))})),Object.defineProperty(r.languages.markup.tag,"addInlined",{value:function(e,t){var n={};n["language-"+t]={pattern:/(^<!\[CDATA\[)[\s\S]+?(?=\]\]>$)/i,lookbehind:!0,inside:r.languages[t]},n.cdata=/^<!\[CDATA\[|\]\]>$/i;var a={"included-cdata":{pattern:/<!\[CDATA\[[\s\S]*?\]\]>/i,inside:n}};a["language-"+t]={pattern:/[\s\S]+/,inside:r.languages[t]};var o={};o[e]={pattern:RegExp(/(<__[^>]*>)(?:<!\[CDATA\[(?:[^\]]|\](?!\]>))*\]\]>|(?!<!\[CDATA\[)[\s\S])*?(?=<\/__>)/.source.replace(/__/g,(function(){return e})),"i"),lookbehind:!0,greedy:!0,inside:a},r.languages.insertBefore("markup","cdata",o)}}),Object.defineProperty(r.languages.markup.tag,"addAttribute",{value:function(e,t){r.languages.markup.tag.inside["special-attr"].push({pattern:RegExp(/(^|["'\s])/.source+"(?:"+e+")"+/\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))/.source,"i"),lookbehind:!0,inside:{"attr-name":/^[^\s=]+/,"attr-value":{pattern:/=[\s\S]+/,inside:{value:{pattern:/(^=\s*(["']|(?!["'])))\S[\s\S]*(?=\2$)/,lookbehind:!0,alias:[t,"language-"+t],inside:r.languages[t]},punctuation:[{pattern:/^=/,alias:"attr-equals"},/"|'/]}}}})}}),r.languages.html=r.languages.markup,r.languages.mathml=r.languages.markup,r.languages.svg=r.languages.markup,r.languages.xml=r.languages.extend("markup",{}),r.languages.ssml=r.languages.xml,r.languages.atom=r.languages.xml,r.languages.rss=r.languages.xml,function(e){var t="\\b(?:BASH|BASHOPTS|BASH_ALIASES|BASH_ARGC|BASH_ARGV|BASH_CMDS|BASH_COMPLETION_COMPAT_DIR|BASH_LINENO|BASH_REMATCH|BASH_SOURCE|BASH_VERSINFO|BASH_VERSION|COLORTERM|COLUMNS|COMP_WORDBREAKS|DBUS_SESSION_BUS_ADDRESS|DEFAULTS_PATH|DESKTOP_SESSION|DIRSTACK|DISPLAY|EUID|GDMSESSION|GDM_LANG|GNOME_KEYRING_CONTROL|GNOME_KEYRING_PID|GPG_AGENT_INFO|GROUPS|HISTCONTROL|HISTFILE|HISTFILESIZE|HISTSIZE|HOME|HOSTNAME|HOSTTYPE|IFS|INSTANCE|JOB|LANG|LANGUAGE|LC_ADDRESS|LC_ALL|LC_IDENTIFICATION|LC_MEASUREMENT|LC_MONETARY|LC_NAME|LC_NUMERIC|LC_PAPER|LC_TELEPHONE|LC_TIME|LESSCLOSE|LESSOPEN|LINES|LOGNAME|LS_COLORS|MACHTYPE|MAILCHECK|MANDATORY_PATH|NO_AT_BRIDGE|OLDPWD|OPTERR|OPTIND|ORBIT_SOCKETDIR|OSTYPE|PAPERSIZE|PATH|PIPESTATUS|PPID|PS1|PS2|PS3|PS4|PWD|RANDOM|REPLY|SECONDS|SELINUX_INIT|SESSION|SESSIONTYPE|SESSION_MANAGER|SHELL|SHELLOPTS|SHLVL|SSH_AUTH_SOCK|TERM|UID|UPSTART_EVENTS|UPSTART_INSTANCE|UPSTART_JOB|UPSTART_SESSION|USER|WINDOWID|XAUTHORITY|XDG_CONFIG_DIRS|XDG_CURRENT_DESKTOP|XDG_DATA_DIRS|XDG_GREETER_DATA_DIR|XDG_MENU_PREFIX|XDG_RUNTIME_DIR|XDG_SEAT|XDG_SEAT_PATH|XDG_SESSION_DESKTOP|XDG_SESSION_ID|XDG_SESSION_PATH|XDG_SESSION_TYPE|XDG_VTNR|XMODIFIERS)\\b",n={pattern:/(^(["']?)\w+\2)[ \t]+\S.*/,lookbehind:!0,alias:"punctuation",inside:null},a={bash:n,environment:{pattern:RegExp("\\$"+t),alias:"constant"},variable:[{pattern:/\$?\(\([\s\S]+?\)\)/,greedy:!0,inside:{variable:[{pattern:/(^\$\(\([\s\S]+)\)\)/,lookbehind:!0},/^\$\(\(/],number:/\b0x[\dA-Fa-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:[Ee]-?\d+)?/,operator:/--|\+\+|\*\*=?|<<=?|>>=?|&&|\|\||[=!+\-*/%<>^&|]=?|[?~:]/,punctuation:/\(\(?|\)\)?|,|;/}},{pattern:/\$\((?:\([^)]+\)|[^()])+\)|`[^`]+`/,greedy:!0,inside:{variable:/^\$\(|^`|\)$|`$/}},{pattern:/\$\{[^}]+\}/,greedy:!0,inside:{operator:/:[-=?+]?|[!\/]|##?|%%?|\^\^?|,,?/,punctuation:/[\[\]]/,environment:{pattern:RegExp("(\\{)"+t),lookbehind:!0,alias:"constant"}}},/\$(?:\w+|[#?*!@$])/],entity:/\\(?:[abceEfnrtv\\"]|O?[0-7]{1,3}|U[0-9a-fA-F]{8}|u[0-9a-fA-F]{4}|x[0-9a-fA-F]{1,2})/};e.languages.bash={shebang:{pattern:/^#!\s*\/.*/,alias:"important"},comment:{pattern:/(^|[^"{\\$])#.*/,lookbehind:!0},"function-name":[{pattern:/(\bfunction\s+)[\w-]+(?=(?:\s*\(?:\s*\))?\s*\{)/,lookbehind:!0,alias:"function"},{pattern:/\b[\w-]+(?=\s*\(\s*\)\s*\{)/,alias:"function"}],"for-or-select":{pattern:/(\b(?:for|select)\s+)\w+(?=\s+in\s)/,alias:"variable",lookbehind:!0},"assign-left":{pattern:/(^|[\s;|&]|[<>]\()\w+(?=\+?=)/,inside:{environment:{pattern:RegExp("(^|[\\s;|&]|[<>]\\()"+t),lookbehind:!0,alias:"constant"}},alias:"variable",lookbehind:!0},string:[{pattern:/((?:^|[^<])<<-?\s*)(\w+)\s[\s\S]*?(?:\r?\n|\r)\2/,lookbehind:!0,greedy:!0,inside:a},{pattern:/((?:^|[^<])<<-?\s*)(["'])(\w+)\2\s[\s\S]*?(?:\r?\n|\r)\3/,lookbehind:!0,greedy:!0,inside:{bash:n}},{pattern:/(^|[^\\](?:\\\\)*)"(?:\\[\s\S]|\$\([^)]+\)|\$(?!\()|`[^`]+`|[^"\\`$])*"/,lookbehind:!0,greedy:!0,inside:a},{pattern:/(^|[^$\\])'[^']*'/,lookbehind:!0,greedy:!0},{pattern:/\$'(?:[^'\\]|\\[\s\S])*'/,greedy:!0,inside:{entity:a.entity}}],environment:{pattern:RegExp("\\$?"+t),alias:"constant"},variable:a.variable,function:{pattern:/(^|[\s;|&]|[<>]\()(?:add|apropos|apt|apt-cache|apt-get|aptitude|aspell|automysqlbackup|awk|basename|bash|bc|bconsole|bg|bzip2|cal|cat|cfdisk|chgrp|chkconfig|chmod|chown|chroot|cksum|clear|cmp|column|comm|composer|cp|cron|crontab|csplit|curl|cut|date|dc|dd|ddrescue|debootstrap|df|diff|diff3|dig|dir|dircolors|dirname|dirs|dmesg|docker|docker-compose|du|egrep|eject|env|ethtool|expand|expect|expr|fdformat|fdisk|fg|fgrep|file|find|fmt|fold|format|free|fsck|ftp|fuser|gawk|git|gparted|grep|groupadd|groupdel|groupmod|groups|grub-mkconfig|gzip|halt|head|hg|history|host|hostname|htop|iconv|id|ifconfig|ifdown|ifup|import|install|ip|jobs|join|kill|killall|less|link|ln|locate|logname|logrotate|look|lpc|lpr|lprint|lprintd|lprintq|lprm|ls|lsof|lynx|make|man|mc|mdadm|mkconfig|mkdir|mke2fs|mkfifo|mkfs|mkisofs|mknod|mkswap|mmv|more|most|mount|mtools|mtr|mutt|mv|nano|nc|netstat|nice|nl|node|nohup|notify-send|npm|nslookup|op|open|parted|passwd|paste|pathchk|ping|pkill|pnpm|podman|podman-compose|popd|pr|printcap|printenv|ps|pushd|pv|quota|quotacheck|quotactl|ram|rar|rcp|reboot|remsync|rename|renice|rev|rm|rmdir|rpm|rsync|scp|screen|sdiff|sed|sendmail|seq|service|sftp|sh|shellcheck|shuf|shutdown|sleep|slocate|sort|split|ssh|stat|strace|su|sudo|sum|suspend|swapon|sync|tac|tail|tar|tee|time|timeout|top|touch|tr|traceroute|tsort|tty|umount|uname|unexpand|uniq|units|unrar|unshar|unzip|update-grub|uptime|useradd|userdel|usermod|users|uudecode|uuencode|v|vcpkg|vdir|vi|vim|virsh|vmstat|wait|watch|wc|wget|whereis|which|who|whoami|write|xargs|xdg-open|yarn|yes|zenity|zip|zsh|zypper)(?=$|[)\s;|&])/,lookbehind:!0},keyword:{pattern:/(^|[\s;|&]|[<>]\()(?:case|do|done|elif|else|esac|fi|for|function|if|in|select|then|until|while)(?=$|[)\s;|&])/,lookbehind:!0},builtin:{pattern:/(^|[\s;|&]|[<>]\()(?:\.|:|alias|bind|break|builtin|caller|cd|command|continue|declare|echo|enable|eval|exec|exit|export|getopts|hash|help|let|local|logout|mapfile|printf|pwd|read|readarray|readonly|return|set|shift|shopt|source|test|times|trap|type|typeset|ulimit|umask|unalias|unset)(?=$|[)\s;|&])/,lookbehind:!0,alias:"class-name"},boolean:{pattern:/(^|[\s;|&]|[<>]\()(?:false|true)(?=$|[)\s;|&])/,lookbehind:!0},"file-descriptor":{pattern:/\B&\d\b/,alias:"important"},operator:{pattern:/\d?<>|>\||\+=|=[=~]?|!=?|<<[<-]?|[&\d]?>>|\d[<>]&?|[<>][&=]?|&[>&]?|\|[&|]?/,inside:{"file-descriptor":{pattern:/^\d/,alias:"important"}}},punctuation:/\$?\(\(?|\)\)?|\.\.|[{}[\];\\]/,number:{pattern:/(^|\s)(?:[1-9]\d*|0)(?:[.,]\d+)?\b/,lookbehind:!0}},n.inside=e.languages.bash;for(var r=["comment","function-name","for-or-select","assign-left","string","environment","function","keyword","builtin","boolean","file-descriptor","operator","punctuation","number"],o=a.variable[1].inside,s=0;s<r.length;s++)o[r[s]]=e.languages.bash[r[s]];e.languages.shell=e.languages.bash}(r),r.languages.clike={comment:[{pattern:/(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/,lookbehind:!0,greedy:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0,greedy:!0}],string:{pattern:/(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},"class-name":{pattern:/(\b(?:class|extends|implements|instanceof|interface|new|trait)\s+|\bcatch\s+\()[\w.\\]+/i,lookbehind:!0,inside:{punctuation:/[.\\]/}},keyword:/\b(?:break|catch|continue|do|else|finally|for|function|if|in|instanceof|new|null|return|throw|try|while)\b/,boolean:/\b(?:false|true)\b/,function:/\b\w+(?=\()/,number:/\b0x[\da-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?/i,operator:/[<>]=?|[!=]=?=?|--?|\+\+?|&&?|\|\|?|[?*/~^%]/,punctuation:/[{}[\];(),.:]/},r.languages.c=r.languages.extend("clike",{comment:{pattern:/\/\/(?:[^\r\n\\]|\\(?:\r\n?|\n|(?![\r\n])))*|\/\*[\s\S]*?(?:\*\/|$)/,greedy:!0},string:{pattern:/"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"/,greedy:!0},"class-name":{pattern:/(\b(?:enum|struct)\s+(?:__attribute__\s*\(\([\s\S]*?\)\)\s*)?)\w+|\b[a-z]\w*_t\b/,lookbehind:!0},keyword:/\b(?:_Alignas|_Alignof|_Atomic|_Bool|_Complex|_Generic|_Imaginary|_Noreturn|_Static_assert|_Thread_local|__attribute__|asm|auto|break|case|char|const|continue|default|do|double|else|enum|extern|float|for|goto|if|inline|int|long|register|return|short|signed|sizeof|static|struct|switch|typedef|typeof|union|unsigned|void|volatile|while)\b/,function:/\b[a-z_]\w*(?=\s*\()/i,number:/(?:\b0x(?:[\da-f]+(?:\.[\da-f]*)?|\.[\da-f]+)(?:p[+-]?\d+)?|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?)[ful]{0,4}/i,operator:/>>=?|<<=?|->|([-+&|:])\1|[?:~]|[-+*/%&|^!=<>]=?/}),r.languages.insertBefore("c","string",{char:{pattern:/'(?:\\(?:\r\n|[\s\S])|[^'\\\r\n]){0,32}'/,greedy:!0}}),r.languages.insertBefore("c","string",{macro:{pattern:/(^[\t ]*)#\s*[a-z](?:[^\r\n\\/]|\/(?!\*)|\/\*(?:[^*]|\*(?!\/))*\*\/|\\(?:\r\n|[\s\S]))*/im,lookbehind:!0,greedy:!0,alias:"property",inside:{string:[{pattern:/^(#\s*include\s*)<[^>]+>/,lookbehind:!0},r.languages.c.string],char:r.languages.c.char,comment:r.languages.c.comment,"macro-name":[{pattern:/(^#\s*define\s+)\w+\b(?!\()/i,lookbehind:!0},{pattern:/(^#\s*define\s+)\w+\b(?=\()/i,lookbehind:!0,alias:"function"}],directive:{pattern:/^(#\s*)[a-z]+/,lookbehind:!0,alias:"keyword"},"directive-hash":/^#/,punctuation:/##|\\(?=[\r\n])/,expression:{pattern:/\S[\s\S]*/,inside:r.languages.c}}}}),r.languages.insertBefore("c","function",{constant:/\b(?:EOF|NULL|SEEK_CUR|SEEK_END|SEEK_SET|__DATE__|__FILE__|__LINE__|__TIMESTAMP__|__TIME__|__func__|stderr|stdin|stdout)\b/}),delete r.languages.c.boolean,function(e){var t=/\b(?:alignas|alignof|asm|auto|bool|break|case|catch|char|char16_t|char32_t|char8_t|class|co_await|co_return|co_yield|compl|concept|const|const_cast|consteval|constexpr|constinit|continue|decltype|default|delete|do|double|dynamic_cast|else|enum|explicit|export|extern|final|float|for|friend|goto|if|import|inline|int|int16_t|int32_t|int64_t|int8_t|long|module|mutable|namespace|new|noexcept|nullptr|operator|override|private|protected|public|register|reinterpret_cast|requires|return|short|signed|sizeof|static|static_assert|static_cast|struct|switch|template|this|thread_local|throw|try|typedef|typeid|typename|uint16_t|uint32_t|uint64_t|uint8_t|union|unsigned|using|virtual|void|volatile|wchar_t|while)\b/,n=/\b(?!<keyword>)\w+(?:\s*\.\s*\w+)*\b/.source.replace(/<keyword>/g,(function(){return t.source}));e.languages.cpp=e.languages.extend("c",{"class-name":[{pattern:RegExp(/(\b(?:class|concept|enum|struct|typename)\s+)(?!<keyword>)\w+/.source.replace(/<keyword>/g,(function(){return t.source}))),lookbehind:!0},/\b[A-Z]\w*(?=\s*::\s*\w+\s*\()/,/\b[A-Z_]\w*(?=\s*::\s*~\w+\s*\()/i,/\b\w+(?=\s*<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>\s*::\s*\w+\s*\()/],keyword:t,number:{pattern:/(?:\b0b[01']+|\b0x(?:[\da-f']+(?:\.[\da-f']*)?|\.[\da-f']+)(?:p[+-]?[\d']+)?|(?:\b[\d']+(?:\.[\d']*)?|\B\.[\d']+)(?:e[+-]?[\d']+)?)[ful]{0,4}/i,greedy:!0},operator:/>>=?|<<=?|->|--|\+\+|&&|\|\||[?:~]|<=>|[-+*/%&|^!=<>]=?|\b(?:and|and_eq|bitand|bitor|not|not_eq|or|or_eq|xor|xor_eq)\b/,boolean:/\b(?:false|true)\b/}),e.languages.insertBefore("cpp","string",{module:{pattern:RegExp(/(\b(?:import|module)\s+)/.source+"(?:"+/"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"|<[^<>\r\n]*>/.source+"|"+/<mod-name>(?:\s*:\s*<mod-name>)?|:\s*<mod-name>/.source.replace(/<mod-name>/g,(function(){return n}))+")"),lookbehind:!0,greedy:!0,inside:{string:/^[<"][\s\S]+/,operator:/:/,punctuation:/\./}},"raw-string":{pattern:/R"([^()\\ ]{0,16})\([\s\S]*?\)\1"/,alias:"string",greedy:!0}}),e.languages.insertBefore("cpp","keyword",{"generic-function":{pattern:/\b(?!operator\b)[a-z_]\w*\s*<(?:[^<>]|<[^<>]*>)*>(?=\s*\()/i,inside:{function:/^\w+/,generic:{pattern:/<[\s\S]+/,alias:"class-name",inside:e.languages.cpp}}}}),e.languages.insertBefore("cpp","operator",{"double-colon":{pattern:/::/,alias:"punctuation"}}),e.languages.insertBefore("cpp","class-name",{"base-clause":{pattern:/(\b(?:class|struct)\s+\w+\s*:\s*)[^;{}"'\s]+(?:\s+[^;{}"'\s]+)*(?=\s*[;{])/,lookbehind:!0,greedy:!0,inside:e.languages.extend("cpp",{})}}),e.languages.insertBefore("inside","double-colon",{"class-name":/\b[a-z_]\w*\b(?!\s*::)/i},e.languages.cpp["base-clause"])}(r),function(e){var t=/(?:"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"|'(?:\\(?:\r\n|[\s\S])|[^'\\\r\n])*')/;e.languages.css={comment:/\/\*[\s\S]*?\*\//,atrule:{pattern:/@[\w-](?:[^;{\s]|\s+(?![\s{]))*(?:;|(?=\s*\{))/,inside:{rule:/^@[\w-]+/,"selector-function-argument":{pattern:/(\bselector\s*\(\s*(?![\s)]))(?:[^()\s]|\s+(?![\s)])|\((?:[^()]|\([^()]*\))*\))+(?=\s*\))/,lookbehind:!0,alias:"selector"},keyword:{pattern:/(^|[^\w-])(?:and|not|only|or)(?![\w-])/,lookbehind:!0}}},url:{pattern:RegExp("\\burl\\((?:"+t.source+"|"+/(?:[^\\\r\n()"']|\\[\s\S])*/.source+")\\)","i"),greedy:!0,inside:{function:/^url/i,punctuation:/^\(|\)$/,string:{pattern:RegExp("^"+t.source+"$"),alias:"url"}}},selector:{pattern:RegExp("(^|[{}\\s])[^{}\\s](?:[^{};\"'\\s]|\\s+(?![\\s{])|"+t.source+")*(?=\\s*\\{)"),lookbehind:!0},string:{pattern:t,greedy:!0},property:{pattern:/(^|[^-\w\xA0-\uFFFF])(?!\s)[-_a-z\xA0-\uFFFF](?:(?!\s)[-\w\xA0-\uFFFF])*(?=\s*:)/i,lookbehind:!0},important:/!important\b/i,function:{pattern:/(^|[^-a-z0-9])[-a-z0-9]+(?=\()/i,lookbehind:!0},punctuation:/[(){};:,]/},e.languages.css.atrule.inside.rest=e.languages.css;var n=e.languages.markup;n&&(n.tag.addInlined("style","css"),n.tag.addAttribute("style","css"))}(r),function(e){var t,n=/("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/;e.languages.css.selector={pattern:e.languages.css.selector.pattern,lookbehind:!0,inside:t={"pseudo-element":/:(?:after|before|first-letter|first-line|selection)|::[-\w]+/,"pseudo-class":/:[-\w]+/,class:/\.[-\w]+/,id:/#[-\w]+/,attribute:{pattern:RegExp("\\[(?:[^[\\]\"']|"+n.source+")*\\]"),greedy:!0,inside:{punctuation:/^\[|\]$/,"case-sensitivity":{pattern:/(\s)[si]$/i,lookbehind:!0,alias:"keyword"},namespace:{pattern:/^(\s*)(?:(?!\s)[-*\w\xA0-\uFFFF])*\|(?!=)/,lookbehind:!0,inside:{punctuation:/\|$/}},"attr-name":{pattern:/^(\s*)(?:(?!\s)[-\w\xA0-\uFFFF])+/,lookbehind:!0},"attr-value":[n,{pattern:/(=\s*)(?:(?!\s)[-\w\xA0-\uFFFF])+(?=\s*$)/,lookbehind:!0}],operator:/[|~*^$]?=/}},"n-th":[{pattern:/(\(\s*)[+-]?\d*[\dn](?:\s*[+-]\s*\d+)?(?=\s*\))/,lookbehind:!0,inside:{number:/[\dn]+/,operator:/[+-]/}},{pattern:/(\(\s*)(?:even|odd)(?=\s*\))/i,lookbehind:!0}],combinator:/>|\+|~|\|\|/,punctuation:/[(),]/}},e.languages.css.atrule.inside["selector-function-argument"].inside=t,e.languages.insertBefore("css","property",{variable:{pattern:/(^|[^-\w\xA0-\uFFFF])--(?!\s)[-_a-z\xA0-\uFFFF](?:(?!\s)[-\w\xA0-\uFFFF])*/i,lookbehind:!0}});var a={pattern:/(\b\d+)(?:%|[a-z]+(?![\w-]))/,lookbehind:!0},r={pattern:/(^|[^\w.-])-?(?:\d+(?:\.\d+)?|\.\d+)/,lookbehind:!0};e.languages.insertBefore("css","function",{operator:{pattern:/(\s)[+\-*\/](?=\s)/,lookbehind:!0},hexcode:{pattern:/\B#[\da-f]{3,8}\b/i,alias:"color"},color:[{pattern:/(^|[^\w-])(?:AliceBlue|AntiqueWhite|Aqua|Aquamarine|Azure|Beige|Bisque|Black|BlanchedAlmond|Blue|BlueViolet|Brown|BurlyWood|CadetBlue|Chartreuse|Chocolate|Coral|CornflowerBlue|Cornsilk|Crimson|Cyan|DarkBlue|DarkCyan|DarkGoldenRod|DarkGr[ae]y|DarkGreen|DarkKhaki|DarkMagenta|DarkOliveGreen|DarkOrange|DarkOrchid|DarkRed|DarkSalmon|DarkSeaGreen|DarkSlateBlue|DarkSlateGr[ae]y|DarkTurquoise|DarkViolet|DeepPink|DeepSkyBlue|DimGr[ae]y|DodgerBlue|FireBrick|FloralWhite|ForestGreen|Fuchsia|Gainsboro|GhostWhite|Gold|GoldenRod|Gr[ae]y|Green|GreenYellow|HoneyDew|HotPink|IndianRed|Indigo|Ivory|Khaki|Lavender|LavenderBlush|LawnGreen|LemonChiffon|LightBlue|LightCoral|LightCyan|LightGoldenRodYellow|LightGr[ae]y|LightGreen|LightPink|LightSalmon|LightSeaGreen|LightSkyBlue|LightSlateGr[ae]y|LightSteelBlue|LightYellow|Lime|LimeGreen|Linen|Magenta|Maroon|MediumAquaMarine|MediumBlue|MediumOrchid|MediumPurple|MediumSeaGreen|MediumSlateBlue|MediumSpringGreen|MediumTurquoise|MediumVioletRed|MidnightBlue|MintCream|MistyRose|Moccasin|NavajoWhite|Navy|OldLace|Olive|OliveDrab|Orange|OrangeRed|Orchid|PaleGoldenRod|PaleGreen|PaleTurquoise|PaleVioletRed|PapayaWhip|PeachPuff|Peru|Pink|Plum|PowderBlue|Purple|Red|RosyBrown|RoyalBlue|SaddleBrown|Salmon|SandyBrown|SeaGreen|SeaShell|Sienna|Silver|SkyBlue|SlateBlue|SlateGr[ae]y|Snow|SpringGreen|SteelBlue|Tan|Teal|Thistle|Tomato|Transparent|Turquoise|Violet|Wheat|White|WhiteSmoke|Yellow|YellowGreen)(?![\w-])/i,lookbehind:!0},{pattern:/\b(?:hsl|rgb)\(\s*\d{1,3}\s*,\s*\d{1,3}%?\s*,\s*\d{1,3}%?\s*\)\B|\b(?:hsl|rgb)a\(\s*\d{1,3}\s*,\s*\d{1,3}%?\s*,\s*\d{1,3}%?\s*,\s*(?:0|0?\.\d+|1)\s*\)\B/i,inside:{unit:a,number:r,function:/[\w-]+(?=\()/,punctuation:/[(),]/}}],entity:/\\[\da-f]{1,8}/i,unit:a,number:r})}(r),r.languages.javascript=r.languages.extend("clike",{"class-name":[r.languages.clike["class-name"],{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$A-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\.(?:constructor|prototype))/,lookbehind:!0}],keyword:[{pattern:/((?:^|\})\s*)catch\b/,lookbehind:!0},{pattern:/(^|[^.]|\.\.\.\s*)\b(?:as|assert(?=\s*\{)|async(?=\s*(?:function\b|\(|[$\w\xA0-\uFFFF]|$))|await|break|case|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally(?=\s*(?:\{|$))|for|from(?=\s*(?:['"]|$))|function|(?:get|set)(?=\s*(?:[#\[$\w\xA0-\uFFFF]|$))|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)\b/,lookbehind:!0}],function:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*(?:\.\s*(?:apply|bind|call)\s*)?\()/,number:{pattern:RegExp(/(^|[^\w$])/.source+"(?:"+/NaN|Infinity/.source+"|"+/0[bB][01]+(?:_[01]+)*n?/.source+"|"+/0[oO][0-7]+(?:_[0-7]+)*n?/.source+"|"+/0[xX][\dA-Fa-f]+(?:_[\dA-Fa-f]+)*n?/.source+"|"+/\d+(?:_\d+)*n/.source+"|"+/(?:\d+(?:_\d+)*(?:\.(?:\d+(?:_\d+)*)?)?|\.\d+(?:_\d+)*)(?:[Ee][+-]?\d+(?:_\d+)*)?/.source+")"+/(?![\w$])/.source),lookbehind:!0},operator:/--|\+\+|\*\*=?|=>|&&=?|\|\|=?|[!=]==|<<=?|>>>?=?|[-+*/%&|^!=<>]=?|\.{3}|\?\?=?|\?\.?|[~:]/}),r.languages.javascript["class-name"][0].pattern=/(\b(?:class|extends|implements|instanceof|interface|new)\s+)[\w.\\]+/,r.languages.insertBefore("javascript","keyword",{regex:{pattern:/((?:^|[^$\w\xA0-\uFFFF."'\])\s]|\b(?:return|yield))\s*)\/(?:\[(?:[^\]\\\r\n]|\\.)*\]|\\.|[^/\\\[\r\n])+\/[dgimyus]{0,7}(?=(?:\s|\/\*(?:[^*]|\*(?!\/))*\*\/)*(?:$|[\r\n,.;:})\]]|\/\/))/,lookbehind:!0,greedy:!0,inside:{"regex-source":{pattern:/^(\/)[\s\S]+(?=\/[a-z]*$)/,lookbehind:!0,alias:"language-regex",inside:r.languages.regex},"regex-delimiter":/^\/|\/$/,"regex-flags":/^[a-z]+$/}},"function-variable":{pattern:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*[=:]\s*(?:async\s*)?(?:\bfunction\b|(?:\((?:[^()]|\([^()]*\))*\)|(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)\s*=>))/,alias:"function"},parameter:[{pattern:/(function(?:\s+(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)?\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\))/,lookbehind:!0,inside:r.languages.javascript},{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$a-z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*=>)/i,lookbehind:!0,inside:r.languages.javascript},{pattern:/(\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*=>)/,lookbehind:!0,inside:r.languages.javascript},{pattern:/((?:\b|\s|^)(?!(?:as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)(?![$\w\xA0-\uFFFF]))(?:(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s*)\(\s*|\]\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*\{)/,lookbehind:!0,inside:r.languages.javascript}],constant:/\b[A-Z](?:[A-Z_]|\dx?)*\b/}),r.languages.insertBefore("javascript","string",{hashbang:{pattern:/^#!.*/,greedy:!0,alias:"comment"},"template-string":{pattern:/`(?:\\[\s\S]|\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}|(?!\$\{)[^\\`])*`/,greedy:!0,inside:{"template-punctuation":{pattern:/^`|`$/,alias:"string"},interpolation:{pattern:/((?:^|[^\\])(?:\\{2})*)\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}/,lookbehind:!0,inside:{"interpolation-punctuation":{pattern:/^\$\{|\}$/,alias:"punctuation"},rest:r.languages.javascript}},string:/[\s\S]+/}},"string-property":{pattern:/((?:^|[,{])[ \t]*)(["'])(?:\\(?:\r\n|[\s\S])|(?!\2)[^\\\r\n])*\2(?=\s*:)/m,lookbehind:!0,greedy:!0,alias:"property"}}),r.languages.insertBefore("javascript","operator",{"literal-property":{pattern:/((?:^|[,{])[ \t]*)(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*:)/m,lookbehind:!0,alias:"property"}}),r.languages.markup&&(r.languages.markup.tag.addInlined("script","javascript"),r.languages.markup.tag.addAttribute(/on(?:abort|blur|change|click|composition(?:end|start|update)|dblclick|error|focus(?:in|out)?|key(?:down|up)|load|mouse(?:down|enter|leave|move|out|over|up)|reset|resize|scroll|select|slotchange|submit|unload|wheel)/.source,"javascript")),r.languages.js=r.languages.javascript,function(e){var t=/#(?!\{).+/,n={pattern:/#\{[^}]+\}/,alias:"variable"};e.languages.coffeescript=e.languages.extend("javascript",{comment:t,string:[{pattern:/'(?:\\[\s\S]|[^\\'])*'/,greedy:!0},{pattern:/"(?:\\[\s\S]|[^\\"])*"/,greedy:!0,inside:{interpolation:n}}],keyword:/\b(?:and|break|by|catch|class|continue|debugger|delete|do|each|else|extend|extends|false|finally|for|if|in|instanceof|is|isnt|let|loop|namespace|new|no|not|null|of|off|on|or|own|return|super|switch|then|this|throw|true|try|typeof|undefined|unless|until|when|while|window|with|yes|yield)\b/,"class-member":{pattern:/@(?!\d)\w+/,alias:"variable"}}),e.languages.insertBefore("coffeescript","comment",{"multiline-comment":{pattern:/###[\s\S]+?###/,alias:"comment"},"block-regex":{pattern:/\/{3}[\s\S]*?\/{3}/,alias:"regex",inside:{comment:t,interpolation:n}}}),e.languages.insertBefore("coffeescript","string",{"inline-javascript":{pattern:/`(?:\\[\s\S]|[^\\`])*`/,inside:{delimiter:{pattern:/^`|`$/,alias:"punctuation"},script:{pattern:/[\s\S]+/,alias:"language-javascript",inside:e.languages.javascript}}},"multiline-string":[{pattern:/'''[\s\S]*?'''/,greedy:!0,alias:"string"},{pattern:/"""[\s\S]*?"""/,greedy:!0,alias:"string",inside:{interpolation:n}}]}),e.languages.insertBefore("coffeescript","keyword",{property:/(?!\d)\w+(?=\s*:(?!:))/}),delete e.languages.coffeescript["template-string"],e.languages.coffee=e.languages.coffeescript}(r),function(e){var t=/[*&][^\s[\]{},]+/,n=/!(?:<[\w\-%#;/?:@&=+$,.!~*'()[\]]+>|(?:[a-zA-Z\d-]*!)?[\w\-%#;/?:@&=+$.~*'()]+)?/,a="(?:"+n.source+"(?:[ \t]+"+t.source+")?|"+t.source+"(?:[ \t]+"+n.source+")?)",r=/(?:[^\s\x00-\x08\x0e-\x1f!"#%&'*,\-:>?@[\]`{|}\x7f-\x84\x86-\x9f\ud800-\udfff\ufffe\uffff]|[?:-]<PLAIN>)(?:[ \t]*(?:(?![#:])<PLAIN>|:<PLAIN>))*/.source.replace(/<PLAIN>/g,(function(){return/[^\s\x00-\x08\x0e-\x1f,[\]{}\x7f-\x84\x86-\x9f\ud800-\udfff\ufffe\uffff]/.source})),o=/"(?:[^"\\\r\n]|\\.)*"|'(?:[^'\\\r\n]|\\.)*'/.source;function s(e,t){t=(t||"").replace(/m/g,"")+"m";var n=/([:\-,[{]\s*(?:\s<<prop>>[ \t]+)?)(?:<<value>>)(?=[ \t]*(?:$|,|\]|\}|(?:[\r\n]\s*)?#))/.source.replace(/<<prop>>/g,(function(){return a})).replace(/<<value>>/g,(function(){return e}));return RegExp(n,t)}e.languages.yaml={scalar:{pattern:RegExp(/([\-:]\s*(?:\s<<prop>>[ \t]+)?[|>])[ \t]*(?:((?:\r?\n|\r)[ \t]+)\S[^\r\n]*(?:\2[^\r\n]+)*)/.source.replace(/<<prop>>/g,(function(){return a}))),lookbehind:!0,alias:"string"},comment:/#.*/,key:{pattern:RegExp(/((?:^|[:\-,[{\r\n?])[ \t]*(?:<<prop>>[ \t]+)?)<<key>>(?=\s*:\s)/.source.replace(/<<prop>>/g,(function(){return a})).replace(/<<key>>/g,(function(){return"(?:"+r+"|"+o+")"}))),lookbehind:!0,greedy:!0,alias:"atrule"},directive:{pattern:/(^[ \t]*)%.+/m,lookbehind:!0,alias:"important"},datetime:{pattern:s(/\d{4}-\d\d?-\d\d?(?:[tT]|[ \t]+)\d\d?:\d{2}:\d{2}(?:\.\d*)?(?:[ \t]*(?:Z|[-+]\d\d?(?::\d{2})?))?|\d{4}-\d{2}-\d{2}|\d\d?:\d{2}(?::\d{2}(?:\.\d*)?)?/.source),lookbehind:!0,alias:"number"},boolean:{pattern:s(/false|true/.source,"i"),lookbehind:!0,alias:"important"},null:{pattern:s(/null|~/.source,"i"),lookbehind:!0,alias:"important"},string:{pattern:s(o),lookbehind:!0,greedy:!0},number:{pattern:s(/[+-]?(?:0x[\da-f]+|0o[0-7]+|(?:\d+(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?|\.inf|\.nan)/.source,"i"),lookbehind:!0},tag:n,important:t,punctuation:/---|[:[\]{}\-,|>?]|\.\.\./},e.languages.yml=e.languages.yaml}(r),function(e){var t=/(?:\\.|[^\\\n\r]|(?:\n|\r\n?)(?![\r\n]))/.source;function n(e){return e=e.replace(/<inner>/g,(function(){return t})),RegExp(/((?:^|[^\\])(?:\\{2})*)/.source+"(?:"+e+")")}var a=/(?:\\.|``(?:[^`\r\n]|`(?!`))+``|`[^`\r\n]+`|[^\\|\r\n`])+/.source,r=/\|?__(?:\|__)+\|?(?:(?:\n|\r\n?)|(?![\s\S]))/.source.replace(/__/g,(function(){return a})),o=/\|?[ \t]*:?-{3,}:?[ \t]*(?:\|[ \t]*:?-{3,}:?[ \t]*)+\|?(?:\n|\r\n?)/.source;e.languages.markdown=e.languages.extend("markup",{}),e.languages.insertBefore("markdown","prolog",{"front-matter-block":{pattern:/(^(?:\s*[\r\n])?)---(?!.)[\s\S]*?[\r\n]---(?!.)/,lookbehind:!0,greedy:!0,inside:{punctuation:/^---|---$/,"front-matter":{pattern:/\S+(?:\s+\S+)*/,alias:["yaml","language-yaml"],inside:e.languages.yaml}}},blockquote:{pattern:/^>(?:[\t ]*>)*/m,alias:"punctuation"},table:{pattern:RegExp("^"+r+o+"(?:"+r+")*","m"),inside:{"table-data-rows":{pattern:RegExp("^("+r+o+")(?:"+r+")*$"),lookbehind:!0,inside:{"table-data":{pattern:RegExp(a),inside:e.languages.markdown},punctuation:/\|/}},"table-line":{pattern:RegExp("^("+r+")"+o+"$"),lookbehind:!0,inside:{punctuation:/\||:?-{3,}:?/}},"table-header-row":{pattern:RegExp("^"+r+"$"),inside:{"table-header":{pattern:RegExp(a),alias:"important",inside:e.languages.markdown},punctuation:/\|/}}}},code:[{pattern:/((?:^|\n)[ \t]*\n|(?:^|\r\n?)[ \t]*\r\n?)(?: {4}|\t).+(?:(?:\n|\r\n?)(?: {4}|\t).+)*/,lookbehind:!0,alias:"keyword"},{pattern:/^```[\s\S]*?^```$/m,greedy:!0,inside:{"code-block":{pattern:/^(```.*(?:\n|\r\n?))[\s\S]+?(?=(?:\n|\r\n?)^```$)/m,lookbehind:!0},"code-language":{pattern:/^(```).+/,lookbehind:!0},punctuation:/```/}}],title:[{pattern:/\S.*(?:\n|\r\n?)(?:==+|--+)(?=[ \t]*$)/m,alias:"important",inside:{punctuation:/==+$|--+$/}},{pattern:/(^\s*)#.+/m,lookbehind:!0,alias:"important",inside:{punctuation:/^#+|#+$/}}],hr:{pattern:/(^\s*)([*-])(?:[\t ]*\2){2,}(?=\s*$)/m,lookbehind:!0,alias:"punctuation"},list:{pattern:/(^\s*)(?:[*+-]|\d+\.)(?=[\t ].)/m,lookbehind:!0,alias:"punctuation"},"url-reference":{pattern:/!?\[[^\]]+\]:[\t ]+(?:\S+|<(?:\\.|[^>\\])+>)(?:[\t ]+(?:"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|\((?:\\.|[^)\\])*\)))?/,inside:{variable:{pattern:/^(!?\[)[^\]]+/,lookbehind:!0},string:/(?:"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|\((?:\\.|[^)\\])*\))$/,punctuation:/^[\[\]!:]|[<>]/},alias:"url"},bold:{pattern:n(/\b__(?:(?!_)<inner>|_(?:(?!_)<inner>)+_)+__\b|\*\*(?:(?!\*)<inner>|\*(?:(?!\*)<inner>)+\*)+\*\*/.source),lookbehind:!0,greedy:!0,inside:{content:{pattern:/(^..)[\s\S]+(?=..$)/,lookbehind:!0,inside:{}},punctuation:/\*\*|__/}},italic:{pattern:n(/\b_(?:(?!_)<inner>|__(?:(?!_)<inner>)+__)+_\b|\*(?:(?!\*)<inner>|\*\*(?:(?!\*)<inner>)+\*\*)+\*/.source),lookbehind:!0,greedy:!0,inside:{content:{pattern:/(^.)[\s\S]+(?=.$)/,lookbehind:!0,inside:{}},punctuation:/[*_]/}},strike:{pattern:n(/(~~?)(?:(?!~)<inner>)+\2/.source),lookbehind:!0,greedy:!0,inside:{content:{pattern:/(^~~?)[\s\S]+(?=\1$)/,lookbehind:!0,inside:{}},punctuation:/~~?/}},"code-snippet":{pattern:/(^|[^\\`])(?:``[^`\r\n]+(?:`[^`\r\n]+)*``(?!`)|`[^`\r\n]+`(?!`))/,lookbehind:!0,greedy:!0,alias:["code","keyword"]},url:{pattern:n(/!?\[(?:(?!\])<inner>)+\](?:\([^\s)]+(?:[\t ]+"(?:\\.|[^"\\])*")?\)|[ \t]?\[(?:(?!\])<inner>)+\])/.source),lookbehind:!0,greedy:!0,inside:{operator:/^!/,content:{pattern:/(^\[)[^\]]+(?=\])/,lookbehind:!0,inside:{}},variable:{pattern:/(^\][ \t]?\[)[^\]]+(?=\]$)/,lookbehind:!0},url:{pattern:/(^\]\()[^\s)]+/,lookbehind:!0},string:{pattern:/(^[ \t]+)"(?:\\.|[^"\\])*"(?=\)$)/,lookbehind:!0}}}}),["url","bold","italic","strike"].forEach((function(t){["url","bold","italic","strike","code-snippet"].forEach((function(n){t!==n&&(e.languages.markdown[t].inside.content.inside[n]=e.languages.markdown[n])}))})),e.hooks.add("after-tokenize",(function(e){"markdown"!==e.language&&"md"!==e.language||function e(t){if(t&&"string"!=typeof t)for(var n=0,a=t.length;n<a;n++){var r=t[n];if("code"===r.type){var o=r.content[1],s=r.content[3];if(o&&s&&"code-language"===o.type&&"code-block"===s.type&&"string"==typeof o.content){var i=o.content.replace(/\b#/g,"sharp").replace(/\b\+\+/g,"pp"),l="language-"+(i=(/[a-z][\w-]*/i.exec(i)||[""])[0].toLowerCase());s.alias?"string"==typeof s.alias?s.alias=[s.alias,l]:s.alias.push(l):s.alias=[l]}}else e(r.content)}}(e.tokens)})),e.hooks.add("wrap",(function(t){if("code-block"===t.type){for(var n="",a=0,r=t.classes.length;a<r;a++){var o=t.classes[a],c=/language-(.+)/.exec(o);if(c){n=c[1];break}}var u,d=e.languages[n];if(d)t.content=e.highlight((u=t.content,u.replace(s,"").replace(/&(\w{1,8}|#x?[\da-f]{1,8});/gi,(function(e,t){var n;if("#"===(t=t.toLowerCase())[0])return n="x"===t[1]?parseInt(t.slice(2),16):Number(t.slice(1)),l(n);var a=i[t];return a||e}))),d,n);else if(n&&"none"!==n&&e.plugins.autoloader){var f="md-"+(new Date).valueOf()+"-"+Math.floor(1e16*Math.random());t.attributes.id=f,e.plugins.autoloader.loadLanguages(n,(function(){var t=document.getElementById(f);t&&(t.innerHTML=e.highlight(t.textContent,e.languages[n],n))}))}}}));var s=RegExp(e.languages.markup.tag.pattern.source,"gi"),i={amp:"&",lt:"<",gt:">",quot:'"'},l=String.fromCodePoint||String.fromCharCode;e.languages.md=e.languages.markdown}(r),r.languages.graphql={comment:/#.*/,description:{pattern:/(?:"""(?:[^"]|(?!""")")*"""|"(?:\\.|[^\\"\r\n])*")(?=\s*[a-z_])/i,greedy:!0,alias:"string",inside:{"language-markdown":{pattern:/(^"(?:"")?)(?!\1)[\s\S]+(?=\1$)/,lookbehind:!0,inside:r.languages.markdown}}},string:{pattern:/"""(?:[^"]|(?!""")")*"""|"(?:\\.|[^\\"\r\n])*"/,greedy:!0},number:/(?:\B-|\b)\d+(?:\.\d+)?(?:e[+-]?\d+)?\b/i,boolean:/\b(?:false|true)\b/,variable:/\$[a-z_]\w*/i,directive:{pattern:/@[a-z_]\w*/i,alias:"function"},"attr-name":{pattern:/\b[a-z_]\w*(?=\s*(?:\((?:[^()"]|"(?:\\.|[^\\"\r\n])*")*\))?:)/i,greedy:!0},"atom-input":{pattern:/\b[A-Z]\w*Input\b/,alias:"class-name"},scalar:/\b(?:Boolean|Float|ID|Int|String)\b/,constant:/\b[A-Z][A-Z_\d]*\b/,"class-name":{pattern:/(\b(?:enum|implements|interface|on|scalar|type|union)\s+|&\s*|:\s*|\[)[A-Z_]\w*/,lookbehind:!0},fragment:{pattern:/(\bfragment\s+|\.{3}\s*(?!on\b))[a-zA-Z_]\w*/,lookbehind:!0,alias:"function"},"definition-mutation":{pattern:/(\bmutation\s+)[a-zA-Z_]\w*/,lookbehind:!0,alias:"function"},"definition-query":{pattern:/(\bquery\s+)[a-zA-Z_]\w*/,lookbehind:!0,alias:"function"},keyword:/\b(?:directive|enum|extend|fragment|implements|input|interface|mutation|on|query|repeatable|scalar|schema|subscription|type|union)\b/,operator:/[!=|&]|\.{3}/,"property-query":/\w+(?=\s*\()/,object:/\w+(?=\s*\{)/,punctuation:/[!(){}\[\]:=,]/,property:/\w+/},r.hooks.add("after-tokenize",(function(e){if("graphql"===e.language)for(var t=e.tokens.filter((function(e){return"string"!=typeof e&&"comment"!==e.type&&"scalar"!==e.type})),n=0;n<t.length;){var a=t[n++];if("keyword"===a.type&&"mutation"===a.content){var r=[];if(d(["definition-mutation","punctuation"])&&"("===u(1).content){n+=2;var o=f(/^\($/,/^\)$/);if(-1===o)continue;for(;n<o;n++){var s=u(0);"variable"===s.type&&(p(s,"variable-input"),r.push(s.content))}n=o+1}if(d(["punctuation","property-query"])&&"{"===u(0).content&&(n++,p(u(0),"property-mutation"),r.length>0)){var i=f(/^\{$/,/^\}$/);if(-1===i)continue;for(var l=n;l<i;l++){var c=t[l];"variable"===c.type&&r.indexOf(c.content)>=0&&p(c,"variable-input")}}}}function u(e){return t[n+e]}function d(e,t){t=t||0;for(var n=0;n<e.length;n++){var a=u(n+t);if(!a||a.type!==e[n])return!1}return!0}function f(e,a){for(var r=1,o=n;o<t.length;o++){var s=t[o],i=s.content;if("punctuation"===s.type&&"string"==typeof i)if(e.test(i))r++;else if(a.test(i)&&0===--r)return o}return-1}function p(e,t){var n=e.alias;n?Array.isArray(n)||(e.alias=n=[n]):e.alias=n=[],n.push(t)}})),r.languages.sql={comment:{pattern:/(^|[^\\])(?:\/\*[\s\S]*?\*\/|(?:--|\/\/|#).*)/,lookbehind:!0},variable:[{pattern:/@(["'`])(?:\\[\s\S]|(?!\1)[^\\])+\1/,greedy:!0},/@[\w.$]+/],string:{pattern:/(^|[^@\\])("|')(?:\\[\s\S]|(?!\2)[^\\]|\2\2)*\2/,greedy:!0,lookbehind:!0},identifier:{pattern:/(^|[^@\\])`(?:\\[\s\S]|[^`\\]|``)*`/,greedy:!0,lookbehind:!0,inside:{punctuation:/^`|`$/}},function:/\b(?:AVG|COUNT|FIRST|FORMAT|LAST|LCASE|LEN|MAX|MID|MIN|MOD|NOW|ROUND|SUM|UCASE)(?=\s*\()/i,keyword:/\b(?:ACTION|ADD|AFTER|ALGORITHM|ALL|ALTER|ANALYZE|ANY|APPLY|AS|ASC|AUTHORIZATION|AUTO_INCREMENT|BACKUP|BDB|BEGIN|BERKELEYDB|BIGINT|BINARY|BIT|BLOB|BOOL|BOOLEAN|BREAK|BROWSE|BTREE|BULK|BY|CALL|CASCADED?|CASE|CHAIN|CHAR(?:ACTER|SET)?|CHECK(?:POINT)?|CLOSE|CLUSTERED|COALESCE|COLLATE|COLUMNS?|COMMENT|COMMIT(?:TED)?|COMPUTE|CONNECT|CONSISTENT|CONSTRAINT|CONTAINS(?:TABLE)?|CONTINUE|CONVERT|CREATE|CROSS|CURRENT(?:_DATE|_TIME|_TIMESTAMP|_USER)?|CURSOR|CYCLE|DATA(?:BASES?)?|DATE(?:TIME)?|DAY|DBCC|DEALLOCATE|DEC|DECIMAL|DECLARE|DEFAULT|DEFINER|DELAYED|DELETE|DELIMITERS?|DENY|DESC|DESCRIBE|DETERMINISTIC|DISABLE|DISCARD|DISK|DISTINCT|DISTINCTROW|DISTRIBUTED|DO|DOUBLE|DROP|DUMMY|DUMP(?:FILE)?|DUPLICATE|ELSE(?:IF)?|ENABLE|ENCLOSED|END|ENGINE|ENUM|ERRLVL|ERRORS|ESCAPED?|EXCEPT|EXEC(?:UTE)?|EXISTS|EXIT|EXPLAIN|EXTENDED|FETCH|FIELDS|FILE|FILLFACTOR|FIRST|FIXED|FLOAT|FOLLOWING|FOR(?: EACH ROW)?|FORCE|FOREIGN|FREETEXT(?:TABLE)?|FROM|FULL|FUNCTION|GEOMETRY(?:COLLECTION)?|GLOBAL|GOTO|GRANT|GROUP|HANDLER|HASH|HAVING|HOLDLOCK|HOUR|IDENTITY(?:COL|_INSERT)?|IF|IGNORE|IMPORT|INDEX|INFILE|INNER|INNODB|INOUT|INSERT|INT|INTEGER|INTERSECT|INTERVAL|INTO|INVOKER|ISOLATION|ITERATE|JOIN|KEYS?|KILL|LANGUAGE|LAST|LEAVE|LEFT|LEVEL|LIMIT|LINENO|LINES|LINESTRING|LOAD|LOCAL|LOCK|LONG(?:BLOB|TEXT)|LOOP|MATCH(?:ED)?|MEDIUM(?:BLOB|INT|TEXT)|MERGE|MIDDLEINT|MINUTE|MODE|MODIFIES|MODIFY|MONTH|MULTI(?:LINESTRING|POINT|POLYGON)|NATIONAL|NATURAL|NCHAR|NEXT|NO|NONCLUSTERED|NULLIF|NUMERIC|OFF?|OFFSETS?|ON|OPEN(?:DATASOURCE|QUERY|ROWSET)?|OPTIMIZE|OPTION(?:ALLY)?|ORDER|OUT(?:ER|FILE)?|OVER|PARTIAL|PARTITION|PERCENT|PIVOT|PLAN|POINT|POLYGON|PRECEDING|PRECISION|PREPARE|PREV|PRIMARY|PRINT|PRIVILEGES|PROC(?:EDURE)?|PUBLIC|PURGE|QUICK|RAISERROR|READS?|REAL|RECONFIGURE|REFERENCES|RELEASE|RENAME|REPEAT(?:ABLE)?|REPLACE|REPLICATION|REQUIRE|RESIGNAL|RESTORE|RESTRICT|RETURN(?:ING|S)?|REVOKE|RIGHT|ROLLBACK|ROUTINE|ROW(?:COUNT|GUIDCOL|S)?|RTREE|RULE|SAVE(?:POINT)?|SCHEMA|SECOND|SELECT|SERIAL(?:IZABLE)?|SESSION(?:_USER)?|SET(?:USER)?|SHARE|SHOW|SHUTDOWN|SIMPLE|SMALLINT|SNAPSHOT|SOME|SONAME|SQL|START(?:ING)?|STATISTICS|STATUS|STRIPED|SYSTEM_USER|TABLES?|TABLESPACE|TEMP(?:ORARY|TABLE)?|TERMINATED|TEXT(?:SIZE)?|THEN|TIME(?:STAMP)?|TINY(?:BLOB|INT|TEXT)|TOP?|TRAN(?:SACTIONS?)?|TRIGGER|TRUNCATE|TSEQUAL|TYPES?|UNBOUNDED|UNCOMMITTED|UNDEFINED|UNION|UNIQUE|UNLOCK|UNPIVOT|UNSIGNED|UPDATE(?:TEXT)?|USAGE|USE|USER|USING|VALUES?|VAR(?:BINARY|CHAR|CHARACTER|YING)|VIEW|WAITFOR|WARNINGS|WHEN|WHERE|WHILE|WITH(?: ROLLUP|IN)?|WORK|WRITE(?:TEXT)?|YEAR)\b/i,boolean:/\b(?:FALSE|NULL|TRUE)\b/i,number:/\b0x[\da-f]+\b|\b\d+(?:\.\d*)?|\B\.\d+\b/i,operator:/[-+*\/=%^~]|&&?|\|\|?|!=?|<(?:=>?|<|>)?|>[>=]?|\b(?:AND|BETWEEN|DIV|ILIKE|IN|IS|LIKE|NOT|OR|REGEXP|RLIKE|SOUNDS LIKE|XOR)\b/i,punctuation:/[;[\]()`,.]/},function(e){var t=e.languages.javascript["template-string"],n=t.pattern.source,a=t.inside.interpolation,r=a.inside["interpolation-punctuation"],o=a.pattern.source;function s(t,a){if(e.languages[t])return{pattern:RegExp("((?:"+a+")\\s*)"+n),lookbehind:!0,greedy:!0,inside:{"template-punctuation":{pattern:/^`|`$/,alias:"string"},"embedded-code":{pattern:/[\s\S]+/,alias:t}}}}function i(e,t){return"___"+t.toUpperCase()+"_"+e+"___"}function l(t,n,a){var r={code:t,grammar:n,language:a};return e.hooks.run("before-tokenize",r),r.tokens=e.tokenize(r.code,r.grammar),e.hooks.run("after-tokenize",r),r.tokens}function c(t){var n={};n["interpolation-punctuation"]=r;var o=e.tokenize(t,n);if(3===o.length){var s=[1,1];s.push.apply(s,l(o[1],e.languages.javascript,"javascript")),o.splice.apply(o,s)}return new e.Token("interpolation",o,a.alias,t)}function u(t,n,a){var r=e.tokenize(t,{interpolation:{pattern:RegExp(o),lookbehind:!0}}),s=0,u={},d=l(r.map((function(e){if("string"==typeof e)return e;for(var n,r=e.content;-1!==t.indexOf(n=i(s++,a)););return u[n]=r,n})).join(""),n,a),f=Object.keys(u);return s=0,function e(t){for(var n=0;n<t.length;n++){if(s>=f.length)return;var a=t[n];if("string"==typeof a||"string"==typeof a.content){var r=f[s],o="string"==typeof a?a:a.content,i=o.indexOf(r);if(-1!==i){++s;var l=o.substring(0,i),d=c(u[r]),p=o.substring(i+r.length),m=[];if(l&&m.push(l),m.push(d),p){var g=[p];e(g),m.push.apply(m,g)}"string"==typeof a?(t.splice.apply(t,[n,1].concat(m)),n+=m.length-1):a.content=m}}else{var h=a.content;Array.isArray(h)?e(h):e([h])}}}(d),new e.Token(a,d,"language-"+a,t)}e.languages.javascript["template-string"]=[s("css",/\b(?:styled(?:\([^)]*\))?(?:\s*\.\s*\w+(?:\([^)]*\))*)*|css(?:\s*\.\s*(?:global|resolve))?|createGlobalStyle|keyframes)/.source),s("html",/\bhtml|\.\s*(?:inner|outer)HTML\s*\+?=/.source),s("svg",/\bsvg/.source),s("markdown",/\b(?:markdown|md)/.source),s("graphql",/\b(?:gql|graphql(?:\s*\.\s*experimental)?)/.source),s("sql",/\bsql/.source),t].filter(Boolean);var d={javascript:!0,js:!0,typescript:!0,ts:!0,jsx:!0,tsx:!0};function f(e){return"string"==typeof e?e:Array.isArray(e)?e.map(f).join(""):f(e.content)}e.hooks.add("after-tokenize",(function(t){t.language in d&&function t(n){for(var a=0,r=n.length;a<r;a++){var o=n[a];if("string"!=typeof o){var s=o.content;if(Array.isArray(s))if("template-string"===o.type){var i=s[1];if(3===s.length&&"string"!=typeof i&&"embedded-code"===i.type){var l=f(i),c=i.alias,d=Array.isArray(c)?c[0]:c,p=e.languages[d];if(!p)continue;s[1]=u(l,p,d)}}else t(s);else"string"!=typeof s&&t([s])}}}(t.tokens)}))}(r),function(e){e.languages.typescript=e.languages.extend("javascript",{"class-name":{pattern:/(\b(?:class|extends|implements|instanceof|interface|new|type)\s+)(?!keyof\b)(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?:\s*<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>)?/,lookbehind:!0,greedy:!0,inside:null},builtin:/\b(?:Array|Function|Promise|any|boolean|console|never|number|string|symbol|unknown)\b/}),e.languages.typescript.keyword.push(/\b(?:abstract|declare|is|keyof|readonly|require)\b/,/\b(?:asserts|infer|interface|module|namespace|type)\b(?=\s*(?:[{_$a-zA-Z\xA0-\uFFFF]|$))/,/\btype\b(?=\s*(?:[\{*]|$))/),delete e.languages.typescript.parameter,delete e.languages.typescript["literal-property"];var t=e.languages.extend("typescript",{});delete t["class-name"],e.languages.typescript["class-name"].inside=t,e.languages.insertBefore("typescript","function",{decorator:{pattern:/@[$\w\xA0-\uFFFF]+/,inside:{at:{pattern:/^@/,alias:"operator"},function:/^[\s\S]+/}},"generic-function":{pattern:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s*<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>(?=\s*\()/,greedy:!0,inside:{function:/^#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*/,generic:{pattern:/<[\s\S]+/,alias:"class-name",inside:t}}}}),e.languages.ts=e.languages.typescript}(r),function(e){function t(e,t){return RegExp(e.replace(/<ID>/g,(function(){return/(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*/.source})),t)}e.languages.insertBefore("javascript","function-variable",{"method-variable":{pattern:RegExp("(\\.\\s*)"+e.languages.javascript["function-variable"].pattern.source),lookbehind:!0,alias:["function-variable","method","function","property-access"]}}),e.languages.insertBefore("javascript","function",{method:{pattern:RegExp("(\\.\\s*)"+e.languages.javascript.function.source),lookbehind:!0,alias:["function","property-access"]}}),e.languages.insertBefore("javascript","constant",{"known-class-name":[{pattern:/\b(?:(?:Float(?:32|64)|(?:Int|Uint)(?:8|16|32)|Uint8Clamped)?Array|ArrayBuffer|BigInt|Boolean|DataView|Date|Error|Function|Intl|JSON|(?:Weak)?(?:Map|Set)|Math|Number|Object|Promise|Proxy|Reflect|RegExp|String|Symbol|WebAssembly)\b/,alias:"class-name"},{pattern:/\b(?:[A-Z]\w*)Error\b/,alias:"class-name"}]}),e.languages.insertBefore("javascript","keyword",{imports:{pattern:t(/(\bimport\b\s*)(?:<ID>(?:\s*,\s*(?:\*\s*as\s+<ID>|\{[^{}]*\}))?|\*\s*as\s+<ID>|\{[^{}]*\})(?=\s*\bfrom\b)/.source),lookbehind:!0,inside:e.languages.javascript},exports:{pattern:t(/(\bexport\b\s*)(?:\*(?:\s*as\s+<ID>)?(?=\s*\bfrom\b)|\{[^{}]*\})/.source),lookbehind:!0,inside:e.languages.javascript}}),e.languages.javascript.keyword.unshift({pattern:/\b(?:as|default|export|from|import)\b/,alias:"module"},{pattern:/\b(?:await|break|catch|continue|do|else|finally|for|if|return|switch|throw|try|while|yield)\b/,alias:"control-flow"},{pattern:/\bnull\b/,alias:["null","nil"]},{pattern:/\bundefined\b/,alias:"nil"}),e.languages.insertBefore("javascript","operator",{spread:{pattern:/\.{3}/,alias:"operator"},arrow:{pattern:/=>/,alias:"operator"}}),e.languages.insertBefore("javascript","punctuation",{"property-access":{pattern:t(/(\.\s*)#?<ID>/.source),lookbehind:!0},"maybe-class-name":{pattern:/(^|[^$\w\xA0-\uFFFF])[A-Z][$\w\xA0-\uFFFF]+/,lookbehind:!0},dom:{pattern:/\b(?:document|(?:local|session)Storage|location|navigator|performance|window)\b/,alias:"variable"},console:{pattern:/\bconsole(?=\s*\.)/,alias:"class-name"}});for(var n=["function","function-variable","method","method-variable","property-access"],a=0;a<n.length;a++){var r=n[a],o=e.languages.javascript[r];"RegExp"===e.util.type(o)&&(o=e.languages.javascript[r]={pattern:o});var s=o.inside||{};o.inside=s,s["maybe-class-name"]=/^[A-Z][\s\S]*/}}(r),function(e){var t=e.util.clone(e.languages.javascript),n=/(?:\s|\/\/.*(?!.)|\/\*(?:[^*]|\*(?!\/))\*\/)/.source,a=/(?:\{(?:\{(?:\{[^{}]*\}|[^{}])*\}|[^{}])*\})/.source,r=/(?:\{<S>*\.{3}(?:[^{}]|<BRACES>)*\})/.source;function o(e,t){return e=e.replace(/<S>/g,(function(){return n})).replace(/<BRACES>/g,(function(){return a})).replace(/<SPREAD>/g,(function(){return r})),RegExp(e,t)}r=o(r).source,e.languages.jsx=e.languages.extend("markup",t),e.languages.jsx.tag.pattern=o(/<\/?(?:[\w.:-]+(?:<S>+(?:[\w.:$-]+(?:=(?:"(?:\\[\s\S]|[^\\"])*"|'(?:\\[\s\S]|[^\\'])*'|[^\s{'"/>=]+|<BRACES>))?|<SPREAD>))*<S>*\/?)?>/.source),e.languages.jsx.tag.inside.tag.pattern=/^<\/?[^\s>\/]*/,e.languages.jsx.tag.inside["attr-value"].pattern=/=(?!\{)(?:"(?:\\[\s\S]|[^\\"])*"|'(?:\\[\s\S]|[^\\'])*'|[^\s'">]+)/,e.languages.jsx.tag.inside.tag.inside["class-name"]=/^[A-Z]\w*(?:\.[A-Z]\w*)*$/,e.languages.jsx.tag.inside.comment=t.comment,e.languages.insertBefore("inside","attr-name",{spread:{pattern:o(/<SPREAD>/.source),inside:e.languages.jsx}},e.languages.jsx.tag),e.languages.insertBefore("inside","special-attr",{script:{pattern:o(/=<BRACES>/.source),alias:"language-javascript",inside:{"script-punctuation":{pattern:/^=(?=\{)/,alias:"punctuation"},rest:e.languages.jsx}}},e.languages.jsx.tag);var s=function(e){return e?"string"==typeof e?e:"string"==typeof e.content?e.content:e.content.map(s).join(""):""},i=function(t){for(var n=[],a=0;a<t.length;a++){var r=t[a],o=!1;if("string"!=typeof r&&("tag"===r.type&&r.content[0]&&"tag"===r.content[0].type?"</"===r.content[0].content[0].content?n.length>0&&n[n.length-1].tagName===s(r.content[0].content[1])&&n.pop():"/>"===r.content[r.content.length-1].content||n.push({tagName:s(r.content[0].content[1]),openedBraces:0}):n.length>0&&"punctuation"===r.type&&"{"===r.content?n[n.length-1].openedBraces++:n.length>0&&n[n.length-1].openedBraces>0&&"punctuation"===r.type&&"}"===r.content?n[n.length-1].openedBraces--:o=!0),(o||"string"==typeof r)&&n.length>0&&0===n[n.length-1].openedBraces){var l=s(r);a<t.length-1&&("string"==typeof t[a+1]||"plain-text"===t[a+1].type)&&(l+=s(t[a+1]),t.splice(a+1,1)),a>0&&("string"==typeof t[a-1]||"plain-text"===t[a-1].type)&&(l=s(t[a-1])+l,t.splice(a-1,1),a--),t[a]=new e.Token("plain-text",l,null,l)}r.content&&"string"!=typeof r.content&&i(r.content)}};e.hooks.add("after-tokenize",(function(e){"jsx"!==e.language&&"tsx"!==e.language||i(e.tokens)}))}(r),function(e){e.languages.diff={coord:[/^(?:\*{3}|-{3}|\+{3}).*$/m,/^@@.*@@$/m,/^\d.*$/m]};var t={"deleted-sign":"-","deleted-arrow":"<","inserted-sign":"+","inserted-arrow":">",unchanged:" ",diff:"!"};Object.keys(t).forEach((function(n){var a=t[n],r=[];/^\w+$/.test(n)||r.push(/\w+/.exec(n)[0]),"diff"===n&&r.push("bold"),e.languages.diff[n]={pattern:RegExp("^(?:["+a+"].*(?:\r\n?|\n|(?![\\s\\S])))+","m"),alias:r,inside:{line:{pattern:/(.)(?=[\s\S]).*(?:\r\n?|\n)?/,lookbehind:!0},prefix:{pattern:/[\s\S]/,alias:/\w+/.exec(n)[0]}}}})),Object.defineProperty(e.languages.diff,"PREFIXES",{value:t})}(r),r.languages.git={comment:/^#.*/m,deleted:/^[-\u2013].*/m,inserted:/^\+.*/m,string:/("|')(?:\\.|(?!\1)[^\\\r\n])*\1/,command:{pattern:/^.*\$ git .*$/m,inside:{parameter:/\s--?\w+/}},coord:/^@@.*@@$/m,"commit-sha1":/^commit \w{40}$/m},r.languages.go=r.languages.extend("clike",{string:{pattern:/(^|[^\\])"(?:\\.|[^"\\\r\n])*"|`[^`]*`/,lookbehind:!0,greedy:!0},keyword:/\b(?:break|case|chan|const|continue|default|defer|else|fallthrough|for|func|go(?:to)?|if|import|interface|map|package|range|return|select|struct|switch|type|var)\b/,boolean:/\b(?:_|false|iota|nil|true)\b/,number:[/\b0(?:b[01_]+|o[0-7_]+)i?\b/i,/\b0x(?:[a-f\d_]+(?:\.[a-f\d_]*)?|\.[a-f\d_]+)(?:p[+-]?\d+(?:_\d+)*)?i?(?!\w)/i,/(?:\b\d[\d_]*(?:\.[\d_]*)?|\B\.\d[\d_]*)(?:e[+-]?[\d_]+)?i?(?!\w)/i],operator:/[*\/%^!=]=?|\+[=+]?|-[=-]?|\|[=|]?|&(?:=|&|\^=?)?|>(?:>=?|=)?|<(?:<=?|=|-)?|:=|\.\.\./,builtin:/\b(?:append|bool|byte|cap|close|complex|complex(?:64|128)|copy|delete|error|float(?:32|64)|u?int(?:8|16|32|64)?|imag|len|make|new|panic|print(?:ln)?|real|recover|rune|string|uintptr)\b/}),r.languages.insertBefore("go","string",{char:{pattern:/'(?:\\.|[^'\\\r\n]){0,10}'/,greedy:!0}}),delete r.languages.go["class-name"],function(e){function t(e,t){return"___"+e.toUpperCase()+t+"___"}Object.defineProperties(e.languages["markup-templating"]={},{buildPlaceholders:{value:function(n,a,r,o){if(n.language===a){var s=n.tokenStack=[];n.code=n.code.replace(r,(function(e){if("function"==typeof o&&!o(e))return e;for(var r,i=s.length;-1!==n.code.indexOf(r=t(a,i));)++i;return s[i]=e,r})),n.grammar=e.languages.markup}}},tokenizePlaceholders:{value:function(n,a){if(n.language===a&&n.tokenStack){n.grammar=e.languages[a];var r=0,o=Object.keys(n.tokenStack);!function s(i){for(var l=0;l<i.length&&!(r>=o.length);l++){var c=i[l];if("string"==typeof c||c.content&&"string"==typeof c.content){var u=o[r],d=n.tokenStack[u],f="string"==typeof c?c:c.content,p=t(a,u),m=f.indexOf(p);if(m>-1){++r;var g=f.substring(0,m),h=new e.Token(a,e.tokenize(d,n.grammar),"language-"+a,d),b=f.substring(m+p.length),v=[];g&&v.push.apply(v,s([g])),v.push(h),b&&v.push.apply(v,s([b])),"string"==typeof c?i.splice.apply(i,[l,1].concat(v)):c.content=v}}else c.content&&s(c.content)}return i}(n.tokens)}}}})}(r),function(e){e.languages.handlebars={comment:/\{\{![\s\S]*?\}\}/,delimiter:{pattern:/^\{\{\{?|\}\}\}?$/,alias:"punctuation"},string:/(["'])(?:\\.|(?!\1)[^\\\r\n])*\1/,number:/\b0x[\dA-Fa-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:[Ee][+-]?\d+)?/,boolean:/\b(?:false|true)\b/,block:{pattern:/^(\s*(?:~\s*)?)[#\/]\S+?(?=\s*(?:~\s*)?$|\s)/,lookbehind:!0,alias:"keyword"},brackets:{pattern:/\[[^\]]+\]/,inside:{punctuation:/\[|\]/,variable:/[\s\S]+/}},punctuation:/[!"#%&':()*+,.\/;<=>@\[\\\]^`{|}~]/,variable:/[^!"#%&'()*+,\/;<=>@\[\\\]^`{|}~\s]+/},e.hooks.add("before-tokenize",(function(t){e.languages["markup-templating"].buildPlaceholders(t,"handlebars",/\{\{\{[\s\S]+?\}\}\}|\{\{[\s\S]+?\}\}/g)})),e.hooks.add("after-tokenize",(function(t){e.languages["markup-templating"].tokenizePlaceholders(t,"handlebars")})),e.languages.hbs=e.languages.handlebars}(r),r.languages.json={property:{pattern:/(^|[^\\])"(?:\\.|[^\\"\r\n])*"(?=\s*:)/,lookbehind:!0,greedy:!0},string:{pattern:/(^|[^\\])"(?:\\.|[^\\"\r\n])*"(?!\s*:)/,lookbehind:!0,greedy:!0},comment:{pattern:/\/\/.*|\/\*[\s\S]*?(?:\*\/|$)/,greedy:!0},number:/-?\b\d+(?:\.\d+)?(?:e[+-]?\d+)?\b/i,punctuation:/[{}[\],]/,operator:/:/,boolean:/\b(?:false|true)\b/,null:{pattern:/\bnull\b/,alias:"keyword"}},r.languages.webmanifest=r.languages.json,r.languages.less=r.languages.extend("css",{comment:[/\/\*[\s\S]*?\*\//,{pattern:/(^|[^\\])\/\/.*/,lookbehind:!0}],atrule:{pattern:/@[\w-](?:\((?:[^(){}]|\([^(){}]*\))*\)|[^(){};\s]|\s+(?!\s))*?(?=\s*\{)/,inside:{punctuation:/[:()]/}},selector:{pattern:/(?:@\{[\w-]+\}|[^{};\s@])(?:@\{[\w-]+\}|\((?:[^(){}]|\([^(){}]*\))*\)|[^(){};@\s]|\s+(?!\s))*?(?=\s*\{)/,inside:{variable:/@+[\w-]+/}},property:/(?:@\{[\w-]+\}|[\w-])+(?:\+_?)?(?=\s*:)/,operator:/[+\-*\/]/}),r.languages.insertBefore("less","property",{variable:[{pattern:/@[\w-]+\s*:/,inside:{punctuation:/:/}},/@@?[\w-]+/],"mixin-usage":{pattern:/([{;]\s*)[.#](?!\d)[\w-].*?(?=[(;])/,lookbehind:!0,alias:"function"}}),r.languages.makefile={comment:{pattern:/(^|[^\\])#(?:\\(?:\r\n|[\s\S])|[^\\\r\n])*/,lookbehind:!0},string:{pattern:/(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},"builtin-target":{pattern:/\.[A-Z][^:#=\s]+(?=\s*:(?!=))/,alias:"builtin"},target:{pattern:/^(?:[^:=\s]|[ \t]+(?![\s:]))+(?=\s*:(?!=))/m,alias:"symbol",inside:{variable:/\$+(?:(?!\$)[^(){}:#=\s]+|(?=[({]))/}},variable:/\$+(?:(?!\$)[^(){}:#=\s]+|\([@*%<^+?][DF]\)|(?=[({]))/,keyword:/-include\b|\b(?:define|else|endef|endif|export|ifn?def|ifn?eq|include|override|private|sinclude|undefine|unexport|vpath)\b/,function:{pattern:/(\()(?:abspath|addsuffix|and|basename|call|dir|error|eval|file|filter(?:-out)?|findstring|firstword|flavor|foreach|guile|if|info|join|lastword|load|notdir|or|origin|patsubst|realpath|shell|sort|strip|subst|suffix|value|warning|wildcard|word(?:list|s)?)(?=[ \t])/,lookbehind:!0},operator:/(?:::|[?:+!])?=|[|@]/,punctuation:/[:;(){}]/},r.languages.objectivec=r.languages.extend("c",{string:{pattern:/@?"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"/,greedy:!0},keyword:/\b(?:asm|auto|break|case|char|const|continue|default|do|double|else|enum|extern|float|for|goto|if|in|inline|int|long|register|return|self|short|signed|sizeof|static|struct|super|switch|typedef|typeof|union|unsigned|void|volatile|while)\b|(?:@interface|@end|@implementation|@protocol|@class|@public|@protected|@private|@property|@try|@catch|@finally|@throw|@synthesize|@dynamic|@selector)\b/,operator:/-[->]?|\+\+?|!=?|<<?=?|>>?=?|==?|&&?|\|\|?|[~^%?*\/@]/}),delete r.languages.objectivec["class-name"],r.languages.objc=r.languages.objectivec,r.languages.ocaml={comment:{pattern:/\(\*[\s\S]*?\*\)/,greedy:!0},char:{pattern:/'(?:[^\\\r\n']|\\(?:.|[ox]?[0-9a-f]{1,3}))'/i,greedy:!0},string:[{pattern:/"(?:\\(?:[\s\S]|\r\n)|[^\\\r\n"])*"/,greedy:!0},{pattern:/\{([a-z_]*)\|[\s\S]*?\|\1\}/,greedy:!0}],number:[/\b(?:0b[01][01_]*|0o[0-7][0-7_]*)\b/i,/\b0x[a-f0-9][a-f0-9_]*(?:\.[a-f0-9_]*)?(?:p[+-]?\d[\d_]*)?(?!\w)/i,/\b\d[\d_]*(?:\.[\d_]*)?(?:e[+-]?\d[\d_]*)?(?!\w)/i],directive:{pattern:/\B#\w+/,alias:"property"},label:{pattern:/\B~\w+/,alias:"property"},"type-variable":{pattern:/\B'\w+/,alias:"function"},variant:{pattern:/`\w+/,alias:"symbol"},keyword:/\b(?:as|assert|begin|class|constraint|do|done|downto|else|end|exception|external|for|fun|function|functor|if|in|include|inherit|initializer|lazy|let|match|method|module|mutable|new|nonrec|object|of|open|private|rec|sig|struct|then|to|try|type|val|value|virtual|when|where|while|with)\b/,boolean:/\b(?:false|true)\b/,"operator-like-punctuation":{pattern:/\[[<>|]|[>|]\]|\{<|>\}/,alias:"punctuation"},operator:/\.[.~]|:[=>]|[=<>@^|&+\-*\/$%!?~][!$%&*+\-.\/:<=>?@^|~]*|\b(?:and|asr|land|lor|lsl|lsr|lxor|mod|or)\b/,punctuation:/;;|::|[(){}\[\].,:;#]|\b_\b/},r.languages.python={comment:{pattern:/(^|[^\\])#.*/,lookbehind:!0,greedy:!0},"string-interpolation":{pattern:/(?:f|fr|rf)(?:("""|''')[\s\S]*?\1|("|')(?:\\.|(?!\2)[^\\\r\n])*\2)/i,greedy:!0,inside:{interpolation:{pattern:/((?:^|[^{])(?:\{\{)*)\{(?!\{)(?:[^{}]|\{(?!\{)(?:[^{}]|\{(?!\{)(?:[^{}])+\})+\})+\}/,lookbehind:!0,inside:{"format-spec":{pattern:/(:)[^:(){}]+(?=\}$)/,lookbehind:!0},"conversion-option":{pattern:/![sra](?=[:}]$)/,alias:"punctuation"},rest:null}},string:/[\s\S]+/}},"triple-quoted-string":{pattern:/(?:[rub]|br|rb)?("""|''')[\s\S]*?\1/i,greedy:!0,alias:"string"},string:{pattern:/(?:[rub]|br|rb)?("|')(?:\\.|(?!\1)[^\\\r\n])*\1/i,greedy:!0},function:{pattern:/((?:^|\s)def[ \t]+)[a-zA-Z_]\w*(?=\s*\()/g,lookbehind:!0},"class-name":{pattern:/(\bclass\s+)\w+/i,lookbehind:!0},decorator:{pattern:/(^[\t ]*)@\w+(?:\.\w+)*/m,lookbehind:!0,alias:["annotation","punctuation"],inside:{punctuation:/\./}},keyword:/\b(?:_(?=\s*:)|and|as|assert|async|await|break|case|class|continue|def|del|elif|else|except|exec|finally|for|from|global|if|import|in|is|lambda|match|nonlocal|not|or|pass|print|raise|return|try|while|with|yield)\b/,builtin:/\b(?:__import__|abs|all|any|apply|ascii|basestring|bin|bool|buffer|bytearray|bytes|callable|chr|classmethod|cmp|coerce|compile|complex|delattr|dict|dir|divmod|enumerate|eval|execfile|file|filter|float|format|frozenset|getattr|globals|hasattr|hash|help|hex|id|input|int|intern|isinstance|issubclass|iter|len|list|locals|long|map|max|memoryview|min|next|object|oct|open|ord|pow|property|range|raw_input|reduce|reload|repr|reversed|round|set|setattr|slice|sorted|staticmethod|str|sum|super|tuple|type|unichr|unicode|vars|xrange|zip)\b/,boolean:/\b(?:False|None|True)\b/,number:/\b0(?:b(?:_?[01])+|o(?:_?[0-7])+|x(?:_?[a-f0-9])+)\b|(?:\b\d+(?:_\d+)*(?:\.(?:\d+(?:_\d+)*)?)?|\B\.\d+(?:_\d+)*)(?:e[+-]?\d+(?:_\d+)*)?j?(?!\w)/i,operator:/[-+%=]=?|!=|:=|\*\*?=?|\/\/?=?|<[<=>]?|>[=>]?|[&|^~]/,punctuation:/[{}[\];(),.:]/},r.languages.python["string-interpolation"].inside.interpolation.inside.rest=r.languages.python,r.languages.py=r.languages.python,r.languages.reason=r.languages.extend("clike",{string:{pattern:/"(?:\\(?:\r\n|[\s\S])|[^\\\r\n"])*"/,greedy:!0},"class-name":/\b[A-Z]\w*/,keyword:/\b(?:and|as|assert|begin|class|constraint|do|done|downto|else|end|exception|external|for|fun|function|functor|if|in|include|inherit|initializer|lazy|let|method|module|mutable|new|nonrec|object|of|open|or|private|rec|sig|struct|switch|then|to|try|type|val|virtual|when|while|with)\b/,operator:/\.{3}|:[:=]|\|>|->|=(?:==?|>)?|<=?|>=?|[|^?'#!~`]|[+\-*\/]\.?|\b(?:asr|land|lor|lsl|lsr|lxor|mod)\b/}),r.languages.insertBefore("reason","class-name",{char:{pattern:/'(?:\\x[\da-f]{2}|\\o[0-3][0-7][0-7]|\\\d{3}|\\.|[^'\\\r\n])'/,greedy:!0},constructor:/\b[A-Z]\w*\b(?!\s*\.)/,label:{pattern:/\b[a-z]\w*(?=::)/,alias:"symbol"}}),delete r.languages.reason.function,function(e){e.languages.sass=e.languages.extend("css",{comment:{pattern:/^([ \t]*)\/[\/*].*(?:(?:\r?\n|\r)\1[ \t].+)*/m,lookbehind:!0,greedy:!0}}),e.languages.insertBefore("sass","atrule",{"atrule-line":{pattern:/^(?:[ \t]*)[@+=].+/m,greedy:!0,inside:{atrule:/(?:@[\w-]+|[+=])/}}}),delete e.languages.sass.atrule;var t=/\$[-\w]+|#\{\$[-\w]+\}/,n=[/[+*\/%]|[=!]=|<=?|>=?|\b(?:and|not|or)\b/,{pattern:/(\s)-(?=\s)/,lookbehind:!0}];e.languages.insertBefore("sass","property",{"variable-line":{pattern:/^[ \t]*\$.+/m,greedy:!0,inside:{punctuation:/:/,variable:t,operator:n}},"property-line":{pattern:/^[ \t]*(?:[^:\s]+ *:.*|:[^:\s].*)/m,greedy:!0,inside:{property:[/[^:\s]+(?=\s*:)/,{pattern:/(:)[^:\s]+/,lookbehind:!0}],punctuation:/:/,variable:t,operator:n,important:e.languages.sass.important}}}),delete e.languages.sass.property,delete e.languages.sass.important,e.languages.insertBefore("sass","punctuation",{selector:{pattern:/^([ \t]*)\S(?:,[^,\r\n]+|[^,\r\n]*)(?:,[^,\r\n]+)*(?:,(?:\r?\n|\r)\1[ \t]+\S(?:,[^,\r\n]+|[^,\r\n]*)(?:,[^,\r\n]+)*)*/m,lookbehind:!0,greedy:!0}})}(r),r.languages.scss=r.languages.extend("css",{comment:{pattern:/(^|[^\\])(?:\/\*[\s\S]*?\*\/|\/\/.*)/,lookbehind:!0},atrule:{pattern:/@[\w-](?:\([^()]+\)|[^()\s]|\s+(?!\s))*?(?=\s+[{;])/,inside:{rule:/@[\w-]+/}},url:/(?:[-a-z]+-)?url(?=\()/i,selector:{pattern:/(?=\S)[^@;{}()]?(?:[^@;{}()\s]|\s+(?!\s)|#\{\$[-\w]+\})+(?=\s*\{(?:\}|\s|[^}][^:{}]*[:{][^}]))/,inside:{parent:{pattern:/&/,alias:"important"},placeholder:/%[-\w]+/,variable:/\$[-\w]+|#\{\$[-\w]+\}/}},property:{pattern:/(?:[-\w]|\$[-\w]|#\{\$[-\w]+\})+(?=\s*:)/,inside:{variable:/\$[-\w]+|#\{\$[-\w]+\}/}}}),r.languages.insertBefore("scss","atrule",{keyword:[/@(?:content|debug|each|else(?: if)?|extend|for|forward|function|if|import|include|mixin|return|use|warn|while)\b/i,{pattern:/( )(?:from|through)(?= )/,lookbehind:!0}]}),r.languages.insertBefore("scss","important",{variable:/\$[-\w]+|#\{\$[-\w]+\}/}),r.languages.insertBefore("scss","function",{"module-modifier":{pattern:/\b(?:as|hide|show|with)\b/i,alias:"keyword"},placeholder:{pattern:/%[-\w]+/,alias:"selector"},statement:{pattern:/\B!(?:default|optional)\b/i,alias:"keyword"},boolean:/\b(?:false|true)\b/,null:{pattern:/\bnull\b/,alias:"keyword"},operator:{pattern:/(\s)(?:[-+*\/%]|[=!]=|<=?|>=?|and|not|or)(?=\s)/,lookbehind:!0}}),r.languages.scss.atrule.inside.rest=r.languages.scss,function(e){var t={pattern:/(\b\d+)(?:%|[a-z]+)/,lookbehind:!0},n={pattern:/(^|[^\w.-])-?(?:\d+(?:\.\d+)?|\.\d+)/,lookbehind:!0},a={comment:{pattern:/(^|[^\\])(?:\/\*[\s\S]*?\*\/|\/\/.*)/,lookbehind:!0},url:{pattern:/\burl\((["']?).*?\1\)/i,greedy:!0},string:{pattern:/("|')(?:(?!\1)[^\\\r\n]|\\(?:\r\n|[\s\S]))*\1/,greedy:!0},interpolation:null,func:null,important:/\B!(?:important|optional)\b/i,keyword:{pattern:/(^|\s+)(?:(?:else|for|if|return|unless)(?=\s|$)|@[\w-]+)/,lookbehind:!0},hexcode:/#[\da-f]{3,6}/i,color:[/\b(?:AliceBlue|AntiqueWhite|Aqua|Aquamarine|Azure|Beige|Bisque|Black|BlanchedAlmond|Blue|BlueViolet|Brown|BurlyWood|CadetBlue|Chartreuse|Chocolate|Coral|CornflowerBlue|Cornsilk|Crimson|Cyan|DarkBlue|DarkCyan|DarkGoldenRod|DarkGr[ae]y|DarkGreen|DarkKhaki|DarkMagenta|DarkOliveGreen|DarkOrange|DarkOrchid|DarkRed|DarkSalmon|DarkSeaGreen|DarkSlateBlue|DarkSlateGr[ae]y|DarkTurquoise|DarkViolet|DeepPink|DeepSkyBlue|DimGr[ae]y|DodgerBlue|FireBrick|FloralWhite|ForestGreen|Fuchsia|Gainsboro|GhostWhite|Gold|GoldenRod|Gr[ae]y|Green|GreenYellow|HoneyDew|HotPink|IndianRed|Indigo|Ivory|Khaki|Lavender|LavenderBlush|LawnGreen|LemonChiffon|LightBlue|LightCoral|LightCyan|LightGoldenRodYellow|LightGr[ae]y|LightGreen|LightPink|LightSalmon|LightSeaGreen|LightSkyBlue|LightSlateGr[ae]y|LightSteelBlue|LightYellow|Lime|LimeGreen|Linen|Magenta|Maroon|MediumAquaMarine|MediumBlue|MediumOrchid|MediumPurple|MediumSeaGreen|MediumSlateBlue|MediumSpringGreen|MediumTurquoise|MediumVioletRed|MidnightBlue|MintCream|MistyRose|Moccasin|NavajoWhite|Navy|OldLace|Olive|OliveDrab|Orange|OrangeRed|Orchid|PaleGoldenRod|PaleGreen|PaleTurquoise|PaleVioletRed|PapayaWhip|PeachPuff|Peru|Pink|Plum|PowderBlue|Purple|Red|RosyBrown|RoyalBlue|SaddleBrown|Salmon|SandyBrown|SeaGreen|SeaShell|Sienna|Silver|SkyBlue|SlateBlue|SlateGr[ae]y|Snow|SpringGreen|SteelBlue|Tan|Teal|Thistle|Tomato|Transparent|Turquoise|Violet|Wheat|White|WhiteSmoke|Yellow|YellowGreen)\b/i,{pattern:/\b(?:hsl|rgb)\(\s*\d{1,3}\s*,\s*\d{1,3}%?\s*,\s*\d{1,3}%?\s*\)\B|\b(?:hsl|rgb)a\(\s*\d{1,3}\s*,\s*\d{1,3}%?\s*,\s*\d{1,3}%?\s*,\s*(?:0|0?\.\d+|1)\s*\)\B/i,inside:{unit:t,number:n,function:/[\w-]+(?=\()/,punctuation:/[(),]/}}],entity:/\\[\da-f]{1,8}/i,unit:t,boolean:/\b(?:false|true)\b/,operator:[/~|[+!\/%<>?=]=?|[-:]=|\*[*=]?|\.{2,3}|&&|\|\||\B-\B|\b(?:and|in|is(?: a| defined| not|nt)?|not|or)\b/],number:n,punctuation:/[{}()\[\];:,]/};a.interpolation={pattern:/\{[^\r\n}:]+\}/,alias:"variable",inside:{delimiter:{pattern:/^\{|\}$/,alias:"punctuation"},rest:a}},a.func={pattern:/[\w-]+\([^)]*\).*/,inside:{function:/^[^(]+/,rest:a}},e.languages.stylus={"atrule-declaration":{pattern:/(^[ \t]*)@.+/m,lookbehind:!0,inside:{atrule:/^@[\w-]+/,rest:a}},"variable-declaration":{pattern:/(^[ \t]*)[\w$-]+\s*.?=[ \t]*(?:\{[^{}]*\}|\S.*|$)/m,lookbehind:!0,inside:{variable:/^\S+/,rest:a}},statement:{pattern:/(^[ \t]*)(?:else|for|if|return|unless)[ \t].+/m,lookbehind:!0,inside:{keyword:/^\S+/,rest:a}},"property-declaration":{pattern:/((?:^|\{)([ \t]*))(?:[\w-]|\{[^}\r\n]+\})+(?:\s*:\s*|[ \t]+)(?!\s)[^{\r\n]*(?:;|[^{\r\n,]$(?!(?:\r?\n|\r)(?:\{|\2[ \t])))/m,lookbehind:!0,inside:{property:{pattern:/^[^\s:]+/,inside:{interpolation:a.interpolation}},rest:a}},selector:{pattern:/(^[ \t]*)(?:(?=\S)(?:[^{}\r\n:()]|::?[\w-]+(?:\([^)\r\n]*\)|(?![\w-]))|\{[^}\r\n]+\})+)(?:(?:\r?\n|\r)(?:\1(?:(?=\S)(?:[^{}\r\n:()]|::?[\w-]+(?:\([^)\r\n]*\)|(?![\w-]))|\{[^}\r\n]+\})+)))*(?:,$|\{|(?=(?:\r?\n|\r)(?:\{|\1[ \t])))/m,lookbehind:!0,inside:{interpolation:a.interpolation,comment:a.comment,punctuation:/[{},]/}},func:a.func,string:a.string,comment:{pattern:/(^|[^\\])(?:\/\*[\s\S]*?\*\/|\/\/.*)/,lookbehind:!0,greedy:!0},interpolation:a.interpolation,punctuation:/[{}()\[\];:.]/}}(r),function(e){var t=e.util.clone(e.languages.typescript);e.languages.tsx=e.languages.extend("jsx",t),delete e.languages.tsx.parameter,delete e.languages.tsx["literal-property"];var n=e.languages.tsx.tag;n.pattern=RegExp(/(^|[^\w$]|(?=<\/))/.source+"(?:"+n.pattern.source+")",n.pattern.flags),n.lookbehind=!0}(r),r.languages.wasm={comment:[/\(;[\s\S]*?;\)/,{pattern:/;;.*/,greedy:!0}],string:{pattern:/"(?:\\[\s\S]|[^"\\])*"/,greedy:!0},keyword:[{pattern:/\b(?:align|offset)=/,inside:{operator:/=/}},{pattern:/\b(?:(?:f32|f64|i32|i64)(?:\.(?:abs|add|and|ceil|clz|const|convert_[su]\/i(?:32|64)|copysign|ctz|demote\/f64|div(?:_[su])?|eqz?|extend_[su]\/i32|floor|ge(?:_[su])?|gt(?:_[su])?|le(?:_[su])?|load(?:(?:8|16|32)_[su])?|lt(?:_[su])?|max|min|mul|neg?|nearest|or|popcnt|promote\/f32|reinterpret\/[fi](?:32|64)|rem_[su]|rot[lr]|shl|shr_[su]|sqrt|store(?:8|16|32)?|sub|trunc(?:_[su]\/f(?:32|64))?|wrap\/i64|xor))?|memory\.(?:grow|size))\b/,inside:{punctuation:/\./}},/\b(?:anyfunc|block|br(?:_if|_table)?|call(?:_indirect)?|data|drop|elem|else|end|export|func|get_(?:global|local)|global|if|import|local|loop|memory|module|mut|nop|offset|param|result|return|select|set_(?:global|local)|start|table|tee_local|then|type|unreachable)\b/],variable:/\$[\w!#$%&'*+\-./:<=>?@\\^`|~]+/,number:/[+-]?\b(?:\d(?:_?\d)*(?:\.\d(?:_?\d)*)?(?:[eE][+-]?\d(?:_?\d)*)?|0x[\da-fA-F](?:_?[\da-fA-F])*(?:\.[\da-fA-F](?:_?[\da-fA-D])*)?(?:[pP][+-]?\d(?:_?\d)*)?)\b|\binf\b|\bnan(?::0x[\da-fA-F](?:_?[\da-fA-D])*)?\b/,punctuation:/[()]/};const o=r},767:()=>{!function(e){for(var t=/\/\*(?:[^*/]|\*(?!\/)|\/(?!\*)|<self>)*\*\//.source,n=0;n<2;n++)t=t.replace(/<self>/g,(function(){return t}));t=t.replace(/<self>/g,(function(){return/[^\s\S]/.source})),e.languages.rust={comment:[{pattern:RegExp(/(^|[^\\])/.source+t),lookbehind:!0,greedy:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0,greedy:!0}],string:{pattern:/b?"(?:\\[\s\S]|[^\\"])*"|b?r(#*)"(?:[^"]|"(?!\1))*"\1/,greedy:!0},char:{pattern:/b?'(?:\\(?:x[0-7][\da-fA-F]|u\{(?:[\da-fA-F]_*){1,6}\}|.)|[^\\\r\n\t'])'/,greedy:!0},attribute:{pattern:/#!?\[(?:[^\[\]"]|"(?:\\[\s\S]|[^\\"])*")*\]/,greedy:!0,alias:"attr-name",inside:{string:null}},"closure-params":{pattern:/([=(,:]\s*|\bmove\s*)\|[^|]*\||\|[^|]*\|(?=\s*(?:\{|->))/,lookbehind:!0,greedy:!0,inside:{"closure-punctuation":{pattern:/^\||\|$/,alias:"punctuation"},rest:null}},"lifetime-annotation":{pattern:/'\w+/,alias:"symbol"},"fragment-specifier":{pattern:/(\$\w+:)[a-z]+/,lookbehind:!0,alias:"punctuation"},variable:/\$\w+/,"function-definition":{pattern:/(\bfn\s+)\w+/,lookbehind:!0,alias:"function"},"type-definition":{pattern:/(\b(?:enum|struct|trait|type|union)\s+)\w+/,lookbehind:!0,alias:"class-name"},"module-declaration":[{pattern:/(\b(?:crate|mod)\s+)[a-z][a-z_\d]*/,lookbehind:!0,alias:"namespace"},{pattern:/(\b(?:crate|self|super)\s*)::\s*[a-z][a-z_\d]*\b(?:\s*::(?:\s*[a-z][a-z_\d]*\s*::)*)?/,lookbehind:!0,alias:"namespace",inside:{punctuation:/::/}}],keyword:[/\b(?:Self|abstract|as|async|await|become|box|break|const|continue|crate|do|dyn|else|enum|extern|final|fn|for|if|impl|in|let|loop|macro|match|mod|move|mut|override|priv|pub|ref|return|self|static|struct|super|trait|try|type|typeof|union|unsafe|unsized|use|virtual|where|while|yield)\b/,/\b(?:bool|char|f(?:32|64)|[ui](?:8|16|32|64|128|size)|str)\b/],function:/\b[a-z_]\w*(?=\s*(?:::\s*<|\())/,macro:{pattern:/\b\w+!/,alias:"property"},constant:/\b[A-Z_][A-Z_\d]+\b/,"class-name":/\b[A-Z]\w*\b/,namespace:{pattern:/(?:\b[a-z][a-z_\d]*\s*::\s*)*\b[a-z][a-z_\d]*\s*::(?!\s*<)/,inside:{punctuation:/::/}},number:/\b(?:0x[\dA-Fa-f](?:_?[\dA-Fa-f])*|0o[0-7](?:_?[0-7])*|0b[01](?:_?[01])*|(?:(?:\d(?:_?\d)*)?\.)?\d(?:_?\d)*(?:[Ee][+-]?\d+)?)(?:_?(?:f32|f64|[iu](?:8|16|32|64|size)?))?\b/,boolean:/\b(?:false|true)\b/,punctuation:/->|\.\.=|\.{1,3}|::|[{}[\];(),:]/,operator:/[-+*\/%!^]=?|=[=>]?|&[&=]?|\|[|=]?|<<?=?|>>?=?|[@?]/},e.languages.rust["closure-params"].inside.rest=e.languages.rust,e.languages.rust.attribute.inside.string=e.languages.rust.string}(Prism)},9930:()=>{!function(e){var t=/(?:[\w-]+|'[^'\n\r]*'|"(?:\\.|[^\\"\r\n])*")/.source;function n(e){return e.replace(/__/g,(function(){return t}))}e.languages.toml={comment:{pattern:/#.*/,greedy:!0},table:{pattern:RegExp(n(/(^[\t ]*\[\s*(?:\[\s*)?)__(?:\s*\.\s*__)*(?=\s*\])/.source),"m"),lookbehind:!0,greedy:!0,alias:"class-name"},key:{pattern:RegExp(n(/(^[\t ]*|[{,]\s*)__(?:\s*\.\s*__)*(?=\s*=)/.source),"m"),lookbehind:!0,greedy:!0,alias:"property"},string:{pattern:/"""(?:\\[\s\S]|[^\\])*?"""|'''[\s\S]*?'''|'[^'\n\r]*'|"(?:\\.|[^\\"\r\n])*"/,greedy:!0},date:[{pattern:/\b\d{4}-\d{2}-\d{2}(?:[T\s]\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})?)?\b/i,alias:"number"},{pattern:/\b\d{2}:\d{2}:\d{2}(?:\.\d+)?\b/,alias:"number"}],number:/(?:\b0(?:x[\da-zA-Z]+(?:_[\da-zA-Z]+)*|o[0-7]+(?:_[0-7]+)*|b[10]+(?:_[10]+)*))\b|[-+]?\b\d+(?:_\d+)*(?:\.\d+(?:_\d+)*)?(?:[eE][+-]?\d+(?:_\d+)*)?\b|[-+]?\b(?:inf|nan)\b/,boolean:/\b(?:false|true)\b/,punctuation:/[.,=[\]{}]/}}(Prism)},6045:(e,t,n)=>{var a={"./prism-rust":767,"./prism-toml":9930};function r(e){var t=o(e);return n(t)}function o(e){if(!n.o(a,e)){var t=new Error("Cannot find module '"+e+"'");throw t.code="MODULE_NOT_FOUND",t}return a[e]}r.keys=function(){return Object.keys(a)},r.resolve=o,e.exports=r,r.id=6045},2703:(e,t,n)=>{"use strict";var a=n(414);function r(){}function o(){}o.resetWarningCache=r,e.exports=function(){function e(e,t,n,r,o,s){if(s!==a){var i=new Error("Calling PropTypes validators directly is not supported by the `prop-types` package. Use PropTypes.checkPropTypes() to call them. Read more at http://fb.me/use-check-prop-types");throw i.name="Invariant Violation",i}}function t(){return e}e.isRequired=e;var n={array:e,bigint:e,bool:e,func:e,number:e,object:e,string:e,symbol:e,any:e,arrayOf:t,element:e,elementType:e,instanceOf:t,node:e,objectOf:t,oneOf:t,oneOfType:t,shape:t,exact:t,checkPropTypes:o,resetWarningCache:r};return n.PropTypes=n,n}},5697:(e,t,n)=>{e.exports=n(2703)()},414:e=>{"use strict";e.exports="SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED"},4448:(e,t,n)=>{"use strict";var a=n(7294),r=n(7418),o=n(3840);function s(e){for(var t="https://reactjs.org/docs/error-decoder.html?invariant="+e,n=1;n<arguments.length;n++)t+="&args[]="+encodeURIComponent(arguments[n]);return"Minified React error #"+e+"; visit "+t+" for the full message or use the non-minified dev environment for full errors and additional helpful warnings."}if(!a)throw Error(s(227));var i=new Set,l={};function c(e,t){u(e,t),u(e+"Capture",t)}function u(e,t){for(l[e]=t,e=0;e<t.length;e++)i.add(t[e])}var d=!("undefined"==typeof window||void 0===window.document||void 0===window.document.createElement),f=/^[:A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD][:A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD\-.0-9\u00B7\u0300-\u036F\u203F-\u2040]*$/,p=Object.prototype.hasOwnProperty,m={},g={};function h(e,t,n,a,r,o,s){this.acceptsBooleans=2===t||3===t||4===t,this.attributeName=a,this.attributeNamespace=r,this.mustUseProperty=n,this.propertyName=e,this.type=t,this.sanitizeURL=o,this.removeEmptyString=s}var b={};"children dangerouslySetInnerHTML defaultValue defaultChecked innerHTML suppressContentEditableWarning suppressHydrationWarning style".split(" ").forEach((function(e){b[e]=new h(e,0,!1,e,null,!1,!1)})),[["acceptCharset","accept-charset"],["className","class"],["htmlFor","for"],["httpEquiv","http-equiv"]].forEach((function(e){var t=e[0];b[t]=new h(t,1,!1,e[1],null,!1,!1)})),["contentEditable","draggable","spellCheck","value"].forEach((function(e){b[e]=new h(e,2,!1,e.toLowerCase(),null,!1,!1)})),["autoReverse","externalResourcesRequired","focusable","preserveAlpha"].forEach((function(e){b[e]=new h(e,2,!1,e,null,!1,!1)})),"allowFullScreen async autoFocus autoPlay controls default defer disabled disablePictureInPicture disableRemotePlayback formNoValidate hidden loop noModule noValidate open playsInline readOnly required reversed scoped seamless itemScope".split(" ").forEach((function(e){b[e]=new h(e,3,!1,e.toLowerCase(),null,!1,!1)})),["checked","multiple","muted","selected"].forEach((function(e){b[e]=new h(e,3,!0,e,null,!1,!1)})),["capture","download"].forEach((function(e){b[e]=new h(e,4,!1,e,null,!1,!1)})),["cols","rows","size","span"].forEach((function(e){b[e]=new h(e,6,!1,e,null,!1,!1)})),["rowSpan","start"].forEach((function(e){b[e]=new h(e,5,!1,e.toLowerCase(),null,!1,!1)}));var v=/[\-:]([a-z])/g;function y(e){return e[1].toUpperCase()}function x(e,t,n,a){var r=b.hasOwnProperty(t)?b[t]:null;(null!==r?0===r.type:!a&&(2<t.length&&("o"===t[0]||"O"===t[0])&&("n"===t[1]||"N"===t[1])))||(function(e,t,n,a){if(null==t||function(e,t,n,a){if(null!==n&&0===n.type)return!1;switch(typeof t){case"function":case"symbol":return!0;case"boolean":return!a&&(null!==n?!n.acceptsBooleans:"data-"!==(e=e.toLowerCase().slice(0,5))&&"aria-"!==e);default:return!1}}(e,t,n,a))return!0;if(a)return!1;if(null!==n)switch(n.type){case 3:return!t;case 4:return!1===t;case 5:return isNaN(t);case 6:return isNaN(t)||1>t}return!1}(t,n,r,a)&&(n=null),a||null===r?function(e){return!!p.call(g,e)||!p.call(m,e)&&(f.test(e)?g[e]=!0:(m[e]=!0,!1))}(t)&&(null===n?e.removeAttribute(t):e.setAttribute(t,""+n)):r.mustUseProperty?e[r.propertyName]=null===n?3!==r.type&&"":n:(t=r.attributeName,a=r.attributeNamespace,null===n?e.removeAttribute(t):(n=3===(r=r.type)||4===r&&!0===n?"":""+n,a?e.setAttributeNS(a,t,n):e.setAttribute(t,n))))}"accent-height alignment-baseline arabic-form baseline-shift cap-height clip-path clip-rule color-interpolation color-interpolation-filters color-profile color-rendering dominant-baseline enable-background fill-opacity fill-rule flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-name glyph-orientation-horizontal glyph-orientation-vertical horiz-adv-x horiz-origin-x image-rendering letter-spacing lighting-color marker-end marker-mid marker-start overline-position overline-thickness paint-order panose-1 pointer-events rendering-intent shape-rendering stop-color stop-opacity strikethrough-position strikethrough-thickness stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width text-anchor text-decoration text-rendering underline-position underline-thickness unicode-bidi unicode-range units-per-em v-alphabetic v-hanging v-ideographic v-mathematical vector-effect vert-adv-y vert-origin-x vert-origin-y word-spacing writing-mode xmlns:xlink x-height".split(" ").forEach((function(e){var t=e.replace(v,y);b[t]=new h(t,1,!1,e,null,!1,!1)})),"xlink:actuate xlink:arcrole xlink:role xlink:show xlink:title xlink:type".split(" ").forEach((function(e){var t=e.replace(v,y);b[t]=new h(t,1,!1,e,"http://www.w3.org/1999/xlink",!1,!1)})),["xml:base","xml:lang","xml:space"].forEach((function(e){var t=e.replace(v,y);b[t]=new h(t,1,!1,e,"http://www.w3.org/XML/1998/namespace",!1,!1)})),["tabIndex","crossOrigin"].forEach((function(e){b[e]=new h(e,1,!1,e.toLowerCase(),null,!1,!1)})),b.xlinkHref=new h("xlinkHref",1,!1,"xlink:href","http://www.w3.org/1999/xlink",!0,!1),["src","href","action","formAction"].forEach((function(e){b[e]=new h(e,1,!1,e.toLowerCase(),null,!0,!0)}));var w=a.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED,S=60103,E=60106,k=60107,_=60108,C=60114,T=60109,q=60110,A=60112,L=60113,N=60120,O=60115,P=60116,I=60121,R=60128,M=60129,D=60130,F=60131;if("function"==typeof Symbol&&Symbol.for){var B=Symbol.for;S=B("react.element"),E=B("react.portal"),k=B("react.fragment"),_=B("react.strict_mode"),C=B("react.profiler"),T=B("react.provider"),q=B("react.context"),A=B("react.forward_ref"),L=B("react.suspense"),N=B("react.suspense_list"),O=B("react.memo"),P=B("react.lazy"),I=B("react.block"),B("react.scope"),R=B("react.opaque.id"),M=B("react.debug_trace_mode"),D=B("react.offscreen"),F=B("react.legacy_hidden")}var j,z="function"==typeof Symbol&&Symbol.iterator;function $(e){return null===e||"object"!=typeof e?null:"function"==typeof(e=z&&e[z]||e["@@iterator"])?e:null}function U(e){if(void 0===j)try{throw Error()}catch(n){var t=n.stack.trim().match(/\n( *(at )?)/);j=t&&t[1]||""}return"\n"+j+e}var Z=!1;function H(e,t){if(!e||Z)return"";Z=!0;var n=Error.prepareStackTrace;Error.prepareStackTrace=void 0;try{if(t)if(t=function(){throw Error()},Object.defineProperty(t.prototype,"props",{set:function(){throw Error()}}),"object"==typeof Reflect&&Reflect.construct){try{Reflect.construct(t,[])}catch(l){var a=l}Reflect.construct(e,[],t)}else{try{t.call()}catch(l){a=l}e.call(t.prototype)}else{try{throw Error()}catch(l){a=l}e()}}catch(l){if(l&&a&&"string"==typeof l.stack){for(var r=l.stack.split("\n"),o=a.stack.split("\n"),s=r.length-1,i=o.length-1;1<=s&&0<=i&&r[s]!==o[i];)i--;for(;1<=s&&0<=i;s--,i--)if(r[s]!==o[i]){if(1!==s||1!==i)do{if(s--,0>--i||r[s]!==o[i])return"\n"+r[s].replace(" at new "," at ")}while(1<=s&&0<=i);break}}}finally{Z=!1,Error.prepareStackTrace=n}return(e=e?e.displayName||e.name:"")?U(e):""}function V(e){switch(e.tag){case 5:return U(e.type);case 16:return U("Lazy");case 13:return U("Suspense");case 19:return U("SuspenseList");case 0:case 2:case 15:return e=H(e.type,!1);case 11:return e=H(e.type.render,!1);case 22:return e=H(e.type._render,!1);case 1:return e=H(e.type,!0);default:return""}}function W(e){if(null==e)return null;if("function"==typeof e)return e.displayName||e.name||null;if("string"==typeof e)return e;switch(e){case k:return"Fragment";case E:return"Portal";case C:return"Profiler";case _:return"StrictMode";case L:return"Suspense";case N:return"SuspenseList"}if("object"==typeof e)switch(e.$$typeof){case q:return(e.displayName||"Context")+".Consumer";case T:return(e._context.displayName||"Context")+".Provider";case A:var t=e.render;return t=t.displayName||t.name||"",e.displayName||(""!==t?"ForwardRef("+t+")":"ForwardRef");case O:return W(e.type);case I:return W(e._render);case P:t=e._payload,e=e._init;try{return W(e(t))}catch(n){}}return null}function G(e){switch(typeof e){case"boolean":case"number":case"object":case"string":case"undefined":return e;default:return""}}function Y(e){var t=e.type;return(e=e.nodeName)&&"input"===e.toLowerCase()&&("checkbox"===t||"radio"===t)}function K(e){e._valueTracker||(e._valueTracker=function(e){var t=Y(e)?"checked":"value",n=Object.getOwnPropertyDescriptor(e.constructor.prototype,t),a=""+e[t];if(!e.hasOwnProperty(t)&&void 0!==n&&"function"==typeof n.get&&"function"==typeof n.set){var r=n.get,o=n.set;return Object.defineProperty(e,t,{configurable:!0,get:function(){return r.call(this)},set:function(e){a=""+e,o.call(this,e)}}),Object.defineProperty(e,t,{enumerable:n.enumerable}),{getValue:function(){return a},setValue:function(e){a=""+e},stopTracking:function(){e._valueTracker=null,delete e[t]}}}}(e))}function Q(e){if(!e)return!1;var t=e._valueTracker;if(!t)return!0;var n=t.getValue(),a="";return e&&(a=Y(e)?e.checked?"true":"false":e.value),(e=a)!==n&&(t.setValue(e),!0)}function X(e){if(void 0===(e=e||("undefined"!=typeof document?document:void 0)))return null;try{return e.activeElement||e.body}catch(t){return e.body}}function J(e,t){var n=t.checked;return r({},t,{defaultChecked:void 0,defaultValue:void 0,value:void 0,checked:null!=n?n:e._wrapperState.initialChecked})}function ee(e,t){var n=null==t.defaultValue?"":t.defaultValue,a=null!=t.checked?t.checked:t.defaultChecked;n=G(null!=t.value?t.value:n),e._wrapperState={initialChecked:a,initialValue:n,controlled:"checkbox"===t.type||"radio"===t.type?null!=t.checked:null!=t.value}}function te(e,t){null!=(t=t.checked)&&x(e,"checked",t,!1)}function ne(e,t){te(e,t);var n=G(t.value),a=t.type;if(null!=n)"number"===a?(0===n&&""===e.value||e.value!=n)&&(e.value=""+n):e.value!==""+n&&(e.value=""+n);else if("submit"===a||"reset"===a)return void e.removeAttribute("value");t.hasOwnProperty("value")?re(e,t.type,n):t.hasOwnProperty("defaultValue")&&re(e,t.type,G(t.defaultValue)),null==t.checked&&null!=t.defaultChecked&&(e.defaultChecked=!!t.defaultChecked)}function ae(e,t,n){if(t.hasOwnProperty("value")||t.hasOwnProperty("defaultValue")){var a=t.type;if(!("submit"!==a&&"reset"!==a||void 0!==t.value&&null!==t.value))return;t=""+e._wrapperState.initialValue,n||t===e.value||(e.value=t),e.defaultValue=t}""!==(n=e.name)&&(e.name=""),e.defaultChecked=!!e._wrapperState.initialChecked,""!==n&&(e.name=n)}function re(e,t,n){"number"===t&&X(e.ownerDocument)===e||(null==n?e.defaultValue=""+e._wrapperState.initialValue:e.defaultValue!==""+n&&(e.defaultValue=""+n))}function oe(e,t){return e=r({children:void 0},t),(t=function(e){var t="";return a.Children.forEach(e,(function(e){null!=e&&(t+=e)})),t}(t.children))&&(e.children=t),e}function se(e,t,n,a){if(e=e.options,t){t={};for(var r=0;r<n.length;r++)t["$"+n[r]]=!0;for(n=0;n<e.length;n++)r=t.hasOwnProperty("$"+e[n].value),e[n].selected!==r&&(e[n].selected=r),r&&a&&(e[n].defaultSelected=!0)}else{for(n=""+G(n),t=null,r=0;r<e.length;r++){if(e[r].value===n)return e[r].selected=!0,void(a&&(e[r].defaultSelected=!0));null!==t||e[r].disabled||(t=e[r])}null!==t&&(t.selected=!0)}}function ie(e,t){if(null!=t.dangerouslySetInnerHTML)throw Error(s(91));return r({},t,{value:void 0,defaultValue:void 0,children:""+e._wrapperState.initialValue})}function le(e,t){var n=t.value;if(null==n){if(n=t.children,t=t.defaultValue,null!=n){if(null!=t)throw Error(s(92));if(Array.isArray(n)){if(!(1>=n.length))throw Error(s(93));n=n[0]}t=n}null==t&&(t=""),n=t}e._wrapperState={initialValue:G(n)}}function ce(e,t){var n=G(t.value),a=G(t.defaultValue);null!=n&&((n=""+n)!==e.value&&(e.value=n),null==t.defaultValue&&e.defaultValue!==n&&(e.defaultValue=n)),null!=a&&(e.defaultValue=""+a)}function ue(e){var t=e.textContent;t===e._wrapperState.initialValue&&""!==t&&null!==t&&(e.value=t)}var de={html:"http://www.w3.org/1999/xhtml",mathml:"http://www.w3.org/1998/Math/MathML",svg:"http://www.w3.org/2000/svg"};function fe(e){switch(e){case"svg":return"http://www.w3.org/2000/svg";case"math":return"http://www.w3.org/1998/Math/MathML";default:return"http://www.w3.org/1999/xhtml"}}function pe(e,t){return null==e||"http://www.w3.org/1999/xhtml"===e?fe(t):"http://www.w3.org/2000/svg"===e&&"foreignObject"===t?"http://www.w3.org/1999/xhtml":e}var me,ge,he=(ge=function(e,t){if(e.namespaceURI!==de.svg||"innerHTML"in e)e.innerHTML=t;else{for((me=me||document.createElement("div")).innerHTML="<svg>"+t.valueOf().toString()+"</svg>",t=me.firstChild;e.firstChild;)e.removeChild(e.firstChild);for(;t.firstChild;)e.appendChild(t.firstChild)}},"undefined"!=typeof MSApp&&MSApp.execUnsafeLocalFunction?function(e,t,n,a){MSApp.execUnsafeLocalFunction((function(){return ge(e,t)}))}:ge);function be(e,t){if(t){var n=e.firstChild;if(n&&n===e.lastChild&&3===n.nodeType)return void(n.nodeValue=t)}e.textContent=t}var ve={animationIterationCount:!0,borderImageOutset:!0,borderImageSlice:!0,borderImageWidth:!0,boxFlex:!0,boxFlexGroup:!0,boxOrdinalGroup:!0,columnCount:!0,columns:!0,flex:!0,flexGrow:!0,flexPositive:!0,flexShrink:!0,flexNegative:!0,flexOrder:!0,gridArea:!0,gridRow:!0,gridRowEnd:!0,gridRowSpan:!0,gridRowStart:!0,gridColumn:!0,gridColumnEnd:!0,gridColumnSpan:!0,gridColumnStart:!0,fontWeight:!0,lineClamp:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,tabSize:!0,widows:!0,zIndex:!0,zoom:!0,fillOpacity:!0,floodOpacity:!0,stopOpacity:!0,strokeDasharray:!0,strokeDashoffset:!0,strokeMiterlimit:!0,strokeOpacity:!0,strokeWidth:!0},ye=["Webkit","ms","Moz","O"];function xe(e,t,n){return null==t||"boolean"==typeof t||""===t?"":n||"number"!=typeof t||0===t||ve.hasOwnProperty(e)&&ve[e]?(""+t).trim():t+"px"}function we(e,t){for(var n in e=e.style,t)if(t.hasOwnProperty(n)){var a=0===n.indexOf("--"),r=xe(n,t[n],a);"float"===n&&(n="cssFloat"),a?e.setProperty(n,r):e[n]=r}}Object.keys(ve).forEach((function(e){ye.forEach((function(t){t=t+e.charAt(0).toUpperCase()+e.substring(1),ve[t]=ve[e]}))}));var Se=r({menuitem:!0},{area:!0,base:!0,br:!0,col:!0,embed:!0,hr:!0,img:!0,input:!0,keygen:!0,link:!0,meta:!0,param:!0,source:!0,track:!0,wbr:!0});function Ee(e,t){if(t){if(Se[e]&&(null!=t.children||null!=t.dangerouslySetInnerHTML))throw Error(s(137,e));if(null!=t.dangerouslySetInnerHTML){if(null!=t.children)throw Error(s(60));if("object"!=typeof t.dangerouslySetInnerHTML||!("__html"in t.dangerouslySetInnerHTML))throw Error(s(61))}if(null!=t.style&&"object"!=typeof t.style)throw Error(s(62))}}function ke(e,t){if(-1===e.indexOf("-"))return"string"==typeof t.is;switch(e){case"annotation-xml":case"color-profile":case"font-face":case"font-face-src":case"font-face-uri":case"font-face-format":case"font-face-name":case"missing-glyph":return!1;default:return!0}}function _e(e){return(e=e.target||e.srcElement||window).correspondingUseElement&&(e=e.correspondingUseElement),3===e.nodeType?e.parentNode:e}var Ce=null,Te=null,qe=null;function Ae(e){if(e=nr(e)){if("function"!=typeof Ce)throw Error(s(280));var t=e.stateNode;t&&(t=rr(t),Ce(e.stateNode,e.type,t))}}function Le(e){Te?qe?qe.push(e):qe=[e]:Te=e}function Ne(){if(Te){var e=Te,t=qe;if(qe=Te=null,Ae(e),t)for(e=0;e<t.length;e++)Ae(t[e])}}function Oe(e,t){return e(t)}function Pe(e,t,n,a,r){return e(t,n,a,r)}function Ie(){}var Re=Oe,Me=!1,De=!1;function Fe(){null===Te&&null===qe||(Ie(),Ne())}function Be(e,t){var n=e.stateNode;if(null===n)return null;var a=rr(n);if(null===a)return null;n=a[t];e:switch(t){case"onClick":case"onClickCapture":case"onDoubleClick":case"onDoubleClickCapture":case"onMouseDown":case"onMouseDownCapture":case"onMouseMove":case"onMouseMoveCapture":case"onMouseUp":case"onMouseUpCapture":case"onMouseEnter":(a=!a.disabled)||(a=!("button"===(e=e.type)||"input"===e||"select"===e||"textarea"===e)),e=!a;break e;default:e=!1}if(e)return null;if(n&&"function"!=typeof n)throw Error(s(231,t,typeof n));return n}var je=!1;if(d)try{var ze={};Object.defineProperty(ze,"passive",{get:function(){je=!0}}),window.addEventListener("test",ze,ze),window.removeEventListener("test",ze,ze)}catch(ge){je=!1}function $e(e,t,n,a,r,o,s,i,l){var c=Array.prototype.slice.call(arguments,3);try{t.apply(n,c)}catch(u){this.onError(u)}}var Ue=!1,Ze=null,He=!1,Ve=null,We={onError:function(e){Ue=!0,Ze=e}};function Ge(e,t,n,a,r,o,s,i,l){Ue=!1,Ze=null,$e.apply(We,arguments)}function Ye(e){var t=e,n=e;if(e.alternate)for(;t.return;)t=t.return;else{e=t;do{0!=(1026&(t=e).flags)&&(n=t.return),e=t.return}while(e)}return 3===t.tag?n:null}function Ke(e){if(13===e.tag){var t=e.memoizedState;if(null===t&&(null!==(e=e.alternate)&&(t=e.memoizedState)),null!==t)return t.dehydrated}return null}function Qe(e){if(Ye(e)!==e)throw Error(s(188))}function Xe(e){if(e=function(e){var t=e.alternate;if(!t){if(null===(t=Ye(e)))throw Error(s(188));return t!==e?null:e}for(var n=e,a=t;;){var r=n.return;if(null===r)break;var o=r.alternate;if(null===o){if(null!==(a=r.return)){n=a;continue}break}if(r.child===o.child){for(o=r.child;o;){if(o===n)return Qe(r),e;if(o===a)return Qe(r),t;o=o.sibling}throw Error(s(188))}if(n.return!==a.return)n=r,a=o;else{for(var i=!1,l=r.child;l;){if(l===n){i=!0,n=r,a=o;break}if(l===a){i=!0,a=r,n=o;break}l=l.sibling}if(!i){for(l=o.child;l;){if(l===n){i=!0,n=o,a=r;break}if(l===a){i=!0,a=o,n=r;break}l=l.sibling}if(!i)throw Error(s(189))}}if(n.alternate!==a)throw Error(s(190))}if(3!==n.tag)throw Error(s(188));return n.stateNode.current===n?e:t}(e),!e)return null;for(var t=e;;){if(5===t.tag||6===t.tag)return t;if(t.child)t.child.return=t,t=t.child;else{if(t===e)break;for(;!t.sibling;){if(!t.return||t.return===e)return null;t=t.return}t.sibling.return=t.return,t=t.sibling}}return null}function Je(e,t){for(var n=e.alternate;null!==t;){if(t===e||t===n)return!0;t=t.return}return!1}var et,tt,nt,at,rt=!1,ot=[],st=null,it=null,lt=null,ct=new Map,ut=new Map,dt=[],ft="mousedown mouseup touchcancel touchend touchstart auxclick dblclick pointercancel pointerdown pointerup dragend dragstart drop compositionend compositionstart keydown keypress keyup input textInput copy cut paste click change contextmenu reset submit".split(" ");function pt(e,t,n,a,r){return{blockedOn:e,domEventName:t,eventSystemFlags:16|n,nativeEvent:r,targetContainers:[a]}}function mt(e,t){switch(e){case"focusin":case"focusout":st=null;break;case"dragenter":case"dragleave":it=null;break;case"mouseover":case"mouseout":lt=null;break;case"pointerover":case"pointerout":ct.delete(t.pointerId);break;case"gotpointercapture":case"lostpointercapture":ut.delete(t.pointerId)}}function gt(e,t,n,a,r,o){return null===e||e.nativeEvent!==o?(e=pt(t,n,a,r,o),null!==t&&(null!==(t=nr(t))&&tt(t)),e):(e.eventSystemFlags|=a,t=e.targetContainers,null!==r&&-1===t.indexOf(r)&&t.push(r),e)}function ht(e){var t=tr(e.target);if(null!==t){var n=Ye(t);if(null!==n)if(13===(t=n.tag)){if(null!==(t=Ke(n)))return e.blockedOn=t,void at(e.lanePriority,(function(){o.unstable_runWithPriority(e.priority,(function(){nt(n)}))}))}else if(3===t&&n.stateNode.hydrate)return void(e.blockedOn=3===n.tag?n.stateNode.containerInfo:null)}e.blockedOn=null}function bt(e){if(null!==e.blockedOn)return!1;for(var t=e.targetContainers;0<t.length;){var n=Xt(e.domEventName,e.eventSystemFlags,t[0],e.nativeEvent);if(null!==n)return null!==(t=nr(n))&&tt(t),e.blockedOn=n,!1;t.shift()}return!0}function vt(e,t,n){bt(e)&&n.delete(t)}function yt(){for(rt=!1;0<ot.length;){var e=ot[0];if(null!==e.blockedOn){null!==(e=nr(e.blockedOn))&&et(e);break}for(var t=e.targetContainers;0<t.length;){var n=Xt(e.domEventName,e.eventSystemFlags,t[0],e.nativeEvent);if(null!==n){e.blockedOn=n;break}t.shift()}null===e.blockedOn&&ot.shift()}null!==st&&bt(st)&&(st=null),null!==it&&bt(it)&&(it=null),null!==lt&&bt(lt)&&(lt=null),ct.forEach(vt),ut.forEach(vt)}function xt(e,t){e.blockedOn===t&&(e.blockedOn=null,rt||(rt=!0,o.unstable_scheduleCallback(o.unstable_NormalPriority,yt)))}function wt(e){function t(t){return xt(t,e)}if(0<ot.length){xt(ot[0],e);for(var n=1;n<ot.length;n++){var a=ot[n];a.blockedOn===e&&(a.blockedOn=null)}}for(null!==st&&xt(st,e),null!==it&&xt(it,e),null!==lt&&xt(lt,e),ct.forEach(t),ut.forEach(t),n=0;n<dt.length;n++)(a=dt[n]).blockedOn===e&&(a.blockedOn=null);for(;0<dt.length&&null===(n=dt[0]).blockedOn;)ht(n),null===n.blockedOn&&dt.shift()}function St(e,t){var n={};return n[e.toLowerCase()]=t.toLowerCase(),n["Webkit"+e]="webkit"+t,n["Moz"+e]="moz"+t,n}var Et={animationend:St("Animation","AnimationEnd"),animationiteration:St("Animation","AnimationIteration"),animationstart:St("Animation","AnimationStart"),transitionend:St("Transition","TransitionEnd")},kt={},_t={};function Ct(e){if(kt[e])return kt[e];if(!Et[e])return e;var t,n=Et[e];for(t in n)if(n.hasOwnProperty(t)&&t in _t)return kt[e]=n[t];return e}d&&(_t=document.createElement("div").style,"AnimationEvent"in window||(delete Et.animationend.animation,delete Et.animationiteration.animation,delete Et.animationstart.animation),"TransitionEvent"in window||delete Et.transitionend.transition);var Tt=Ct("animationend"),qt=Ct("animationiteration"),At=Ct("animationstart"),Lt=Ct("transitionend"),Nt=new Map,Ot=new Map,Pt=["abort","abort",Tt,"animationEnd",qt,"animationIteration",At,"animationStart","canplay","canPlay","canplaythrough","canPlayThrough","durationchange","durationChange","emptied","emptied","encrypted","encrypted","ended","ended","error","error","gotpointercapture","gotPointerCapture","load","load","loadeddata","loadedData","loadedmetadata","loadedMetadata","loadstart","loadStart","lostpointercapture","lostPointerCapture","playing","playing","progress","progress","seeking","seeking","stalled","stalled","suspend","suspend","timeupdate","timeUpdate",Lt,"transitionEnd","waiting","waiting"];function It(e,t){for(var n=0;n<e.length;n+=2){var a=e[n],r=e[n+1];r="on"+(r[0].toUpperCase()+r.slice(1)),Ot.set(a,t),Nt.set(a,r),c(r,[a])}}(0,o.unstable_now)();var Rt=8;function Mt(e){if(0!=(1&e))return Rt=15,1;if(0!=(2&e))return Rt=14,2;if(0!=(4&e))return Rt=13,4;var t=24&e;return 0!==t?(Rt=12,t):0!=(32&e)?(Rt=11,32):0!==(t=192&e)?(Rt=10,t):0!=(256&e)?(Rt=9,256):0!==(t=3584&e)?(Rt=8,t):0!=(4096&e)?(Rt=7,4096):0!==(t=4186112&e)?(Rt=6,t):0!==(t=62914560&e)?(Rt=5,t):67108864&e?(Rt=4,67108864):0!=(134217728&e)?(Rt=3,134217728):0!==(t=805306368&e)?(Rt=2,t):0!=(1073741824&e)?(Rt=1,1073741824):(Rt=8,e)}function Dt(e,t){var n=e.pendingLanes;if(0===n)return Rt=0;var a=0,r=0,o=e.expiredLanes,s=e.suspendedLanes,i=e.pingedLanes;if(0!==o)a=o,r=Rt=15;else if(0!==(o=134217727&n)){var l=o&~s;0!==l?(a=Mt(l),r=Rt):0!==(i&=o)&&(a=Mt(i),r=Rt)}else 0!==(o=n&~s)?(a=Mt(o),r=Rt):0!==i&&(a=Mt(i),r=Rt);if(0===a)return 0;if(a=n&((0>(a=31-Ut(a))?0:1<<a)<<1)-1,0!==t&&t!==a&&0==(t&s)){if(Mt(t),r<=Rt)return t;Rt=r}if(0!==(t=e.entangledLanes))for(e=e.entanglements,t&=a;0<t;)r=1<<(n=31-Ut(t)),a|=e[n],t&=~r;return a}function Ft(e){return 0!==(e=-1073741825&e.pendingLanes)?e:1073741824&e?1073741824:0}function Bt(e,t){switch(e){case 15:return 1;case 14:return 2;case 12:return 0===(e=jt(24&~t))?Bt(10,t):e;case 10:return 0===(e=jt(192&~t))?Bt(8,t):e;case 8:return 0===(e=jt(3584&~t))&&(0===(e=jt(4186112&~t))&&(e=512)),e;case 2:return 0===(t=jt(805306368&~t))&&(t=268435456),t}throw Error(s(358,e))}function jt(e){return e&-e}function zt(e){for(var t=[],n=0;31>n;n++)t.push(e);return t}function $t(e,t,n){e.pendingLanes|=t;var a=t-1;e.suspendedLanes&=a,e.pingedLanes&=a,(e=e.eventTimes)[t=31-Ut(t)]=n}var Ut=Math.clz32?Math.clz32:function(e){return 0===e?32:31-(Zt(e)/Ht|0)|0},Zt=Math.log,Ht=Math.LN2;var Vt=o.unstable_UserBlockingPriority,Wt=o.unstable_runWithPriority,Gt=!0;function Yt(e,t,n,a){Me||Ie();var r=Qt,o=Me;Me=!0;try{Pe(r,e,t,n,a)}finally{(Me=o)||Fe()}}function Kt(e,t,n,a){Wt(Vt,Qt.bind(null,e,t,n,a))}function Qt(e,t,n,a){var r;if(Gt)if((r=0==(4&t))&&0<ot.length&&-1<ft.indexOf(e))e=pt(null,e,t,n,a),ot.push(e);else{var o=Xt(e,t,n,a);if(null===o)r&&mt(e,a);else{if(r){if(-1<ft.indexOf(e))return e=pt(o,e,t,n,a),void ot.push(e);if(function(e,t,n,a,r){switch(t){case"focusin":return st=gt(st,e,t,n,a,r),!0;case"dragenter":return it=gt(it,e,t,n,a,r),!0;case"mouseover":return lt=gt(lt,e,t,n,a,r),!0;case"pointerover":var o=r.pointerId;return ct.set(o,gt(ct.get(o)||null,e,t,n,a,r)),!0;case"gotpointercapture":return o=r.pointerId,ut.set(o,gt(ut.get(o)||null,e,t,n,a,r)),!0}return!1}(o,e,t,n,a))return;mt(e,a)}Ia(e,t,a,null,n)}}}function Xt(e,t,n,a){var r=_e(a);if(null!==(r=tr(r))){var o=Ye(r);if(null===o)r=null;else{var s=o.tag;if(13===s){if(null!==(r=Ke(o)))return r;r=null}else if(3===s){if(o.stateNode.hydrate)return 3===o.tag?o.stateNode.containerInfo:null;r=null}else o!==r&&(r=null)}}return Ia(e,t,a,r,n),null}var Jt=null,en=null,tn=null;function nn(){if(tn)return tn;var e,t,n=en,a=n.length,r="value"in Jt?Jt.value:Jt.textContent,o=r.length;for(e=0;e<a&&n[e]===r[e];e++);var s=a-e;for(t=1;t<=s&&n[a-t]===r[o-t];t++);return tn=r.slice(e,1<t?1-t:void 0)}function an(e){var t=e.keyCode;return"charCode"in e?0===(e=e.charCode)&&13===t&&(e=13):e=t,10===e&&(e=13),32<=e||13===e?e:0}function rn(){return!0}function on(){return!1}function sn(e){function t(t,n,a,r,o){for(var s in this._reactName=t,this._targetInst=a,this.type=n,this.nativeEvent=r,this.target=o,this.currentTarget=null,e)e.hasOwnProperty(s)&&(t=e[s],this[s]=t?t(r):r[s]);return this.isDefaultPrevented=(null!=r.defaultPrevented?r.defaultPrevented:!1===r.returnValue)?rn:on,this.isPropagationStopped=on,this}return r(t.prototype,{preventDefault:function(){this.defaultPrevented=!0;var e=this.nativeEvent;e&&(e.preventDefault?e.preventDefault():"unknown"!=typeof e.returnValue&&(e.returnValue=!1),this.isDefaultPrevented=rn)},stopPropagation:function(){var e=this.nativeEvent;e&&(e.stopPropagation?e.stopPropagation():"unknown"!=typeof e.cancelBubble&&(e.cancelBubble=!0),this.isPropagationStopped=rn)},persist:function(){},isPersistent:rn}),t}var ln,cn,un,dn={eventPhase:0,bubbles:0,cancelable:0,timeStamp:function(e){return e.timeStamp||Date.now()},defaultPrevented:0,isTrusted:0},fn=sn(dn),pn=r({},dn,{view:0,detail:0}),mn=sn(pn),gn=r({},pn,{screenX:0,screenY:0,clientX:0,clientY:0,pageX:0,pageY:0,ctrlKey:0,shiftKey:0,altKey:0,metaKey:0,getModifierState:Tn,button:0,buttons:0,relatedTarget:function(e){return void 0===e.relatedTarget?e.fromElement===e.srcElement?e.toElement:e.fromElement:e.relatedTarget},movementX:function(e){return"movementX"in e?e.movementX:(e!==un&&(un&&"mousemove"===e.type?(ln=e.screenX-un.screenX,cn=e.screenY-un.screenY):cn=ln=0,un=e),ln)},movementY:function(e){return"movementY"in e?e.movementY:cn}}),hn=sn(gn),bn=sn(r({},gn,{dataTransfer:0})),vn=sn(r({},pn,{relatedTarget:0})),yn=sn(r({},dn,{animationName:0,elapsedTime:0,pseudoElement:0})),xn=r({},dn,{clipboardData:function(e){return"clipboardData"in e?e.clipboardData:window.clipboardData}}),wn=sn(xn),Sn=sn(r({},dn,{data:0})),En={Esc:"Escape",Spacebar:" ",Left:"ArrowLeft",Up:"ArrowUp",Right:"ArrowRight",Down:"ArrowDown",Del:"Delete",Win:"OS",Menu:"ContextMenu",Apps:"ContextMenu",Scroll:"ScrollLock",MozPrintableKey:"Unidentified"},kn={8:"Backspace",9:"Tab",12:"Clear",13:"Enter",16:"Shift",17:"Control",18:"Alt",19:"Pause",20:"CapsLock",27:"Escape",32:" ",33:"PageUp",34:"PageDown",35:"End",36:"Home",37:"ArrowLeft",38:"ArrowUp",39:"ArrowRight",40:"ArrowDown",45:"Insert",46:"Delete",112:"F1",113:"F2",114:"F3",115:"F4",116:"F5",117:"F6",118:"F7",119:"F8",120:"F9",121:"F10",122:"F11",123:"F12",144:"NumLock",145:"ScrollLock",224:"Meta"},_n={Alt:"altKey",Control:"ctrlKey",Meta:"metaKey",Shift:"shiftKey"};function Cn(e){var t=this.nativeEvent;return t.getModifierState?t.getModifierState(e):!!(e=_n[e])&&!!t[e]}function Tn(){return Cn}var qn=r({},pn,{key:function(e){if(e.key){var t=En[e.key]||e.key;if("Unidentified"!==t)return t}return"keypress"===e.type?13===(e=an(e))?"Enter":String.fromCharCode(e):"keydown"===e.type||"keyup"===e.type?kn[e.keyCode]||"Unidentified":""},code:0,location:0,ctrlKey:0,shiftKey:0,altKey:0,metaKey:0,repeat:0,locale:0,getModifierState:Tn,charCode:function(e){return"keypress"===e.type?an(e):0},keyCode:function(e){return"keydown"===e.type||"keyup"===e.type?e.keyCode:0},which:function(e){return"keypress"===e.type?an(e):"keydown"===e.type||"keyup"===e.type?e.keyCode:0}}),An=sn(qn),Ln=sn(r({},gn,{pointerId:0,width:0,height:0,pressure:0,tangentialPressure:0,tiltX:0,tiltY:0,twist:0,pointerType:0,isPrimary:0})),Nn=sn(r({},pn,{touches:0,targetTouches:0,changedTouches:0,altKey:0,metaKey:0,ctrlKey:0,shiftKey:0,getModifierState:Tn})),On=sn(r({},dn,{propertyName:0,elapsedTime:0,pseudoElement:0})),Pn=r({},gn,{deltaX:function(e){return"deltaX"in e?e.deltaX:"wheelDeltaX"in e?-e.wheelDeltaX:0},deltaY:function(e){return"deltaY"in e?e.deltaY:"wheelDeltaY"in e?-e.wheelDeltaY:"wheelDelta"in e?-e.wheelDelta:0},deltaZ:0,deltaMode:0}),In=sn(Pn),Rn=[9,13,27,32],Mn=d&&"CompositionEvent"in window,Dn=null;d&&"documentMode"in document&&(Dn=document.documentMode);var Fn=d&&"TextEvent"in window&&!Dn,Bn=d&&(!Mn||Dn&&8<Dn&&11>=Dn),jn=String.fromCharCode(32),zn=!1;function $n(e,t){switch(e){case"keyup":return-1!==Rn.indexOf(t.keyCode);case"keydown":return 229!==t.keyCode;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function Un(e){return"object"==typeof(e=e.detail)&&"data"in e?e.data:null}var Zn=!1;var Hn={color:!0,date:!0,datetime:!0,"datetime-local":!0,email:!0,month:!0,number:!0,password:!0,range:!0,search:!0,tel:!0,text:!0,time:!0,url:!0,week:!0};function Vn(e){var t=e&&e.nodeName&&e.nodeName.toLowerCase();return"input"===t?!!Hn[e.type]:"textarea"===t}function Wn(e,t,n,a){Le(a),0<(t=Ma(t,"onChange")).length&&(n=new fn("onChange","change",null,n,a),e.push({event:n,listeners:t}))}var Gn=null,Yn=null;function Kn(e){qa(e,0)}function Qn(e){if(Q(ar(e)))return e}function Xn(e,t){if("change"===e)return t}var Jn=!1;if(d){var ea;if(d){var ta="oninput"in document;if(!ta){var na=document.createElement("div");na.setAttribute("oninput","return;"),ta="function"==typeof na.oninput}ea=ta}else ea=!1;Jn=ea&&(!document.documentMode||9<document.documentMode)}function aa(){Gn&&(Gn.detachEvent("onpropertychange",ra),Yn=Gn=null)}function ra(e){if("value"===e.propertyName&&Qn(Yn)){var t=[];if(Wn(t,Yn,e,_e(e)),e=Kn,Me)e(t);else{Me=!0;try{Oe(e,t)}finally{Me=!1,Fe()}}}}function oa(e,t,n){"focusin"===e?(aa(),Yn=n,(Gn=t).attachEvent("onpropertychange",ra)):"focusout"===e&&aa()}function sa(e){if("selectionchange"===e||"keyup"===e||"keydown"===e)return Qn(Yn)}function ia(e,t){if("click"===e)return Qn(t)}function la(e,t){if("input"===e||"change"===e)return Qn(t)}var ca="function"==typeof Object.is?Object.is:function(e,t){return e===t&&(0!==e||1/e==1/t)||e!=e&&t!=t},ua=Object.prototype.hasOwnProperty;function da(e,t){if(ca(e,t))return!0;if("object"!=typeof e||null===e||"object"!=typeof t||null===t)return!1;var n=Object.keys(e),a=Object.keys(t);if(n.length!==a.length)return!1;for(a=0;a<n.length;a++)if(!ua.call(t,n[a])||!ca(e[n[a]],t[n[a]]))return!1;return!0}function fa(e){for(;e&&e.firstChild;)e=e.firstChild;return e}function pa(e,t){var n,a=fa(e);for(e=0;a;){if(3===a.nodeType){if(n=e+a.textContent.length,e<=t&&n>=t)return{node:a,offset:t-e};e=n}e:{for(;a;){if(a.nextSibling){a=a.nextSibling;break e}a=a.parentNode}a=void 0}a=fa(a)}}function ma(e,t){return!(!e||!t)&&(e===t||(!e||3!==e.nodeType)&&(t&&3===t.nodeType?ma(e,t.parentNode):"contains"in e?e.contains(t):!!e.compareDocumentPosition&&!!(16&e.compareDocumentPosition(t))))}function ga(){for(var e=window,t=X();t instanceof e.HTMLIFrameElement;){try{var n="string"==typeof t.contentWindow.location.href}catch(a){n=!1}if(!n)break;t=X((e=t.contentWindow).document)}return t}function ha(e){var t=e&&e.nodeName&&e.nodeName.toLowerCase();return t&&("input"===t&&("text"===e.type||"search"===e.type||"tel"===e.type||"url"===e.type||"password"===e.type)||"textarea"===t||"true"===e.contentEditable)}var ba=d&&"documentMode"in document&&11>=document.documentMode,va=null,ya=null,xa=null,wa=!1;function Sa(e,t,n){var a=n.window===n?n.document:9===n.nodeType?n:n.ownerDocument;wa||null==va||va!==X(a)||("selectionStart"in(a=va)&&ha(a)?a={start:a.selectionStart,end:a.selectionEnd}:a={anchorNode:(a=(a.ownerDocument&&a.ownerDocument.defaultView||window).getSelection()).anchorNode,anchorOffset:a.anchorOffset,focusNode:a.focusNode,focusOffset:a.focusOffset},xa&&da(xa,a)||(xa=a,0<(a=Ma(ya,"onSelect")).length&&(t=new fn("onSelect","select",null,t,n),e.push({event:t,listeners:a}),t.target=va)))}It("cancel cancel click click close close contextmenu contextMenu copy copy cut cut auxclick auxClick dblclick doubleClick dragend dragEnd dragstart dragStart drop drop focusin focus focusout blur input input invalid invalid keydown keyDown keypress keyPress keyup keyUp mousedown mouseDown mouseup mouseUp paste paste pause pause play play pointercancel pointerCancel pointerdown pointerDown pointerup pointerUp ratechange rateChange reset reset seeked seeked submit submit touchcancel touchCancel touchend touchEnd touchstart touchStart volumechange volumeChange".split(" "),0),It("drag drag dragenter dragEnter dragexit dragExit dragleave dragLeave dragover dragOver mousemove mouseMove mouseout mouseOut mouseover mouseOver pointermove pointerMove pointerout pointerOut pointerover pointerOver scroll scroll toggle toggle touchmove touchMove wheel wheel".split(" "),1),It(Pt,2);for(var Ea="change selectionchange textInput compositionstart compositionend compositionupdate".split(" "),ka=0;ka<Ea.length;ka++)Ot.set(Ea[ka],0);u("onMouseEnter",["mouseout","mouseover"]),u("onMouseLeave",["mouseout","mouseover"]),u("onPointerEnter",["pointerout","pointerover"]),u("onPointerLeave",["pointerout","pointerover"]),c("onChange","change click focusin focusout input keydown keyup selectionchange".split(" ")),c("onSelect","focusout contextmenu dragend focusin keydown keyup mousedown mouseup selectionchange".split(" ")),c("onBeforeInput",["compositionend","keypress","textInput","paste"]),c("onCompositionEnd","compositionend focusout keydown keypress keyup mousedown".split(" ")),c("onCompositionStart","compositionstart focusout keydown keypress keyup mousedown".split(" ")),c("onCompositionUpdate","compositionupdate focusout keydown keypress keyup mousedown".split(" "));var _a="abort canplay canplaythrough durationchange emptied encrypted ended error loadeddata loadedmetadata loadstart pause play playing progress ratechange seeked seeking stalled suspend timeupdate volumechange waiting".split(" "),Ca=new Set("cancel close invalid load scroll toggle".split(" ").concat(_a));function Ta(e,t,n){var a=e.type||"unknown-event";e.currentTarget=n,function(e,t,n,a,r,o,i,l,c){if(Ge.apply(this,arguments),Ue){if(!Ue)throw Error(s(198));var u=Ze;Ue=!1,Ze=null,He||(He=!0,Ve=u)}}(a,t,void 0,e),e.currentTarget=null}function qa(e,t){t=0!=(4&t);for(var n=0;n<e.length;n++){var a=e[n],r=a.event;a=a.listeners;e:{var o=void 0;if(t)for(var s=a.length-1;0<=s;s--){var i=a[s],l=i.instance,c=i.currentTarget;if(i=i.listener,l!==o&&r.isPropagationStopped())break e;Ta(r,i,c),o=l}else for(s=0;s<a.length;s++){if(l=(i=a[s]).instance,c=i.currentTarget,i=i.listener,l!==o&&r.isPropagationStopped())break e;Ta(r,i,c),o=l}}}if(He)throw e=Ve,He=!1,Ve=null,e}function Aa(e,t){var n=or(t),a=e+"__bubble";n.has(a)||(Pa(t,e,2,!1),n.add(a))}var La="_reactListening"+Math.random().toString(36).slice(2);function Na(e){e[La]||(e[La]=!0,i.forEach((function(t){Ca.has(t)||Oa(t,!1,e,null),Oa(t,!0,e,null)})))}function Oa(e,t,n,a){var r=4<arguments.length&&void 0!==arguments[4]?arguments[4]:0,o=n;if("selectionchange"===e&&9!==n.nodeType&&(o=n.ownerDocument),null!==a&&!t&&Ca.has(e)){if("scroll"!==e)return;r|=2,o=a}var s=or(o),i=e+"__"+(t?"capture":"bubble");s.has(i)||(t&&(r|=4),Pa(o,e,r,t),s.add(i))}function Pa(e,t,n,a){var r=Ot.get(t);switch(void 0===r?2:r){case 0:r=Yt;break;case 1:r=Kt;break;default:r=Qt}n=r.bind(null,t,n,e),r=void 0,!je||"touchstart"!==t&&"touchmove"!==t&&"wheel"!==t||(r=!0),a?void 0!==r?e.addEventListener(t,n,{capture:!0,passive:r}):e.addEventListener(t,n,!0):void 0!==r?e.addEventListener(t,n,{passive:r}):e.addEventListener(t,n,!1)}function Ia(e,t,n,a,r){var o=a;if(0==(1&t)&&0==(2&t)&&null!==a)e:for(;;){if(null===a)return;var s=a.tag;if(3===s||4===s){var i=a.stateNode.containerInfo;if(i===r||8===i.nodeType&&i.parentNode===r)break;if(4===s)for(s=a.return;null!==s;){var l=s.tag;if((3===l||4===l)&&((l=s.stateNode.containerInfo)===r||8===l.nodeType&&l.parentNode===r))return;s=s.return}for(;null!==i;){if(null===(s=tr(i)))return;if(5===(l=s.tag)||6===l){a=o=s;continue e}i=i.parentNode}}a=a.return}!function(e,t,n){if(De)return e(t,n);De=!0;try{return Re(e,t,n)}finally{De=!1,Fe()}}((function(){var a=o,r=_e(n),s=[];e:{var i=Nt.get(e);if(void 0!==i){var l=fn,c=e;switch(e){case"keypress":if(0===an(n))break e;case"keydown":case"keyup":l=An;break;case"focusin":c="focus",l=vn;break;case"focusout":c="blur",l=vn;break;case"beforeblur":case"afterblur":l=vn;break;case"click":if(2===n.button)break e;case"auxclick":case"dblclick":case"mousedown":case"mousemove":case"mouseup":case"mouseout":case"mouseover":case"contextmenu":l=hn;break;case"drag":case"dragend":case"dragenter":case"dragexit":case"dragleave":case"dragover":case"dragstart":case"drop":l=bn;break;case"touchcancel":case"touchend":case"touchmove":case"touchstart":l=Nn;break;case Tt:case qt:case At:l=yn;break;case Lt:l=On;break;case"scroll":l=mn;break;case"wheel":l=In;break;case"copy":case"cut":case"paste":l=wn;break;case"gotpointercapture":case"lostpointercapture":case"pointercancel":case"pointerdown":case"pointermove":case"pointerout":case"pointerover":case"pointerup":l=Ln}var u=0!=(4&t),d=!u&&"scroll"===e,f=u?null!==i?i+"Capture":null:i;u=[];for(var p,m=a;null!==m;){var g=(p=m).stateNode;if(5===p.tag&&null!==g&&(p=g,null!==f&&(null!=(g=Be(m,f))&&u.push(Ra(m,g,p)))),d)break;m=m.return}0<u.length&&(i=new l(i,c,null,n,r),s.push({event:i,listeners:u}))}}if(0==(7&t)){if(l="mouseout"===e||"pointerout"===e,(!(i="mouseover"===e||"pointerover"===e)||0!=(16&t)||!(c=n.relatedTarget||n.fromElement)||!tr(c)&&!c[Ja])&&(l||i)&&(i=r.window===r?r:(i=r.ownerDocument)?i.defaultView||i.parentWindow:window,l?(l=a,null!==(c=(c=n.relatedTarget||n.toElement)?tr(c):null)&&(c!==(d=Ye(c))||5!==c.tag&&6!==c.tag)&&(c=null)):(l=null,c=a),l!==c)){if(u=hn,g="onMouseLeave",f="onMouseEnter",m="mouse","pointerout"!==e&&"pointerover"!==e||(u=Ln,g="onPointerLeave",f="onPointerEnter",m="pointer"),d=null==l?i:ar(l),p=null==c?i:ar(c),(i=new u(g,m+"leave",l,n,r)).target=d,i.relatedTarget=p,g=null,tr(r)===a&&((u=new u(f,m+"enter",c,n,r)).target=p,u.relatedTarget=d,g=u),d=g,l&&c)e:{for(f=c,m=0,p=u=l;p;p=Da(p))m++;for(p=0,g=f;g;g=Da(g))p++;for(;0<m-p;)u=Da(u),m--;for(;0<p-m;)f=Da(f),p--;for(;m--;){if(u===f||null!==f&&u===f.alternate)break e;u=Da(u),f=Da(f)}u=null}else u=null;null!==l&&Fa(s,i,l,u,!1),null!==c&&null!==d&&Fa(s,d,c,u,!0)}if("select"===(l=(i=a?ar(a):window).nodeName&&i.nodeName.toLowerCase())||"input"===l&&"file"===i.type)var h=Xn;else if(Vn(i))if(Jn)h=la;else{h=sa;var b=oa}else(l=i.nodeName)&&"input"===l.toLowerCase()&&("checkbox"===i.type||"radio"===i.type)&&(h=ia);switch(h&&(h=h(e,a))?Wn(s,h,n,r):(b&&b(e,i,a),"focusout"===e&&(b=i._wrapperState)&&b.controlled&&"number"===i.type&&re(i,"number",i.value)),b=a?ar(a):window,e){case"focusin":(Vn(b)||"true"===b.contentEditable)&&(va=b,ya=a,xa=null);break;case"focusout":xa=ya=va=null;break;case"mousedown":wa=!0;break;case"contextmenu":case"mouseup":case"dragend":wa=!1,Sa(s,n,r);break;case"selectionchange":if(ba)break;case"keydown":case"keyup":Sa(s,n,r)}var v;if(Mn)e:{switch(e){case"compositionstart":var y="onCompositionStart";break e;case"compositionend":y="onCompositionEnd";break e;case"compositionupdate":y="onCompositionUpdate";break e}y=void 0}else Zn?$n(e,n)&&(y="onCompositionEnd"):"keydown"===e&&229===n.keyCode&&(y="onCompositionStart");y&&(Bn&&"ko"!==n.locale&&(Zn||"onCompositionStart"!==y?"onCompositionEnd"===y&&Zn&&(v=nn()):(en="value"in(Jt=r)?Jt.value:Jt.textContent,Zn=!0)),0<(b=Ma(a,y)).length&&(y=new Sn(y,e,null,n,r),s.push({event:y,listeners:b}),v?y.data=v:null!==(v=Un(n))&&(y.data=v))),(v=Fn?function(e,t){switch(e){case"compositionend":return Un(t);case"keypress":return 32!==t.which?null:(zn=!0,jn);case"textInput":return(e=t.data)===jn&&zn?null:e;default:return null}}(e,n):function(e,t){if(Zn)return"compositionend"===e||!Mn&&$n(e,t)?(e=nn(),tn=en=Jt=null,Zn=!1,e):null;switch(e){case"paste":default:return null;case"keypress":if(!(t.ctrlKey||t.altKey||t.metaKey)||t.ctrlKey&&t.altKey){if(t.char&&1<t.char.length)return t.char;if(t.which)return String.fromCharCode(t.which)}return null;case"compositionend":return Bn&&"ko"!==t.locale?null:t.data}}(e,n))&&(0<(a=Ma(a,"onBeforeInput")).length&&(r=new Sn("onBeforeInput","beforeinput",null,n,r),s.push({event:r,listeners:a}),r.data=v))}qa(s,t)}))}function Ra(e,t,n){return{instance:e,listener:t,currentTarget:n}}function Ma(e,t){for(var n=t+"Capture",a=[];null!==e;){var r=e,o=r.stateNode;5===r.tag&&null!==o&&(r=o,null!=(o=Be(e,n))&&a.unshift(Ra(e,o,r)),null!=(o=Be(e,t))&&a.push(Ra(e,o,r))),e=e.return}return a}function Da(e){if(null===e)return null;do{e=e.return}while(e&&5!==e.tag);return e||null}function Fa(e,t,n,a,r){for(var o=t._reactName,s=[];null!==n&&n!==a;){var i=n,l=i.alternate,c=i.stateNode;if(null!==l&&l===a)break;5===i.tag&&null!==c&&(i=c,r?null!=(l=Be(n,o))&&s.unshift(Ra(n,l,i)):r||null!=(l=Be(n,o))&&s.push(Ra(n,l,i))),n=n.return}0!==s.length&&e.push({event:t,listeners:s})}function Ba(){}var ja=null,za=null;function $a(e,t){switch(e){case"button":case"input":case"select":case"textarea":return!!t.autoFocus}return!1}function Ua(e,t){return"textarea"===e||"option"===e||"noscript"===e||"string"==typeof t.children||"number"==typeof t.children||"object"==typeof t.dangerouslySetInnerHTML&&null!==t.dangerouslySetInnerHTML&&null!=t.dangerouslySetInnerHTML.__html}var Za="function"==typeof setTimeout?setTimeout:void 0,Ha="function"==typeof clearTimeout?clearTimeout:void 0;function Va(e){1===e.nodeType?e.textContent="":9===e.nodeType&&(null!=(e=e.body)&&(e.textContent=""))}function Wa(e){for(;null!=e;e=e.nextSibling){var t=e.nodeType;if(1===t||3===t)break}return e}function Ga(e){e=e.previousSibling;for(var t=0;e;){if(8===e.nodeType){var n=e.data;if("$"===n||"$!"===n||"$?"===n){if(0===t)return e;t--}else"/$"===n&&t++}e=e.previousSibling}return null}var Ya=0;var Ka=Math.random().toString(36).slice(2),Qa="__reactFiber$"+Ka,Xa="__reactProps$"+Ka,Ja="__reactContainer$"+Ka,er="__reactEvents$"+Ka;function tr(e){var t=e[Qa];if(t)return t;for(var n=e.parentNode;n;){if(t=n[Ja]||n[Qa]){if(n=t.alternate,null!==t.child||null!==n&&null!==n.child)for(e=Ga(e);null!==e;){if(n=e[Qa])return n;e=Ga(e)}return t}n=(e=n).parentNode}return null}function nr(e){return!(e=e[Qa]||e[Ja])||5!==e.tag&&6!==e.tag&&13!==e.tag&&3!==e.tag?null:e}function ar(e){if(5===e.tag||6===e.tag)return e.stateNode;throw Error(s(33))}function rr(e){return e[Xa]||null}function or(e){var t=e[er];return void 0===t&&(t=e[er]=new Set),t}var sr=[],ir=-1;function lr(e){return{current:e}}function cr(e){0>ir||(e.current=sr[ir],sr[ir]=null,ir--)}function ur(e,t){ir++,sr[ir]=e.current,e.current=t}var dr={},fr=lr(dr),pr=lr(!1),mr=dr;function gr(e,t){var n=e.type.contextTypes;if(!n)return dr;var a=e.stateNode;if(a&&a.__reactInternalMemoizedUnmaskedChildContext===t)return a.__reactInternalMemoizedMaskedChildContext;var r,o={};for(r in n)o[r]=t[r];return a&&((e=e.stateNode).__reactInternalMemoizedUnmaskedChildContext=t,e.__reactInternalMemoizedMaskedChildContext=o),o}function hr(e){return null!=(e=e.childContextTypes)}function br(){cr(pr),cr(fr)}function vr(e,t,n){if(fr.current!==dr)throw Error(s(168));ur(fr,t),ur(pr,n)}function yr(e,t,n){var a=e.stateNode;if(e=t.childContextTypes,"function"!=typeof a.getChildContext)return n;for(var o in a=a.getChildContext())if(!(o in e))throw Error(s(108,W(t)||"Unknown",o));return r({},n,a)}function xr(e){return e=(e=e.stateNode)&&e.__reactInternalMemoizedMergedChildContext||dr,mr=fr.current,ur(fr,e),ur(pr,pr.current),!0}function wr(e,t,n){var a=e.stateNode;if(!a)throw Error(s(169));n?(e=yr(e,t,mr),a.__reactInternalMemoizedMergedChildContext=e,cr(pr),cr(fr),ur(fr,e)):cr(pr),ur(pr,n)}var Sr=null,Er=null,kr=o.unstable_runWithPriority,_r=o.unstable_scheduleCallback,Cr=o.unstable_cancelCallback,Tr=o.unstable_shouldYield,qr=o.unstable_requestPaint,Ar=o.unstable_now,Lr=o.unstable_getCurrentPriorityLevel,Nr=o.unstable_ImmediatePriority,Or=o.unstable_UserBlockingPriority,Pr=o.unstable_NormalPriority,Ir=o.unstable_LowPriority,Rr=o.unstable_IdlePriority,Mr={},Dr=void 0!==qr?qr:function(){},Fr=null,Br=null,jr=!1,zr=Ar(),$r=1e4>zr?Ar:function(){return Ar()-zr};function Ur(){switch(Lr()){case Nr:return 99;case Or:return 98;case Pr:return 97;case Ir:return 96;case Rr:return 95;default:throw Error(s(332))}}function Zr(e){switch(e){case 99:return Nr;case 98:return Or;case 97:return Pr;case 96:return Ir;case 95:return Rr;default:throw Error(s(332))}}function Hr(e,t){return e=Zr(e),kr(e,t)}function Vr(e,t,n){return e=Zr(e),_r(e,t,n)}function Wr(){if(null!==Br){var e=Br;Br=null,Cr(e)}Gr()}function Gr(){if(!jr&&null!==Fr){jr=!0;var e=0;try{var t=Fr;Hr(99,(function(){for(;e<t.length;e++){var n=t[e];do{n=n(!0)}while(null!==n)}})),Fr=null}catch(n){throw null!==Fr&&(Fr=Fr.slice(e+1)),_r(Nr,Wr),n}finally{jr=!1}}}var Yr=w.ReactCurrentBatchConfig;function Kr(e,t){if(e&&e.defaultProps){for(var n in t=r({},t),e=e.defaultProps)void 0===t[n]&&(t[n]=e[n]);return t}return t}var Qr=lr(null),Xr=null,Jr=null,eo=null;function to(){eo=Jr=Xr=null}function no(e){var t=Qr.current;cr(Qr),e.type._context._currentValue=t}function ao(e,t){for(;null!==e;){var n=e.alternate;if((e.childLanes&t)===t){if(null===n||(n.childLanes&t)===t)break;n.childLanes|=t}else e.childLanes|=t,null!==n&&(n.childLanes|=t);e=e.return}}function ro(e,t){Xr=e,eo=Jr=null,null!==(e=e.dependencies)&&null!==e.firstContext&&(0!=(e.lanes&t)&&(Ms=!0),e.firstContext=null)}function oo(e,t){if(eo!==e&&!1!==t&&0!==t)if("number"==typeof t&&1073741823!==t||(eo=e,t=1073741823),t={context:e,observedBits:t,next:null},null===Jr){if(null===Xr)throw Error(s(308));Jr=t,Xr.dependencies={lanes:0,firstContext:t,responders:null}}else Jr=Jr.next=t;return e._currentValue}var so=!1;function io(e){e.updateQueue={baseState:e.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null},effects:null}}function lo(e,t){e=e.updateQueue,t.updateQueue===e&&(t.updateQueue={baseState:e.baseState,firstBaseUpdate:e.firstBaseUpdate,lastBaseUpdate:e.lastBaseUpdate,shared:e.shared,effects:e.effects})}function co(e,t){return{eventTime:e,lane:t,tag:0,payload:null,callback:null,next:null}}function uo(e,t){if(null!==(e=e.updateQueue)){var n=(e=e.shared).pending;null===n?t.next=t:(t.next=n.next,n.next=t),e.pending=t}}function fo(e,t){var n=e.updateQueue,a=e.alternate;if(null!==a&&n===(a=a.updateQueue)){var r=null,o=null;if(null!==(n=n.firstBaseUpdate)){do{var s={eventTime:n.eventTime,lane:n.lane,tag:n.tag,payload:n.payload,callback:n.callback,next:null};null===o?r=o=s:o=o.next=s,n=n.next}while(null!==n);null===o?r=o=t:o=o.next=t}else r=o=t;return n={baseState:a.baseState,firstBaseUpdate:r,lastBaseUpdate:o,shared:a.shared,effects:a.effects},void(e.updateQueue=n)}null===(e=n.lastBaseUpdate)?n.firstBaseUpdate=t:e.next=t,n.lastBaseUpdate=t}function po(e,t,n,a){var o=e.updateQueue;so=!1;var s=o.firstBaseUpdate,i=o.lastBaseUpdate,l=o.shared.pending;if(null!==l){o.shared.pending=null;var c=l,u=c.next;c.next=null,null===i?s=u:i.next=u,i=c;var d=e.alternate;if(null!==d){var f=(d=d.updateQueue).lastBaseUpdate;f!==i&&(null===f?d.firstBaseUpdate=u:f.next=u,d.lastBaseUpdate=c)}}if(null!==s){for(f=o.baseState,i=0,d=u=c=null;;){l=s.lane;var p=s.eventTime;if((a&l)===l){null!==d&&(d=d.next={eventTime:p,lane:0,tag:s.tag,payload:s.payload,callback:s.callback,next:null});e:{var m=e,g=s;switch(l=t,p=n,g.tag){case 1:if("function"==typeof(m=g.payload)){f=m.call(p,f,l);break e}f=m;break e;case 3:m.flags=-4097&m.flags|64;case 0:if(null==(l="function"==typeof(m=g.payload)?m.call(p,f,l):m))break e;f=r({},f,l);break e;case 2:so=!0}}null!==s.callback&&(e.flags|=32,null===(l=o.effects)?o.effects=[s]:l.push(s))}else p={eventTime:p,lane:l,tag:s.tag,payload:s.payload,callback:s.callback,next:null},null===d?(u=d=p,c=f):d=d.next=p,i|=l;if(null===(s=s.next)){if(null===(l=o.shared.pending))break;s=l.next,l.next=null,o.lastBaseUpdate=l,o.shared.pending=null}}null===d&&(c=f),o.baseState=c,o.firstBaseUpdate=u,o.lastBaseUpdate=d,zi|=i,e.lanes=i,e.memoizedState=f}}function mo(e,t,n){if(e=t.effects,t.effects=null,null!==e)for(t=0;t<e.length;t++){var a=e[t],r=a.callback;if(null!==r){if(a.callback=null,a=n,"function"!=typeof r)throw Error(s(191,r));r.call(a)}}}var go=(new a.Component).refs;function ho(e,t,n,a){n=null==(n=n(a,t=e.memoizedState))?t:r({},t,n),e.memoizedState=n,0===e.lanes&&(e.updateQueue.baseState=n)}var bo={isMounted:function(e){return!!(e=e._reactInternals)&&Ye(e)===e},enqueueSetState:function(e,t,n){e=e._reactInternals;var a=fl(),r=pl(e),o=co(a,r);o.payload=t,null!=n&&(o.callback=n),uo(e,o),ml(e,r,a)},enqueueReplaceState:function(e,t,n){e=e._reactInternals;var a=fl(),r=pl(e),o=co(a,r);o.tag=1,o.payload=t,null!=n&&(o.callback=n),uo(e,o),ml(e,r,a)},enqueueForceUpdate:function(e,t){e=e._reactInternals;var n=fl(),a=pl(e),r=co(n,a);r.tag=2,null!=t&&(r.callback=t),uo(e,r),ml(e,a,n)}};function vo(e,t,n,a,r,o,s){return"function"==typeof(e=e.stateNode).shouldComponentUpdate?e.shouldComponentUpdate(a,o,s):!t.prototype||!t.prototype.isPureReactComponent||(!da(n,a)||!da(r,o))}function yo(e,t,n){var a=!1,r=dr,o=t.contextType;return"object"==typeof o&&null!==o?o=oo(o):(r=hr(t)?mr:fr.current,o=(a=null!=(a=t.contextTypes))?gr(e,r):dr),t=new t(n,o),e.memoizedState=null!==t.state&&void 0!==t.state?t.state:null,t.updater=bo,e.stateNode=t,t._reactInternals=e,a&&((e=e.stateNode).__reactInternalMemoizedUnmaskedChildContext=r,e.__reactInternalMemoizedMaskedChildContext=o),t}function xo(e,t,n,a){e=t.state,"function"==typeof t.componentWillReceiveProps&&t.componentWillReceiveProps(n,a),"function"==typeof t.UNSAFE_componentWillReceiveProps&&t.UNSAFE_componentWillReceiveProps(n,a),t.state!==e&&bo.enqueueReplaceState(t,t.state,null)}function wo(e,t,n,a){var r=e.stateNode;r.props=n,r.state=e.memoizedState,r.refs=go,io(e);var o=t.contextType;"object"==typeof o&&null!==o?r.context=oo(o):(o=hr(t)?mr:fr.current,r.context=gr(e,o)),po(e,n,r,a),r.state=e.memoizedState,"function"==typeof(o=t.getDerivedStateFromProps)&&(ho(e,t,o,n),r.state=e.memoizedState),"function"==typeof t.getDerivedStateFromProps||"function"==typeof r.getSnapshotBeforeUpdate||"function"!=typeof r.UNSAFE_componentWillMount&&"function"!=typeof r.componentWillMount||(t=r.state,"function"==typeof r.componentWillMount&&r.componentWillMount(),"function"==typeof r.UNSAFE_componentWillMount&&r.UNSAFE_componentWillMount(),t!==r.state&&bo.enqueueReplaceState(r,r.state,null),po(e,n,r,a),r.state=e.memoizedState),"function"==typeof r.componentDidMount&&(e.flags|=4)}var So=Array.isArray;function Eo(e,t,n){if(null!==(e=n.ref)&&"function"!=typeof e&&"object"!=typeof e){if(n._owner){if(n=n._owner){if(1!==n.tag)throw Error(s(309));var a=n.stateNode}if(!a)throw Error(s(147,e));var r=""+e;return null!==t&&null!==t.ref&&"function"==typeof t.ref&&t.ref._stringRef===r?t.ref:(t=function(e){var t=a.refs;t===go&&(t=a.refs={}),null===e?delete t[r]:t[r]=e},t._stringRef=r,t)}if("string"!=typeof e)throw Error(s(284));if(!n._owner)throw Error(s(290,e))}return e}function ko(e,t){if("textarea"!==e.type)throw Error(s(31,"[object Object]"===Object.prototype.toString.call(t)?"object with keys {"+Object.keys(t).join(", ")+"}":t))}function _o(e){function t(t,n){if(e){var a=t.lastEffect;null!==a?(a.nextEffect=n,t.lastEffect=n):t.firstEffect=t.lastEffect=n,n.nextEffect=null,n.flags=8}}function n(n,a){if(!e)return null;for(;null!==a;)t(n,a),a=a.sibling;return null}function a(e,t){for(e=new Map;null!==t;)null!==t.key?e.set(t.key,t):e.set(t.index,t),t=t.sibling;return e}function r(e,t){return(e=Vl(e,t)).index=0,e.sibling=null,e}function o(t,n,a){return t.index=a,e?null!==(a=t.alternate)?(a=a.index)<n?(t.flags=2,n):a:(t.flags=2,n):n}function i(t){return e&&null===t.alternate&&(t.flags=2),t}function l(e,t,n,a){return null===t||6!==t.tag?((t=Kl(n,e.mode,a)).return=e,t):((t=r(t,n)).return=e,t)}function c(e,t,n,a){return null!==t&&t.elementType===n.type?((a=r(t,n.props)).ref=Eo(e,t,n),a.return=e,a):((a=Wl(n.type,n.key,n.props,null,e.mode,a)).ref=Eo(e,t,n),a.return=e,a)}function u(e,t,n,a){return null===t||4!==t.tag||t.stateNode.containerInfo!==n.containerInfo||t.stateNode.implementation!==n.implementation?((t=Ql(n,e.mode,a)).return=e,t):((t=r(t,n.children||[])).return=e,t)}function d(e,t,n,a,o){return null===t||7!==t.tag?((t=Gl(n,e.mode,a,o)).return=e,t):((t=r(t,n)).return=e,t)}function f(e,t,n){if("string"==typeof t||"number"==typeof t)return(t=Kl(""+t,e.mode,n)).return=e,t;if("object"==typeof t&&null!==t){switch(t.$$typeof){case S:return(n=Wl(t.type,t.key,t.props,null,e.mode,n)).ref=Eo(e,null,t),n.return=e,n;case E:return(t=Ql(t,e.mode,n)).return=e,t}if(So(t)||$(t))return(t=Gl(t,e.mode,n,null)).return=e,t;ko(e,t)}return null}function p(e,t,n,a){var r=null!==t?t.key:null;if("string"==typeof n||"number"==typeof n)return null!==r?null:l(e,t,""+n,a);if("object"==typeof n&&null!==n){switch(n.$$typeof){case S:return n.key===r?n.type===k?d(e,t,n.props.children,a,r):c(e,t,n,a):null;case E:return n.key===r?u(e,t,n,a):null}if(So(n)||$(n))return null!==r?null:d(e,t,n,a,null);ko(e,n)}return null}function m(e,t,n,a,r){if("string"==typeof a||"number"==typeof a)return l(t,e=e.get(n)||null,""+a,r);if("object"==typeof a&&null!==a){switch(a.$$typeof){case S:return e=e.get(null===a.key?n:a.key)||null,a.type===k?d(t,e,a.props.children,r,a.key):c(t,e,a,r);case E:return u(t,e=e.get(null===a.key?n:a.key)||null,a,r)}if(So(a)||$(a))return d(t,e=e.get(n)||null,a,r,null);ko(t,a)}return null}function g(r,s,i,l){for(var c=null,u=null,d=s,g=s=0,h=null;null!==d&&g<i.length;g++){d.index>g?(h=d,d=null):h=d.sibling;var b=p(r,d,i[g],l);if(null===b){null===d&&(d=h);break}e&&d&&null===b.alternate&&t(r,d),s=o(b,s,g),null===u?c=b:u.sibling=b,u=b,d=h}if(g===i.length)return n(r,d),c;if(null===d){for(;g<i.length;g++)null!==(d=f(r,i[g],l))&&(s=o(d,s,g),null===u?c=d:u.sibling=d,u=d);return c}for(d=a(r,d);g<i.length;g++)null!==(h=m(d,r,g,i[g],l))&&(e&&null!==h.alternate&&d.delete(null===h.key?g:h.key),s=o(h,s,g),null===u?c=h:u.sibling=h,u=h);return e&&d.forEach((function(e){return t(r,e)})),c}function h(r,i,l,c){var u=$(l);if("function"!=typeof u)throw Error(s(150));if(null==(l=u.call(l)))throw Error(s(151));for(var d=u=null,g=i,h=i=0,b=null,v=l.next();null!==g&&!v.done;h++,v=l.next()){g.index>h?(b=g,g=null):b=g.sibling;var y=p(r,g,v.value,c);if(null===y){null===g&&(g=b);break}e&&g&&null===y.alternate&&t(r,g),i=o(y,i,h),null===d?u=y:d.sibling=y,d=y,g=b}if(v.done)return n(r,g),u;if(null===g){for(;!v.done;h++,v=l.next())null!==(v=f(r,v.value,c))&&(i=o(v,i,h),null===d?u=v:d.sibling=v,d=v);return u}for(g=a(r,g);!v.done;h++,v=l.next())null!==(v=m(g,r,h,v.value,c))&&(e&&null!==v.alternate&&g.delete(null===v.key?h:v.key),i=o(v,i,h),null===d?u=v:d.sibling=v,d=v);return e&&g.forEach((function(e){return t(r,e)})),u}return function(e,a,o,l){var c="object"==typeof o&&null!==o&&o.type===k&&null===o.key;c&&(o=o.props.children);var u="object"==typeof o&&null!==o;if(u)switch(o.$$typeof){case S:e:{for(u=o.key,c=a;null!==c;){if(c.key===u){if(7===c.tag){if(o.type===k){n(e,c.sibling),(a=r(c,o.props.children)).return=e,e=a;break e}}else if(c.elementType===o.type){n(e,c.sibling),(a=r(c,o.props)).ref=Eo(e,c,o),a.return=e,e=a;break e}n(e,c);break}t(e,c),c=c.sibling}o.type===k?((a=Gl(o.props.children,e.mode,l,o.key)).return=e,e=a):((l=Wl(o.type,o.key,o.props,null,e.mode,l)).ref=Eo(e,a,o),l.return=e,e=l)}return i(e);case E:e:{for(c=o.key;null!==a;){if(a.key===c){if(4===a.tag&&a.stateNode.containerInfo===o.containerInfo&&a.stateNode.implementation===o.implementation){n(e,a.sibling),(a=r(a,o.children||[])).return=e,e=a;break e}n(e,a);break}t(e,a),a=a.sibling}(a=Ql(o,e.mode,l)).return=e,e=a}return i(e)}if("string"==typeof o||"number"==typeof o)return o=""+o,null!==a&&6===a.tag?(n(e,a.sibling),(a=r(a,o)).return=e,e=a):(n(e,a),(a=Kl(o,e.mode,l)).return=e,e=a),i(e);if(So(o))return g(e,a,o,l);if($(o))return h(e,a,o,l);if(u&&ko(e,o),void 0===o&&!c)switch(e.tag){case 1:case 22:case 0:case 11:case 15:throw Error(s(152,W(e.type)||"Component"))}return n(e,a)}}var Co=_o(!0),To=_o(!1),qo={},Ao=lr(qo),Lo=lr(qo),No=lr(qo);function Oo(e){if(e===qo)throw Error(s(174));return e}function Po(e,t){switch(ur(No,t),ur(Lo,e),ur(Ao,qo),e=t.nodeType){case 9:case 11:t=(t=t.documentElement)?t.namespaceURI:pe(null,"");break;default:t=pe(t=(e=8===e?t.parentNode:t).namespaceURI||null,e=e.tagName)}cr(Ao),ur(Ao,t)}function Io(){cr(Ao),cr(Lo),cr(No)}function Ro(e){Oo(No.current);var t=Oo(Ao.current),n=pe(t,e.type);t!==n&&(ur(Lo,e),ur(Ao,n))}function Mo(e){Lo.current===e&&(cr(Ao),cr(Lo))}var Do=lr(0);function Fo(e){for(var t=e;null!==t;){if(13===t.tag){var n=t.memoizedState;if(null!==n&&(null===(n=n.dehydrated)||"$?"===n.data||"$!"===n.data))return t}else if(19===t.tag&&void 0!==t.memoizedProps.revealOrder){if(0!=(64&t.flags))return t}else if(null!==t.child){t.child.return=t,t=t.child;continue}if(t===e)break;for(;null===t.sibling;){if(null===t.return||t.return===e)return null;t=t.return}t.sibling.return=t.return,t=t.sibling}return null}var Bo=null,jo=null,zo=!1;function $o(e,t){var n=Zl(5,null,null,0);n.elementType="DELETED",n.type="DELETED",n.stateNode=t,n.return=e,n.flags=8,null!==e.lastEffect?(e.lastEffect.nextEffect=n,e.lastEffect=n):e.firstEffect=e.lastEffect=n}function Uo(e,t){switch(e.tag){case 5:var n=e.type;return null!==(t=1!==t.nodeType||n.toLowerCase()!==t.nodeName.toLowerCase()?null:t)&&(e.stateNode=t,!0);case 6:return null!==(t=""===e.pendingProps||3!==t.nodeType?null:t)&&(e.stateNode=t,!0);default:return!1}}function Zo(e){if(zo){var t=jo;if(t){var n=t;if(!Uo(e,t)){if(!(t=Wa(n.nextSibling))||!Uo(e,t))return e.flags=-1025&e.flags|2,zo=!1,void(Bo=e);$o(Bo,n)}Bo=e,jo=Wa(t.firstChild)}else e.flags=-1025&e.flags|2,zo=!1,Bo=e}}function Ho(e){for(e=e.return;null!==e&&5!==e.tag&&3!==e.tag&&13!==e.tag;)e=e.return;Bo=e}function Vo(e){if(e!==Bo)return!1;if(!zo)return Ho(e),zo=!0,!1;var t=e.type;if(5!==e.tag||"head"!==t&&"body"!==t&&!Ua(t,e.memoizedProps))for(t=jo;t;)$o(e,t),t=Wa(t.nextSibling);if(Ho(e),13===e.tag){if(!(e=null!==(e=e.memoizedState)?e.dehydrated:null))throw Error(s(317));e:{for(e=e.nextSibling,t=0;e;){if(8===e.nodeType){var n=e.data;if("/$"===n){if(0===t){jo=Wa(e.nextSibling);break e}t--}else"$"!==n&&"$!"!==n&&"$?"!==n||t++}e=e.nextSibling}jo=null}}else jo=Bo?Wa(e.stateNode.nextSibling):null;return!0}function Wo(){jo=Bo=null,zo=!1}var Go=[];function Yo(){for(var e=0;e<Go.length;e++)Go[e]._workInProgressVersionPrimary=null;Go.length=0}var Ko=w.ReactCurrentDispatcher,Qo=w.ReactCurrentBatchConfig,Xo=0,Jo=null,es=null,ts=null,ns=!1,as=!1;function rs(){throw Error(s(321))}function os(e,t){if(null===t)return!1;for(var n=0;n<t.length&&n<e.length;n++)if(!ca(e[n],t[n]))return!1;return!0}function ss(e,t,n,a,r,o){if(Xo=o,Jo=t,t.memoizedState=null,t.updateQueue=null,t.lanes=0,Ko.current=null===e||null===e.memoizedState?Os:Ps,e=n(a,r),as){o=0;do{if(as=!1,!(25>o))throw Error(s(301));o+=1,ts=es=null,t.updateQueue=null,Ko.current=Is,e=n(a,r)}while(as)}if(Ko.current=Ns,t=null!==es&&null!==es.next,Xo=0,ts=es=Jo=null,ns=!1,t)throw Error(s(300));return e}function is(){var e={memoizedState:null,baseState:null,baseQueue:null,queue:null,next:null};return null===ts?Jo.memoizedState=ts=e:ts=ts.next=e,ts}function ls(){if(null===es){var e=Jo.alternate;e=null!==e?e.memoizedState:null}else e=es.next;var t=null===ts?Jo.memoizedState:ts.next;if(null!==t)ts=t,es=e;else{if(null===e)throw Error(s(310));e={memoizedState:(es=e).memoizedState,baseState:es.baseState,baseQueue:es.baseQueue,queue:es.queue,next:null},null===ts?Jo.memoizedState=ts=e:ts=ts.next=e}return ts}function cs(e,t){return"function"==typeof t?t(e):t}function us(e){var t=ls(),n=t.queue;if(null===n)throw Error(s(311));n.lastRenderedReducer=e;var a=es,r=a.baseQueue,o=n.pending;if(null!==o){if(null!==r){var i=r.next;r.next=o.next,o.next=i}a.baseQueue=r=o,n.pending=null}if(null!==r){r=r.next,a=a.baseState;var l=i=o=null,c=r;do{var u=c.lane;if((Xo&u)===u)null!==l&&(l=l.next={lane:0,action:c.action,eagerReducer:c.eagerReducer,eagerState:c.eagerState,next:null}),a=c.eagerReducer===e?c.eagerState:e(a,c.action);else{var d={lane:u,action:c.action,eagerReducer:c.eagerReducer,eagerState:c.eagerState,next:null};null===l?(i=l=d,o=a):l=l.next=d,Jo.lanes|=u,zi|=u}c=c.next}while(null!==c&&c!==r);null===l?o=a:l.next=i,ca(a,t.memoizedState)||(Ms=!0),t.memoizedState=a,t.baseState=o,t.baseQueue=l,n.lastRenderedState=a}return[t.memoizedState,n.dispatch]}function ds(e){var t=ls(),n=t.queue;if(null===n)throw Error(s(311));n.lastRenderedReducer=e;var a=n.dispatch,r=n.pending,o=t.memoizedState;if(null!==r){n.pending=null;var i=r=r.next;do{o=e(o,i.action),i=i.next}while(i!==r);ca(o,t.memoizedState)||(Ms=!0),t.memoizedState=o,null===t.baseQueue&&(t.baseState=o),n.lastRenderedState=o}return[o,a]}function fs(e,t,n){var a=t._getVersion;a=a(t._source);var r=t._workInProgressVersionPrimary;if(null!==r?e=r===a:(e=e.mutableReadLanes,(e=(Xo&e)===e)&&(t._workInProgressVersionPrimary=a,Go.push(t))),e)return n(t._source);throw Go.push(t),Error(s(350))}function ps(e,t,n,a){var r=Pi;if(null===r)throw Error(s(349));var o=t._getVersion,i=o(t._source),l=Ko.current,c=l.useState((function(){return fs(r,t,n)})),u=c[1],d=c[0];c=ts;var f=e.memoizedState,p=f.refs,m=p.getSnapshot,g=f.source;f=f.subscribe;var h=Jo;return e.memoizedState={refs:p,source:t,subscribe:a},l.useEffect((function(){p.getSnapshot=n,p.setSnapshot=u;var e=o(t._source);if(!ca(i,e)){e=n(t._source),ca(d,e)||(u(e),e=pl(h),r.mutableReadLanes|=e&r.pendingLanes),e=r.mutableReadLanes,r.entangledLanes|=e;for(var a=r.entanglements,s=e;0<s;){var l=31-Ut(s),c=1<<l;a[l]|=e,s&=~c}}}),[n,t,a]),l.useEffect((function(){return a(t._source,(function(){var e=p.getSnapshot,n=p.setSnapshot;try{n(e(t._source));var a=pl(h);r.mutableReadLanes|=a&r.pendingLanes}catch(o){n((function(){throw o}))}}))}),[t,a]),ca(m,n)&&ca(g,t)&&ca(f,a)||((e={pending:null,dispatch:null,lastRenderedReducer:cs,lastRenderedState:d}).dispatch=u=Ls.bind(null,Jo,e),c.queue=e,c.baseQueue=null,d=fs(r,t,n),c.memoizedState=c.baseState=d),d}function ms(e,t,n){return ps(ls(),e,t,n)}function gs(e){var t=is();return"function"==typeof e&&(e=e()),t.memoizedState=t.baseState=e,e=(e=t.queue={pending:null,dispatch:null,lastRenderedReducer:cs,lastRenderedState:e}).dispatch=Ls.bind(null,Jo,e),[t.memoizedState,e]}function hs(e,t,n,a){return e={tag:e,create:t,destroy:n,deps:a,next:null},null===(t=Jo.updateQueue)?(t={lastEffect:null},Jo.updateQueue=t,t.lastEffect=e.next=e):null===(n=t.lastEffect)?t.lastEffect=e.next=e:(a=n.next,n.next=e,e.next=a,t.lastEffect=e),e}function bs(e){return e={current:e},is().memoizedState=e}function vs(){return ls().memoizedState}function ys(e,t,n,a){var r=is();Jo.flags|=e,r.memoizedState=hs(1|t,n,void 0,void 0===a?null:a)}function xs(e,t,n,a){var r=ls();a=void 0===a?null:a;var o=void 0;if(null!==es){var s=es.memoizedState;if(o=s.destroy,null!==a&&os(a,s.deps))return void hs(t,n,o,a)}Jo.flags|=e,r.memoizedState=hs(1|t,n,o,a)}function ws(e,t){return ys(516,4,e,t)}function Ss(e,t){return xs(516,4,e,t)}function Es(e,t){return xs(4,2,e,t)}function ks(e,t){return"function"==typeof t?(e=e(),t(e),function(){t(null)}):null!=t?(e=e(),t.current=e,function(){t.current=null}):void 0}function _s(e,t,n){return n=null!=n?n.concat([e]):null,xs(4,2,ks.bind(null,t,e),n)}function Cs(){}function Ts(e,t){var n=ls();t=void 0===t?null:t;var a=n.memoizedState;return null!==a&&null!==t&&os(t,a[1])?a[0]:(n.memoizedState=[e,t],e)}function qs(e,t){var n=ls();t=void 0===t?null:t;var a=n.memoizedState;return null!==a&&null!==t&&os(t,a[1])?a[0]:(e=e(),n.memoizedState=[e,t],e)}function As(e,t){var n=Ur();Hr(98>n?98:n,(function(){e(!0)})),Hr(97<n?97:n,(function(){var n=Qo.transition;Qo.transition=1;try{e(!1),t()}finally{Qo.transition=n}}))}function Ls(e,t,n){var a=fl(),r=pl(e),o={lane:r,action:n,eagerReducer:null,eagerState:null,next:null},s=t.pending;if(null===s?o.next=o:(o.next=s.next,s.next=o),t.pending=o,s=e.alternate,e===Jo||null!==s&&s===Jo)as=ns=!0;else{if(0===e.lanes&&(null===s||0===s.lanes)&&null!==(s=t.lastRenderedReducer))try{var i=t.lastRenderedState,l=s(i,n);if(o.eagerReducer=s,o.eagerState=l,ca(l,i))return}catch(c){}ml(e,r,a)}}var Ns={readContext:oo,useCallback:rs,useContext:rs,useEffect:rs,useImperativeHandle:rs,useLayoutEffect:rs,useMemo:rs,useReducer:rs,useRef:rs,useState:rs,useDebugValue:rs,useDeferredValue:rs,useTransition:rs,useMutableSource:rs,useOpaqueIdentifier:rs,unstable_isNewReconciler:!1},Os={readContext:oo,useCallback:function(e,t){return is().memoizedState=[e,void 0===t?null:t],e},useContext:oo,useEffect:ws,useImperativeHandle:function(e,t,n){return n=null!=n?n.concat([e]):null,ys(4,2,ks.bind(null,t,e),n)},useLayoutEffect:function(e,t){return ys(4,2,e,t)},useMemo:function(e,t){var n=is();return t=void 0===t?null:t,e=e(),n.memoizedState=[e,t],e},useReducer:function(e,t,n){var a=is();return t=void 0!==n?n(t):t,a.memoizedState=a.baseState=t,e=(e=a.queue={pending:null,dispatch:null,lastRenderedReducer:e,lastRenderedState:t}).dispatch=Ls.bind(null,Jo,e),[a.memoizedState,e]},useRef:bs,useState:gs,useDebugValue:Cs,useDeferredValue:function(e){var t=gs(e),n=t[0],a=t[1];return ws((function(){var t=Qo.transition;Qo.transition=1;try{a(e)}finally{Qo.transition=t}}),[e]),n},useTransition:function(){var e=gs(!1),t=e[0];return bs(e=As.bind(null,e[1])),[e,t]},useMutableSource:function(e,t,n){var a=is();return a.memoizedState={refs:{getSnapshot:t,setSnapshot:null},source:e,subscribe:n},ps(a,e,t,n)},useOpaqueIdentifier:function(){if(zo){var e=!1,t=function(e){return{$$typeof:R,toString:e,valueOf:e}}((function(){throw e||(e=!0,n("r:"+(Ya++).toString(36))),Error(s(355))})),n=gs(t)[1];return 0==(2&Jo.mode)&&(Jo.flags|=516,hs(5,(function(){n("r:"+(Ya++).toString(36))}),void 0,null)),t}return gs(t="r:"+(Ya++).toString(36)),t},unstable_isNewReconciler:!1},Ps={readContext:oo,useCallback:Ts,useContext:oo,useEffect:Ss,useImperativeHandle:_s,useLayoutEffect:Es,useMemo:qs,useReducer:us,useRef:vs,useState:function(){return us(cs)},useDebugValue:Cs,useDeferredValue:function(e){var t=us(cs),n=t[0],a=t[1];return Ss((function(){var t=Qo.transition;Qo.transition=1;try{a(e)}finally{Qo.transition=t}}),[e]),n},useTransition:function(){var e=us(cs)[0];return[vs().current,e]},useMutableSource:ms,useOpaqueIdentifier:function(){return us(cs)[0]},unstable_isNewReconciler:!1},Is={readContext:oo,useCallback:Ts,useContext:oo,useEffect:Ss,useImperativeHandle:_s,useLayoutEffect:Es,useMemo:qs,useReducer:ds,useRef:vs,useState:function(){return ds(cs)},useDebugValue:Cs,useDeferredValue:function(e){var t=ds(cs),n=t[0],a=t[1];return Ss((function(){var t=Qo.transition;Qo.transition=1;try{a(e)}finally{Qo.transition=t}}),[e]),n},useTransition:function(){var e=ds(cs)[0];return[vs().current,e]},useMutableSource:ms,useOpaqueIdentifier:function(){return ds(cs)[0]},unstable_isNewReconciler:!1},Rs=w.ReactCurrentOwner,Ms=!1;function Ds(e,t,n,a){t.child=null===e?To(t,null,n,a):Co(t,e.child,n,a)}function Fs(e,t,n,a,r){n=n.render;var o=t.ref;return ro(t,r),a=ss(e,t,n,a,o,r),null===e||Ms?(t.flags|=1,Ds(e,t,a,r),t.child):(t.updateQueue=e.updateQueue,t.flags&=-517,e.lanes&=~r,oi(e,t,r))}function Bs(e,t,n,a,r,o){if(null===e){var s=n.type;return"function"!=typeof s||Hl(s)||void 0!==s.defaultProps||null!==n.compare||void 0!==n.defaultProps?((e=Wl(n.type,null,a,t,t.mode,o)).ref=t.ref,e.return=t,t.child=e):(t.tag=15,t.type=s,js(e,t,s,a,r,o))}return s=e.child,0==(r&o)&&(r=s.memoizedProps,(n=null!==(n=n.compare)?n:da)(r,a)&&e.ref===t.ref)?oi(e,t,o):(t.flags|=1,(e=Vl(s,a)).ref=t.ref,e.return=t,t.child=e)}function js(e,t,n,a,r,o){if(null!==e&&da(e.memoizedProps,a)&&e.ref===t.ref){if(Ms=!1,0==(o&r))return t.lanes=e.lanes,oi(e,t,o);0!=(16384&e.flags)&&(Ms=!0)}return Us(e,t,n,a,o)}function zs(e,t,n){var a=t.pendingProps,r=a.children,o=null!==e?e.memoizedState:null;if("hidden"===a.mode||"unstable-defer-without-hiding"===a.mode)if(0==(4&t.mode))t.memoizedState={baseLanes:0},Sl(t,n);else{if(0==(1073741824&n))return e=null!==o?o.baseLanes|n:n,t.lanes=t.childLanes=1073741824,t.memoizedState={baseLanes:e},Sl(t,e),null;t.memoizedState={baseLanes:0},Sl(t,null!==o?o.baseLanes:n)}else null!==o?(a=o.baseLanes|n,t.memoizedState=null):a=n,Sl(t,a);return Ds(e,t,r,n),t.child}function $s(e,t){var n=t.ref;(null===e&&null!==n||null!==e&&e.ref!==n)&&(t.flags|=128)}function Us(e,t,n,a,r){var o=hr(n)?mr:fr.current;return o=gr(t,o),ro(t,r),n=ss(e,t,n,a,o,r),null===e||Ms?(t.flags|=1,Ds(e,t,n,r),t.child):(t.updateQueue=e.updateQueue,t.flags&=-517,e.lanes&=~r,oi(e,t,r))}function Zs(e,t,n,a,r){if(hr(n)){var o=!0;xr(t)}else o=!1;if(ro(t,r),null===t.stateNode)null!==e&&(e.alternate=null,t.alternate=null,t.flags|=2),yo(t,n,a),wo(t,n,a,r),a=!0;else if(null===e){var s=t.stateNode,i=t.memoizedProps;s.props=i;var l=s.context,c=n.contextType;"object"==typeof c&&null!==c?c=oo(c):c=gr(t,c=hr(n)?mr:fr.current);var u=n.getDerivedStateFromProps,d="function"==typeof u||"function"==typeof s.getSnapshotBeforeUpdate;d||"function"!=typeof s.UNSAFE_componentWillReceiveProps&&"function"!=typeof s.componentWillReceiveProps||(i!==a||l!==c)&&xo(t,s,a,c),so=!1;var f=t.memoizedState;s.state=f,po(t,a,s,r),l=t.memoizedState,i!==a||f!==l||pr.current||so?("function"==typeof u&&(ho(t,n,u,a),l=t.memoizedState),(i=so||vo(t,n,i,a,f,l,c))?(d||"function"!=typeof s.UNSAFE_componentWillMount&&"function"!=typeof s.componentWillMount||("function"==typeof s.componentWillMount&&s.componentWillMount(),"function"==typeof s.UNSAFE_componentWillMount&&s.UNSAFE_componentWillMount()),"function"==typeof s.componentDidMount&&(t.flags|=4)):("function"==typeof s.componentDidMount&&(t.flags|=4),t.memoizedProps=a,t.memoizedState=l),s.props=a,s.state=l,s.context=c,a=i):("function"==typeof s.componentDidMount&&(t.flags|=4),a=!1)}else{s=t.stateNode,lo(e,t),i=t.memoizedProps,c=t.type===t.elementType?i:Kr(t.type,i),s.props=c,d=t.pendingProps,f=s.context,"object"==typeof(l=n.contextType)&&null!==l?l=oo(l):l=gr(t,l=hr(n)?mr:fr.current);var p=n.getDerivedStateFromProps;(u="function"==typeof p||"function"==typeof s.getSnapshotBeforeUpdate)||"function"!=typeof s.UNSAFE_componentWillReceiveProps&&"function"!=typeof s.componentWillReceiveProps||(i!==d||f!==l)&&xo(t,s,a,l),so=!1,f=t.memoizedState,s.state=f,po(t,a,s,r);var m=t.memoizedState;i!==d||f!==m||pr.current||so?("function"==typeof p&&(ho(t,n,p,a),m=t.memoizedState),(c=so||vo(t,n,c,a,f,m,l))?(u||"function"!=typeof s.UNSAFE_componentWillUpdate&&"function"!=typeof s.componentWillUpdate||("function"==typeof s.componentWillUpdate&&s.componentWillUpdate(a,m,l),"function"==typeof s.UNSAFE_componentWillUpdate&&s.UNSAFE_componentWillUpdate(a,m,l)),"function"==typeof s.componentDidUpdate&&(t.flags|=4),"function"==typeof s.getSnapshotBeforeUpdate&&(t.flags|=256)):("function"!=typeof s.componentDidUpdate||i===e.memoizedProps&&f===e.memoizedState||(t.flags|=4),"function"!=typeof s.getSnapshotBeforeUpdate||i===e.memoizedProps&&f===e.memoizedState||(t.flags|=256),t.memoizedProps=a,t.memoizedState=m),s.props=a,s.state=m,s.context=l,a=c):("function"!=typeof s.componentDidUpdate||i===e.memoizedProps&&f===e.memoizedState||(t.flags|=4),"function"!=typeof s.getSnapshotBeforeUpdate||i===e.memoizedProps&&f===e.memoizedState||(t.flags|=256),a=!1)}return Hs(e,t,n,a,o,r)}function Hs(e,t,n,a,r,o){$s(e,t);var s=0!=(64&t.flags);if(!a&&!s)return r&&wr(t,n,!1),oi(e,t,o);a=t.stateNode,Rs.current=t;var i=s&&"function"!=typeof n.getDerivedStateFromError?null:a.render();return t.flags|=1,null!==e&&s?(t.child=Co(t,e.child,null,o),t.child=Co(t,null,i,o)):Ds(e,t,i,o),t.memoizedState=a.state,r&&wr(t,n,!0),t.child}function Vs(e){var t=e.stateNode;t.pendingContext?vr(0,t.pendingContext,t.pendingContext!==t.context):t.context&&vr(0,t.context,!1),Po(e,t.containerInfo)}var Ws,Gs,Ys,Ks,Qs={dehydrated:null,retryLane:0};function Xs(e,t,n){var a,r=t.pendingProps,o=Do.current,s=!1;return(a=0!=(64&t.flags))||(a=(null===e||null!==e.memoizedState)&&0!=(2&o)),a?(s=!0,t.flags&=-65):null!==e&&null===e.memoizedState||void 0===r.fallback||!0===r.unstable_avoidThisFallback||(o|=1),ur(Do,1&o),null===e?(void 0!==r.fallback&&Zo(t),e=r.children,o=r.fallback,s?(e=Js(t,e,o,n),t.child.memoizedState={baseLanes:n},t.memoizedState=Qs,e):"number"==typeof r.unstable_expectedLoadTime?(e=Js(t,e,o,n),t.child.memoizedState={baseLanes:n},t.memoizedState=Qs,t.lanes=33554432,e):((n=Yl({mode:"visible",children:e},t.mode,n,null)).return=t,t.child=n)):(e.memoizedState,s?(r=ti(e,t,r.children,r.fallback,n),s=t.child,o=e.child.memoizedState,s.memoizedState=null===o?{baseLanes:n}:{baseLanes:o.baseLanes|n},s.childLanes=e.childLanes&~n,t.memoizedState=Qs,r):(n=ei(e,t,r.children,n),t.memoizedState=null,n))}function Js(e,t,n,a){var r=e.mode,o=e.child;return t={mode:"hidden",children:t},0==(2&r)&&null!==o?(o.childLanes=0,o.pendingProps=t):o=Yl(t,r,0,null),n=Gl(n,r,a,null),o.return=e,n.return=e,o.sibling=n,e.child=o,n}function ei(e,t,n,a){var r=e.child;return e=r.sibling,n=Vl(r,{mode:"visible",children:n}),0==(2&t.mode)&&(n.lanes=a),n.return=t,n.sibling=null,null!==e&&(e.nextEffect=null,e.flags=8,t.firstEffect=t.lastEffect=e),t.child=n}function ti(e,t,n,a,r){var o=t.mode,s=e.child;e=s.sibling;var i={mode:"hidden",children:n};return 0==(2&o)&&t.child!==s?((n=t.child).childLanes=0,n.pendingProps=i,null!==(s=n.lastEffect)?(t.firstEffect=n.firstEffect,t.lastEffect=s,s.nextEffect=null):t.firstEffect=t.lastEffect=null):n=Vl(s,i),null!==e?a=Vl(e,a):(a=Gl(a,o,r,null)).flags|=2,a.return=t,n.return=t,n.sibling=a,t.child=n,a}function ni(e,t){e.lanes|=t;var n=e.alternate;null!==n&&(n.lanes|=t),ao(e.return,t)}function ai(e,t,n,a,r,o){var s=e.memoizedState;null===s?e.memoizedState={isBackwards:t,rendering:null,renderingStartTime:0,last:a,tail:n,tailMode:r,lastEffect:o}:(s.isBackwards=t,s.rendering=null,s.renderingStartTime=0,s.last=a,s.tail=n,s.tailMode=r,s.lastEffect=o)}function ri(e,t,n){var a=t.pendingProps,r=a.revealOrder,o=a.tail;if(Ds(e,t,a.children,n),0!=(2&(a=Do.current)))a=1&a|2,t.flags|=64;else{if(null!==e&&0!=(64&e.flags))e:for(e=t.child;null!==e;){if(13===e.tag)null!==e.memoizedState&&ni(e,n);else if(19===e.tag)ni(e,n);else if(null!==e.child){e.child.return=e,e=e.child;continue}if(e===t)break e;for(;null===e.sibling;){if(null===e.return||e.return===t)break e;e=e.return}e.sibling.return=e.return,e=e.sibling}a&=1}if(ur(Do,a),0==(2&t.mode))t.memoizedState=null;else switch(r){case"forwards":for(n=t.child,r=null;null!==n;)null!==(e=n.alternate)&&null===Fo(e)&&(r=n),n=n.sibling;null===(n=r)?(r=t.child,t.child=null):(r=n.sibling,n.sibling=null),ai(t,!1,r,n,o,t.lastEffect);break;case"backwards":for(n=null,r=t.child,t.child=null;null!==r;){if(null!==(e=r.alternate)&&null===Fo(e)){t.child=r;break}e=r.sibling,r.sibling=n,n=r,r=e}ai(t,!0,n,null,o,t.lastEffect);break;case"together":ai(t,!1,null,null,void 0,t.lastEffect);break;default:t.memoizedState=null}return t.child}function oi(e,t,n){if(null!==e&&(t.dependencies=e.dependencies),zi|=t.lanes,0!=(n&t.childLanes)){if(null!==e&&t.child!==e.child)throw Error(s(153));if(null!==t.child){for(n=Vl(e=t.child,e.pendingProps),t.child=n,n.return=t;null!==e.sibling;)e=e.sibling,(n=n.sibling=Vl(e,e.pendingProps)).return=t;n.sibling=null}return t.child}return null}function si(e,t){if(!zo)switch(e.tailMode){case"hidden":t=e.tail;for(var n=null;null!==t;)null!==t.alternate&&(n=t),t=t.sibling;null===n?e.tail=null:n.sibling=null;break;case"collapsed":n=e.tail;for(var a=null;null!==n;)null!==n.alternate&&(a=n),n=n.sibling;null===a?t||null===e.tail?e.tail=null:e.tail.sibling=null:a.sibling=null}}function ii(e,t,n){var a=t.pendingProps;switch(t.tag){case 2:case 16:case 15:case 0:case 11:case 7:case 8:case 12:case 9:case 14:return null;case 1:case 17:return hr(t.type)&&br(),null;case 3:return Io(),cr(pr),cr(fr),Yo(),(a=t.stateNode).pendingContext&&(a.context=a.pendingContext,a.pendingContext=null),null!==e&&null!==e.child||(Vo(t)?t.flags|=4:a.hydrate||(t.flags|=256)),Gs(t),null;case 5:Mo(t);var o=Oo(No.current);if(n=t.type,null!==e&&null!=t.stateNode)Ys(e,t,n,a,o),e.ref!==t.ref&&(t.flags|=128);else{if(!a){if(null===t.stateNode)throw Error(s(166));return null}if(e=Oo(Ao.current),Vo(t)){a=t.stateNode,n=t.type;var i=t.memoizedProps;switch(a[Qa]=t,a[Xa]=i,n){case"dialog":Aa("cancel",a),Aa("close",a);break;case"iframe":case"object":case"embed":Aa("load",a);break;case"video":case"audio":for(e=0;e<_a.length;e++)Aa(_a[e],a);break;case"source":Aa("error",a);break;case"img":case"image":case"link":Aa("error",a),Aa("load",a);break;case"details":Aa("toggle",a);break;case"input":ee(a,i),Aa("invalid",a);break;case"select":a._wrapperState={wasMultiple:!!i.multiple},Aa("invalid",a);break;case"textarea":le(a,i),Aa("invalid",a)}for(var c in Ee(n,i),e=null,i)i.hasOwnProperty(c)&&(o=i[c],"children"===c?"string"==typeof o?a.textContent!==o&&(e=["children",o]):"number"==typeof o&&a.textContent!==""+o&&(e=["children",""+o]):l.hasOwnProperty(c)&&null!=o&&"onScroll"===c&&Aa("scroll",a));switch(n){case"input":K(a),ae(a,i,!0);break;case"textarea":K(a),ue(a);break;case"select":case"option":break;default:"function"==typeof i.onClick&&(a.onclick=Ba)}a=e,t.updateQueue=a,null!==a&&(t.flags|=4)}else{switch(c=9===o.nodeType?o:o.ownerDocument,e===de.html&&(e=fe(n)),e===de.html?"script"===n?((e=c.createElement("div")).innerHTML="<script><\/script>",e=e.removeChild(e.firstChild)):"string"==typeof a.is?e=c.createElement(n,{is:a.is}):(e=c.createElement(n),"select"===n&&(c=e,a.multiple?c.multiple=!0:a.size&&(c.size=a.size))):e=c.createElementNS(e,n),e[Qa]=t,e[Xa]=a,Ws(e,t,!1,!1),t.stateNode=e,c=ke(n,a),n){case"dialog":Aa("cancel",e),Aa("close",e),o=a;break;case"iframe":case"object":case"embed":Aa("load",e),o=a;break;case"video":case"audio":for(o=0;o<_a.length;o++)Aa(_a[o],e);o=a;break;case"source":Aa("error",e),o=a;break;case"img":case"image":case"link":Aa("error",e),Aa("load",e),o=a;break;case"details":Aa("toggle",e),o=a;break;case"input":ee(e,a),o=J(e,a),Aa("invalid",e);break;case"option":o=oe(e,a);break;case"select":e._wrapperState={wasMultiple:!!a.multiple},o=r({},a,{value:void 0}),Aa("invalid",e);break;case"textarea":le(e,a),o=ie(e,a),Aa("invalid",e);break;default:o=a}Ee(n,o);var u=o;for(i in u)if(u.hasOwnProperty(i)){var d=u[i];"style"===i?we(e,d):"dangerouslySetInnerHTML"===i?null!=(d=d?d.__html:void 0)&&he(e,d):"children"===i?"string"==typeof d?("textarea"!==n||""!==d)&&be(e,d):"number"==typeof d&&be(e,""+d):"suppressContentEditableWarning"!==i&&"suppressHydrationWarning"!==i&&"autoFocus"!==i&&(l.hasOwnProperty(i)?null!=d&&"onScroll"===i&&Aa("scroll",e):null!=d&&x(e,i,d,c))}switch(n){case"input":K(e),ae(e,a,!1);break;case"textarea":K(e),ue(e);break;case"option":null!=a.value&&e.setAttribute("value",""+G(a.value));break;case"select":e.multiple=!!a.multiple,null!=(i=a.value)?se(e,!!a.multiple,i,!1):null!=a.defaultValue&&se(e,!!a.multiple,a.defaultValue,!0);break;default:"function"==typeof o.onClick&&(e.onclick=Ba)}$a(n,a)&&(t.flags|=4)}null!==t.ref&&(t.flags|=128)}return null;case 6:if(e&&null!=t.stateNode)Ks(e,t,e.memoizedProps,a);else{if("string"!=typeof a&&null===t.stateNode)throw Error(s(166));n=Oo(No.current),Oo(Ao.current),Vo(t)?(a=t.stateNode,n=t.memoizedProps,a[Qa]=t,a.nodeValue!==n&&(t.flags|=4)):((a=(9===n.nodeType?n:n.ownerDocument).createTextNode(a))[Qa]=t,t.stateNode=a)}return null;case 13:return cr(Do),a=t.memoizedState,0!=(64&t.flags)?(t.lanes=n,t):(a=null!==a,n=!1,null===e?void 0!==t.memoizedProps.fallback&&Vo(t):n=null!==e.memoizedState,a&&!n&&0!=(2&t.mode)&&(null===e&&!0!==t.memoizedProps.unstable_avoidThisFallback||0!=(1&Do.current)?0===Fi&&(Fi=3):(0!==Fi&&3!==Fi||(Fi=4),null===Pi||0==(134217727&zi)&&0==(134217727&$i)||vl(Pi,Ri))),(a||n)&&(t.flags|=4),null);case 4:return Io(),Gs(t),null===e&&Na(t.stateNode.containerInfo),null;case 10:return no(t),null;case 19:if(cr(Do),null===(a=t.memoizedState))return null;if(i=0!=(64&t.flags),null===(c=a.rendering))if(i)si(a,!1);else{if(0!==Fi||null!==e&&0!=(64&e.flags))for(e=t.child;null!==e;){if(null!==(c=Fo(e))){for(t.flags|=64,si(a,!1),null!==(i=c.updateQueue)&&(t.updateQueue=i,t.flags|=4),null===a.lastEffect&&(t.firstEffect=null),t.lastEffect=a.lastEffect,a=n,n=t.child;null!==n;)e=a,(i=n).flags&=2,i.nextEffect=null,i.firstEffect=null,i.lastEffect=null,null===(c=i.alternate)?(i.childLanes=0,i.lanes=e,i.child=null,i.memoizedProps=null,i.memoizedState=null,i.updateQueue=null,i.dependencies=null,i.stateNode=null):(i.childLanes=c.childLanes,i.lanes=c.lanes,i.child=c.child,i.memoizedProps=c.memoizedProps,i.memoizedState=c.memoizedState,i.updateQueue=c.updateQueue,i.type=c.type,e=c.dependencies,i.dependencies=null===e?null:{lanes:e.lanes,firstContext:e.firstContext}),n=n.sibling;return ur(Do,1&Do.current|2),t.child}e=e.sibling}null!==a.tail&&$r()>Vi&&(t.flags|=64,i=!0,si(a,!1),t.lanes=33554432)}else{if(!i)if(null!==(e=Fo(c))){if(t.flags|=64,i=!0,null!==(n=e.updateQueue)&&(t.updateQueue=n,t.flags|=4),si(a,!0),null===a.tail&&"hidden"===a.tailMode&&!c.alternate&&!zo)return null!==(t=t.lastEffect=a.lastEffect)&&(t.nextEffect=null),null}else 2*$r()-a.renderingStartTime>Vi&&1073741824!==n&&(t.flags|=64,i=!0,si(a,!1),t.lanes=33554432);a.isBackwards?(c.sibling=t.child,t.child=c):(null!==(n=a.last)?n.sibling=c:t.child=c,a.last=c)}return null!==a.tail?(n=a.tail,a.rendering=n,a.tail=n.sibling,a.lastEffect=t.lastEffect,a.renderingStartTime=$r(),n.sibling=null,t=Do.current,ur(Do,i?1&t|2:1&t),n):null;case 23:case 24:return El(),null!==e&&null!==e.memoizedState!=(null!==t.memoizedState)&&"unstable-defer-without-hiding"!==a.mode&&(t.flags|=4),null}throw Error(s(156,t.tag))}function li(e){switch(e.tag){case 1:hr(e.type)&&br();var t=e.flags;return 4096&t?(e.flags=-4097&t|64,e):null;case 3:if(Io(),cr(pr),cr(fr),Yo(),0!=(64&(t=e.flags)))throw Error(s(285));return e.flags=-4097&t|64,e;case 5:return Mo(e),null;case 13:return cr(Do),4096&(t=e.flags)?(e.flags=-4097&t|64,e):null;case 19:return cr(Do),null;case 4:return Io(),null;case 10:return no(e),null;case 23:case 24:return El(),null;default:return null}}function ci(e,t){try{var n="",a=t;do{n+=V(a),a=a.return}while(a);var r=n}catch(o){r="\nError generating stack: "+o.message+"\n"+o.stack}return{value:e,source:t,stack:r}}function ui(e,t){try{console.error(t.value)}catch(n){setTimeout((function(){throw n}))}}Ws=function(e,t){for(var n=t.child;null!==n;){if(5===n.tag||6===n.tag)e.appendChild(n.stateNode);else if(4!==n.tag&&null!==n.child){n.child.return=n,n=n.child;continue}if(n===t)break;for(;null===n.sibling;){if(null===n.return||n.return===t)return;n=n.return}n.sibling.return=n.return,n=n.sibling}},Gs=function(){},Ys=function(e,t,n,a){var o=e.memoizedProps;if(o!==a){e=t.stateNode,Oo(Ao.current);var s,i=null;switch(n){case"input":o=J(e,o),a=J(e,a),i=[];break;case"option":o=oe(e,o),a=oe(e,a),i=[];break;case"select":o=r({},o,{value:void 0}),a=r({},a,{value:void 0}),i=[];break;case"textarea":o=ie(e,o),a=ie(e,a),i=[];break;default:"function"!=typeof o.onClick&&"function"==typeof a.onClick&&(e.onclick=Ba)}for(d in Ee(n,a),n=null,o)if(!a.hasOwnProperty(d)&&o.hasOwnProperty(d)&&null!=o[d])if("style"===d){var c=o[d];for(s in c)c.hasOwnProperty(s)&&(n||(n={}),n[s]="")}else"dangerouslySetInnerHTML"!==d&&"children"!==d&&"suppressContentEditableWarning"!==d&&"suppressHydrationWarning"!==d&&"autoFocus"!==d&&(l.hasOwnProperty(d)?i||(i=[]):(i=i||[]).push(d,null));for(d in a){var u=a[d];if(c=null!=o?o[d]:void 0,a.hasOwnProperty(d)&&u!==c&&(null!=u||null!=c))if("style"===d)if(c){for(s in c)!c.hasOwnProperty(s)||u&&u.hasOwnProperty(s)||(n||(n={}),n[s]="");for(s in u)u.hasOwnProperty(s)&&c[s]!==u[s]&&(n||(n={}),n[s]=u[s])}else n||(i||(i=[]),i.push(d,n)),n=u;else"dangerouslySetInnerHTML"===d?(u=u?u.__html:void 0,c=c?c.__html:void 0,null!=u&&c!==u&&(i=i||[]).push(d,u)):"children"===d?"string"!=typeof u&&"number"!=typeof u||(i=i||[]).push(d,""+u):"suppressContentEditableWarning"!==d&&"suppressHydrationWarning"!==d&&(l.hasOwnProperty(d)?(null!=u&&"onScroll"===d&&Aa("scroll",e),i||c===u||(i=[])):"object"==typeof u&&null!==u&&u.$$typeof===R?u.toString():(i=i||[]).push(d,u))}n&&(i=i||[]).push("style",n);var d=i;(t.updateQueue=d)&&(t.flags|=4)}},Ks=function(e,t,n,a){n!==a&&(t.flags|=4)};var di="function"==typeof WeakMap?WeakMap:Map;function fi(e,t,n){(n=co(-1,n)).tag=3,n.payload={element:null};var a=t.value;return n.callback=function(){Ki||(Ki=!0,Qi=a),ui(0,t)},n}function pi(e,t,n){(n=co(-1,n)).tag=3;var a=e.type.getDerivedStateFromError;if("function"==typeof a){var r=t.value;n.payload=function(){return ui(0,t),a(r)}}var o=e.stateNode;return null!==o&&"function"==typeof o.componentDidCatch&&(n.callback=function(){"function"!=typeof a&&(null===Xi?Xi=new Set([this]):Xi.add(this),ui(0,t));var e=t.stack;this.componentDidCatch(t.value,{componentStack:null!==e?e:""})}),n}var mi="function"==typeof WeakSet?WeakSet:Set;function gi(e){var t=e.ref;if(null!==t)if("function"==typeof t)try{t(null)}catch(n){jl(e,n)}else t.current=null}function hi(e,t){switch(t.tag){case 0:case 11:case 15:case 22:case 5:case 6:case 4:case 17:return;case 1:if(256&t.flags&&null!==e){var n=e.memoizedProps,a=e.memoizedState;t=(e=t.stateNode).getSnapshotBeforeUpdate(t.elementType===t.type?n:Kr(t.type,n),a),e.__reactInternalSnapshotBeforeUpdate=t}return;case 3:return void(256&t.flags&&Va(t.stateNode.containerInfo))}throw Error(s(163))}function bi(e,t,n){switch(n.tag){case 0:case 11:case 15:case 22:if(null!==(t=null!==(t=n.updateQueue)?t.lastEffect:null)){e=t=t.next;do{if(3==(3&e.tag)){var a=e.create;e.destroy=a()}e=e.next}while(e!==t)}if(null!==(t=null!==(t=n.updateQueue)?t.lastEffect:null)){e=t=t.next;do{var r=e;a=r.next,0!=(4&(r=r.tag))&&0!=(1&r)&&(Dl(n,e),Ml(n,e)),e=a}while(e!==t)}return;case 1:return e=n.stateNode,4&n.flags&&(null===t?e.componentDidMount():(a=n.elementType===n.type?t.memoizedProps:Kr(n.type,t.memoizedProps),e.componentDidUpdate(a,t.memoizedState,e.__reactInternalSnapshotBeforeUpdate))),void(null!==(t=n.updateQueue)&&mo(n,t,e));case 3:if(null!==(t=n.updateQueue)){if(e=null,null!==n.child)switch(n.child.tag){case 5:case 1:e=n.child.stateNode}mo(n,t,e)}return;case 5:return e=n.stateNode,void(null===t&&4&n.flags&&$a(n.type,n.memoizedProps)&&e.focus());case 6:case 4:case 12:case 19:case 17:case 20:case 21:case 23:case 24:return;case 13:return void(null===n.memoizedState&&(n=n.alternate,null!==n&&(n=n.memoizedState,null!==n&&(n=n.dehydrated,null!==n&&wt(n)))))}throw Error(s(163))}function vi(e,t){for(var n=e;;){if(5===n.tag){var a=n.stateNode;if(t)"function"==typeof(a=a.style).setProperty?a.setProperty("display","none","important"):a.display="none";else{a=n.stateNode;var r=n.memoizedProps.style;r=null!=r&&r.hasOwnProperty("display")?r.display:null,a.style.display=xe("display",r)}}else if(6===n.tag)n.stateNode.nodeValue=t?"":n.memoizedProps;else if((23!==n.tag&&24!==n.tag||null===n.memoizedState||n===e)&&null!==n.child){n.child.return=n,n=n.child;continue}if(n===e)break;for(;null===n.sibling;){if(null===n.return||n.return===e)return;n=n.return}n.sibling.return=n.return,n=n.sibling}}function yi(e,t){if(Er&&"function"==typeof Er.onCommitFiberUnmount)try{Er.onCommitFiberUnmount(Sr,t)}catch(o){}switch(t.tag){case 0:case 11:case 14:case 15:case 22:if(null!==(e=t.updateQueue)&&null!==(e=e.lastEffect)){var n=e=e.next;do{var a=n,r=a.destroy;if(a=a.tag,void 0!==r)if(0!=(4&a))Dl(t,n);else{a=t;try{r()}catch(o){jl(a,o)}}n=n.next}while(n!==e)}break;case 1:if(gi(t),"function"==typeof(e=t.stateNode).componentWillUnmount)try{e.props=t.memoizedProps,e.state=t.memoizedState,e.componentWillUnmount()}catch(o){jl(t,o)}break;case 5:gi(t);break;case 4:_i(e,t)}}function xi(e){e.alternate=null,e.child=null,e.dependencies=null,e.firstEffect=null,e.lastEffect=null,e.memoizedProps=null,e.memoizedState=null,e.pendingProps=null,e.return=null,e.updateQueue=null}function wi(e){return 5===e.tag||3===e.tag||4===e.tag}function Si(e){e:{for(var t=e.return;null!==t;){if(wi(t))break e;t=t.return}throw Error(s(160))}var n=t;switch(t=n.stateNode,n.tag){case 5:var a=!1;break;case 3:case 4:t=t.containerInfo,a=!0;break;default:throw Error(s(161))}16&n.flags&&(be(t,""),n.flags&=-17);e:t:for(n=e;;){for(;null===n.sibling;){if(null===n.return||wi(n.return)){n=null;break e}n=n.return}for(n.sibling.return=n.return,n=n.sibling;5!==n.tag&&6!==n.tag&&18!==n.tag;){if(2&n.flags)continue t;if(null===n.child||4===n.tag)continue t;n.child.return=n,n=n.child}if(!(2&n.flags)){n=n.stateNode;break e}}a?Ei(e,n,t):ki(e,n,t)}function Ei(e,t,n){var a=e.tag,r=5===a||6===a;if(r)e=r?e.stateNode:e.stateNode.instance,t?8===n.nodeType?n.parentNode.insertBefore(e,t):n.insertBefore(e,t):(8===n.nodeType?(t=n.parentNode).insertBefore(e,n):(t=n).appendChild(e),null!=(n=n._reactRootContainer)||null!==t.onclick||(t.onclick=Ba));else if(4!==a&&null!==(e=e.child))for(Ei(e,t,n),e=e.sibling;null!==e;)Ei(e,t,n),e=e.sibling}function ki(e,t,n){var a=e.tag,r=5===a||6===a;if(r)e=r?e.stateNode:e.stateNode.instance,t?n.insertBefore(e,t):n.appendChild(e);else if(4!==a&&null!==(e=e.child))for(ki(e,t,n),e=e.sibling;null!==e;)ki(e,t,n),e=e.sibling}function _i(e,t){for(var n,a,r=t,o=!1;;){if(!o){o=r.return;e:for(;;){if(null===o)throw Error(s(160));switch(n=o.stateNode,o.tag){case 5:a=!1;break e;case 3:case 4:n=n.containerInfo,a=!0;break e}o=o.return}o=!0}if(5===r.tag||6===r.tag){e:for(var i=e,l=r,c=l;;)if(yi(i,c),null!==c.child&&4!==c.tag)c.child.return=c,c=c.child;else{if(c===l)break e;for(;null===c.sibling;){if(null===c.return||c.return===l)break e;c=c.return}c.sibling.return=c.return,c=c.sibling}a?(i=n,l=r.stateNode,8===i.nodeType?i.parentNode.removeChild(l):i.removeChild(l)):n.removeChild(r.stateNode)}else if(4===r.tag){if(null!==r.child){n=r.stateNode.containerInfo,a=!0,r.child.return=r,r=r.child;continue}}else if(yi(e,r),null!==r.child){r.child.return=r,r=r.child;continue}if(r===t)break;for(;null===r.sibling;){if(null===r.return||r.return===t)return;4===(r=r.return).tag&&(o=!1)}r.sibling.return=r.return,r=r.sibling}}function Ci(e,t){switch(t.tag){case 0:case 11:case 14:case 15:case 22:var n=t.updateQueue;if(null!==(n=null!==n?n.lastEffect:null)){var a=n=n.next;do{3==(3&a.tag)&&(e=a.destroy,a.destroy=void 0,void 0!==e&&e()),a=a.next}while(a!==n)}return;case 1:case 12:case 17:return;case 5:if(null!=(n=t.stateNode)){a=t.memoizedProps;var r=null!==e?e.memoizedProps:a;e=t.type;var o=t.updateQueue;if(t.updateQueue=null,null!==o){for(n[Xa]=a,"input"===e&&"radio"===a.type&&null!=a.name&&te(n,a),ke(e,r),t=ke(e,a),r=0;r<o.length;r+=2){var i=o[r],l=o[r+1];"style"===i?we(n,l):"dangerouslySetInnerHTML"===i?he(n,l):"children"===i?be(n,l):x(n,i,l,t)}switch(e){case"input":ne(n,a);break;case"textarea":ce(n,a);break;case"select":e=n._wrapperState.wasMultiple,n._wrapperState.wasMultiple=!!a.multiple,null!=(o=a.value)?se(n,!!a.multiple,o,!1):e!==!!a.multiple&&(null!=a.defaultValue?se(n,!!a.multiple,a.defaultValue,!0):se(n,!!a.multiple,a.multiple?[]:"",!1))}}}return;case 6:if(null===t.stateNode)throw Error(s(162));return void(t.stateNode.nodeValue=t.memoizedProps);case 3:return void((n=t.stateNode).hydrate&&(n.hydrate=!1,wt(n.containerInfo)));case 13:return null!==t.memoizedState&&(Hi=$r(),vi(t.child,!0)),void Ti(t);case 19:return void Ti(t);case 23:case 24:return void vi(t,null!==t.memoizedState)}throw Error(s(163))}function Ti(e){var t=e.updateQueue;if(null!==t){e.updateQueue=null;var n=e.stateNode;null===n&&(n=e.stateNode=new mi),t.forEach((function(t){var a=$l.bind(null,e,t);n.has(t)||(n.add(t),t.then(a,a))}))}}function qi(e,t){return null!==e&&(null===(e=e.memoizedState)||null!==e.dehydrated)&&(null!==(t=t.memoizedState)&&null===t.dehydrated)}var Ai=Math.ceil,Li=w.ReactCurrentDispatcher,Ni=w.ReactCurrentOwner,Oi=0,Pi=null,Ii=null,Ri=0,Mi=0,Di=lr(0),Fi=0,Bi=null,ji=0,zi=0,$i=0,Ui=0,Zi=null,Hi=0,Vi=1/0;function Wi(){Vi=$r()+500}var Gi,Yi=null,Ki=!1,Qi=null,Xi=null,Ji=!1,el=null,tl=90,nl=[],al=[],rl=null,ol=0,sl=null,il=-1,ll=0,cl=0,ul=null,dl=!1;function fl(){return 0!=(48&Oi)?$r():-1!==il?il:il=$r()}function pl(e){if(0==(2&(e=e.mode)))return 1;if(0==(4&e))return 99===Ur()?1:2;if(0===ll&&(ll=ji),0!==Yr.transition){0!==cl&&(cl=null!==Zi?Zi.pendingLanes:0),e=ll;var t=4186112&~cl;return 0===(t&=-t)&&(0===(t=(e=4186112&~e)&-e)&&(t=8192)),t}return e=Ur(),0!=(4&Oi)&&98===e?e=Bt(12,ll):e=Bt(e=function(e){switch(e){case 99:return 15;case 98:return 10;case 97:case 96:return 8;case 95:return 2;default:return 0}}(e),ll),e}function ml(e,t,n){if(50<ol)throw ol=0,sl=null,Error(s(185));if(null===(e=gl(e,t)))return null;$t(e,t,n),e===Pi&&($i|=t,4===Fi&&vl(e,Ri));var a=Ur();1===t?0!=(8&Oi)&&0==(48&Oi)?yl(e):(hl(e,n),0===Oi&&(Wi(),Wr())):(0==(4&Oi)||98!==a&&99!==a||(null===rl?rl=new Set([e]):rl.add(e)),hl(e,n)),Zi=e}function gl(e,t){e.lanes|=t;var n=e.alternate;for(null!==n&&(n.lanes|=t),n=e,e=e.return;null!==e;)e.childLanes|=t,null!==(n=e.alternate)&&(n.childLanes|=t),n=e,e=e.return;return 3===n.tag?n.stateNode:null}function hl(e,t){for(var n=e.callbackNode,a=e.suspendedLanes,r=e.pingedLanes,o=e.expirationTimes,i=e.pendingLanes;0<i;){var l=31-Ut(i),c=1<<l,u=o[l];if(-1===u){if(0==(c&a)||0!=(c&r)){u=t,Mt(c);var d=Rt;o[l]=10<=d?u+250:6<=d?u+5e3:-1}}else u<=t&&(e.expiredLanes|=c);i&=~c}if(a=Dt(e,e===Pi?Ri:0),t=Rt,0===a)null!==n&&(n!==Mr&&Cr(n),e.callbackNode=null,e.callbackPriority=0);else{if(null!==n){if(e.callbackPriority===t)return;n!==Mr&&Cr(n)}15===t?(n=yl.bind(null,e),null===Fr?(Fr=[n],Br=_r(Nr,Gr)):Fr.push(n),n=Mr):14===t?n=Vr(99,yl.bind(null,e)):(n=function(e){switch(e){case 15:case 14:return 99;case 13:case 12:case 11:case 10:return 98;case 9:case 8:case 7:case 6:case 4:case 5:return 97;case 3:case 2:case 1:return 95;case 0:return 90;default:throw Error(s(358,e))}}(t),n=Vr(n,bl.bind(null,e))),e.callbackPriority=t,e.callbackNode=n}}function bl(e){if(il=-1,cl=ll=0,0!=(48&Oi))throw Error(s(327));var t=e.callbackNode;if(Rl()&&e.callbackNode!==t)return null;var n=Dt(e,e===Pi?Ri:0);if(0===n)return null;var a=n,r=Oi;Oi|=16;var o=Cl();for(Pi===e&&Ri===a||(Wi(),kl(e,a));;)try{Al();break}catch(l){_l(e,l)}if(to(),Li.current=o,Oi=r,null!==Ii?a=0:(Pi=null,Ri=0,a=Fi),0!=(ji&$i))kl(e,0);else if(0!==a){if(2===a&&(Oi|=64,e.hydrate&&(e.hydrate=!1,Va(e.containerInfo)),0!==(n=Ft(e))&&(a=Tl(e,n))),1===a)throw t=Bi,kl(e,0),vl(e,n),hl(e,$r()),t;switch(e.finishedWork=e.current.alternate,e.finishedLanes=n,a){case 0:case 1:throw Error(s(345));case 2:case 5:Ol(e);break;case 3:if(vl(e,n),(62914560&n)===n&&10<(a=Hi+500-$r())){if(0!==Dt(e,0))break;if(((r=e.suspendedLanes)&n)!==n){fl(),e.pingedLanes|=e.suspendedLanes&r;break}e.timeoutHandle=Za(Ol.bind(null,e),a);break}Ol(e);break;case 4:if(vl(e,n),(4186112&n)===n)break;for(a=e.eventTimes,r=-1;0<n;){var i=31-Ut(n);o=1<<i,(i=a[i])>r&&(r=i),n&=~o}if(n=r,10<(n=(120>(n=$r()-n)?120:480>n?480:1080>n?1080:1920>n?1920:3e3>n?3e3:4320>n?4320:1960*Ai(n/1960))-n)){e.timeoutHandle=Za(Ol.bind(null,e),n);break}Ol(e);break;default:throw Error(s(329))}}return hl(e,$r()),e.callbackNode===t?bl.bind(null,e):null}function vl(e,t){for(t&=~Ui,t&=~$i,e.suspendedLanes|=t,e.pingedLanes&=~t,e=e.expirationTimes;0<t;){var n=31-Ut(t),a=1<<n;e[n]=-1,t&=~a}}function yl(e){if(0!=(48&Oi))throw Error(s(327));if(Rl(),e===Pi&&0!=(e.expiredLanes&Ri)){var t=Ri,n=Tl(e,t);0!=(ji&$i)&&(n=Tl(e,t=Dt(e,t)))}else n=Tl(e,t=Dt(e,0));if(0!==e.tag&&2===n&&(Oi|=64,e.hydrate&&(e.hydrate=!1,Va(e.containerInfo)),0!==(t=Ft(e))&&(n=Tl(e,t))),1===n)throw n=Bi,kl(e,0),vl(e,t),hl(e,$r()),n;return e.finishedWork=e.current.alternate,e.finishedLanes=t,Ol(e),hl(e,$r()),null}function xl(e,t){var n=Oi;Oi|=1;try{return e(t)}finally{0===(Oi=n)&&(Wi(),Wr())}}function wl(e,t){var n=Oi;Oi&=-2,Oi|=8;try{return e(t)}finally{0===(Oi=n)&&(Wi(),Wr())}}function Sl(e,t){ur(Di,Mi),Mi|=t,ji|=t}function El(){Mi=Di.current,cr(Di)}function kl(e,t){e.finishedWork=null,e.finishedLanes=0;var n=e.timeoutHandle;if(-1!==n&&(e.timeoutHandle=-1,Ha(n)),null!==Ii)for(n=Ii.return;null!==n;){var a=n;switch(a.tag){case 1:null!=(a=a.type.childContextTypes)&&br();break;case 3:Io(),cr(pr),cr(fr),Yo();break;case 5:Mo(a);break;case 4:Io();break;case 13:case 19:cr(Do);break;case 10:no(a);break;case 23:case 24:El()}n=n.return}Pi=e,Ii=Vl(e.current,null),Ri=Mi=ji=t,Fi=0,Bi=null,Ui=$i=zi=0}function _l(e,t){for(;;){var n=Ii;try{if(to(),Ko.current=Ns,ns){for(var a=Jo.memoizedState;null!==a;){var r=a.queue;null!==r&&(r.pending=null),a=a.next}ns=!1}if(Xo=0,ts=es=Jo=null,as=!1,Ni.current=null,null===n||null===n.return){Fi=1,Bi=t,Ii=null;break}e:{var o=e,s=n.return,i=n,l=t;if(t=Ri,i.flags|=2048,i.firstEffect=i.lastEffect=null,null!==l&&"object"==typeof l&&"function"==typeof l.then){var c=l;if(0==(2&i.mode)){var u=i.alternate;u?(i.updateQueue=u.updateQueue,i.memoizedState=u.memoizedState,i.lanes=u.lanes):(i.updateQueue=null,i.memoizedState=null)}var d=0!=(1&Do.current),f=s;do{var p;if(p=13===f.tag){var m=f.memoizedState;if(null!==m)p=null!==m.dehydrated;else{var g=f.memoizedProps;p=void 0!==g.fallback&&(!0!==g.unstable_avoidThisFallback||!d)}}if(p){var h=f.updateQueue;if(null===h){var b=new Set;b.add(c),f.updateQueue=b}else h.add(c);if(0==(2&f.mode)){if(f.flags|=64,i.flags|=16384,i.flags&=-2981,1===i.tag)if(null===i.alternate)i.tag=17;else{var v=co(-1,1);v.tag=2,uo(i,v)}i.lanes|=1;break e}l=void 0,i=t;var y=o.pingCache;if(null===y?(y=o.pingCache=new di,l=new Set,y.set(c,l)):void 0===(l=y.get(c))&&(l=new Set,y.set(c,l)),!l.has(i)){l.add(i);var x=zl.bind(null,o,c,i);c.then(x,x)}f.flags|=4096,f.lanes=t;break e}f=f.return}while(null!==f);l=Error((W(i.type)||"A React component")+" suspended while rendering, but no fallback UI was specified.\n\nAdd a <Suspense fallback=...> component higher in the tree to provide a loading indicator or placeholder to display.")}5!==Fi&&(Fi=2),l=ci(l,i),f=s;do{switch(f.tag){case 3:o=l,f.flags|=4096,t&=-t,f.lanes|=t,fo(f,fi(0,o,t));break e;case 1:o=l;var w=f.type,S=f.stateNode;if(0==(64&f.flags)&&("function"==typeof w.getDerivedStateFromError||null!==S&&"function"==typeof S.componentDidCatch&&(null===Xi||!Xi.has(S)))){f.flags|=4096,t&=-t,f.lanes|=t,fo(f,pi(f,o,t));break e}}f=f.return}while(null!==f)}Nl(n)}catch(E){t=E,Ii===n&&null!==n&&(Ii=n=n.return);continue}break}}function Cl(){var e=Li.current;return Li.current=Ns,null===e?Ns:e}function Tl(e,t){var n=Oi;Oi|=16;var a=Cl();for(Pi===e&&Ri===t||kl(e,t);;)try{ql();break}catch(r){_l(e,r)}if(to(),Oi=n,Li.current=a,null!==Ii)throw Error(s(261));return Pi=null,Ri=0,Fi}function ql(){for(;null!==Ii;)Ll(Ii)}function Al(){for(;null!==Ii&&!Tr();)Ll(Ii)}function Ll(e){var t=Gi(e.alternate,e,Mi);e.memoizedProps=e.pendingProps,null===t?Nl(e):Ii=t,Ni.current=null}function Nl(e){var t=e;do{var n=t.alternate;if(e=t.return,0==(2048&t.flags)){if(null!==(n=ii(n,t,Mi)))return void(Ii=n);if(24!==(n=t).tag&&23!==n.tag||null===n.memoizedState||0!=(1073741824&Mi)||0==(4&n.mode)){for(var a=0,r=n.child;null!==r;)a|=r.lanes|r.childLanes,r=r.sibling;n.childLanes=a}null!==e&&0==(2048&e.flags)&&(null===e.firstEffect&&(e.firstEffect=t.firstEffect),null!==t.lastEffect&&(null!==e.lastEffect&&(e.lastEffect.nextEffect=t.firstEffect),e.lastEffect=t.lastEffect),1<t.flags&&(null!==e.lastEffect?e.lastEffect.nextEffect=t:e.firstEffect=t,e.lastEffect=t))}else{if(null!==(n=li(t)))return n.flags&=2047,void(Ii=n);null!==e&&(e.firstEffect=e.lastEffect=null,e.flags|=2048)}if(null!==(t=t.sibling))return void(Ii=t);Ii=t=e}while(null!==t);0===Fi&&(Fi=5)}function Ol(e){var t=Ur();return Hr(99,Pl.bind(null,e,t)),null}function Pl(e,t){do{Rl()}while(null!==el);if(0!=(48&Oi))throw Error(s(327));var n=e.finishedWork;if(null===n)return null;if(e.finishedWork=null,e.finishedLanes=0,n===e.current)throw Error(s(177));e.callbackNode=null;var a=n.lanes|n.childLanes,r=a,o=e.pendingLanes&~r;e.pendingLanes=r,e.suspendedLanes=0,e.pingedLanes=0,e.expiredLanes&=r,e.mutableReadLanes&=r,e.entangledLanes&=r,r=e.entanglements;for(var i=e.eventTimes,l=e.expirationTimes;0<o;){var c=31-Ut(o),u=1<<c;r[c]=0,i[c]=-1,l[c]=-1,o&=~u}if(null!==rl&&0==(24&a)&&rl.has(e)&&rl.delete(e),e===Pi&&(Ii=Pi=null,Ri=0),1<n.flags?null!==n.lastEffect?(n.lastEffect.nextEffect=n,a=n.firstEffect):a=n:a=n.firstEffect,null!==a){if(r=Oi,Oi|=32,Ni.current=null,ja=Gt,ha(i=ga())){if("selectionStart"in i)l={start:i.selectionStart,end:i.selectionEnd};else e:if(l=(l=i.ownerDocument)&&l.defaultView||window,(u=l.getSelection&&l.getSelection())&&0!==u.rangeCount){l=u.anchorNode,o=u.anchorOffset,c=u.focusNode,u=u.focusOffset;try{l.nodeType,c.nodeType}catch(C){l=null;break e}var d=0,f=-1,p=-1,m=0,g=0,h=i,b=null;t:for(;;){for(var v;h!==l||0!==o&&3!==h.nodeType||(f=d+o),h!==c||0!==u&&3!==h.nodeType||(p=d+u),3===h.nodeType&&(d+=h.nodeValue.length),null!==(v=h.firstChild);)b=h,h=v;for(;;){if(h===i)break t;if(b===l&&++m===o&&(f=d),b===c&&++g===u&&(p=d),null!==(v=h.nextSibling))break;b=(h=b).parentNode}h=v}l=-1===f||-1===p?null:{start:f,end:p}}else l=null;l=l||{start:0,end:0}}else l=null;za={focusedElem:i,selectionRange:l},Gt=!1,ul=null,dl=!1,Yi=a;do{try{Il()}catch(C){if(null===Yi)throw Error(s(330));jl(Yi,C),Yi=Yi.nextEffect}}while(null!==Yi);ul=null,Yi=a;do{try{for(i=e;null!==Yi;){var y=Yi.flags;if(16&y&&be(Yi.stateNode,""),128&y){var x=Yi.alternate;if(null!==x){var w=x.ref;null!==w&&("function"==typeof w?w(null):w.current=null)}}switch(1038&y){case 2:Si(Yi),Yi.flags&=-3;break;case 6:Si(Yi),Yi.flags&=-3,Ci(Yi.alternate,Yi);break;case 1024:Yi.flags&=-1025;break;case 1028:Yi.flags&=-1025,Ci(Yi.alternate,Yi);break;case 4:Ci(Yi.alternate,Yi);break;case 8:_i(i,l=Yi);var S=l.alternate;xi(l),null!==S&&xi(S)}Yi=Yi.nextEffect}}catch(C){if(null===Yi)throw Error(s(330));jl(Yi,C),Yi=Yi.nextEffect}}while(null!==Yi);if(w=za,x=ga(),y=w.focusedElem,i=w.selectionRange,x!==y&&y&&y.ownerDocument&&ma(y.ownerDocument.documentElement,y)){null!==i&&ha(y)&&(x=i.start,void 0===(w=i.end)&&(w=x),"selectionStart"in y?(y.selectionStart=x,y.selectionEnd=Math.min(w,y.value.length)):(w=(x=y.ownerDocument||document)&&x.defaultView||window).getSelection&&(w=w.getSelection(),l=y.textContent.length,S=Math.min(i.start,l),i=void 0===i.end?S:Math.min(i.end,l),!w.extend&&S>i&&(l=i,i=S,S=l),l=pa(y,S),o=pa(y,i),l&&o&&(1!==w.rangeCount||w.anchorNode!==l.node||w.anchorOffset!==l.offset||w.focusNode!==o.node||w.focusOffset!==o.offset)&&((x=x.createRange()).setStart(l.node,l.offset),w.removeAllRanges(),S>i?(w.addRange(x),w.extend(o.node,o.offset)):(x.setEnd(o.node,o.offset),w.addRange(x))))),x=[];for(w=y;w=w.parentNode;)1===w.nodeType&&x.push({element:w,left:w.scrollLeft,top:w.scrollTop});for("function"==typeof y.focus&&y.focus(),y=0;y<x.length;y++)(w=x[y]).element.scrollLeft=w.left,w.element.scrollTop=w.top}Gt=!!ja,za=ja=null,e.current=n,Yi=a;do{try{for(y=e;null!==Yi;){var E=Yi.flags;if(36&E&&bi(y,Yi.alternate,Yi),128&E){x=void 0;var k=Yi.ref;if(null!==k){var _=Yi.stateNode;Yi.tag,x=_,"function"==typeof k?k(x):k.current=x}}Yi=Yi.nextEffect}}catch(C){if(null===Yi)throw Error(s(330));jl(Yi,C),Yi=Yi.nextEffect}}while(null!==Yi);Yi=null,Dr(),Oi=r}else e.current=n;if(Ji)Ji=!1,el=e,tl=t;else for(Yi=a;null!==Yi;)t=Yi.nextEffect,Yi.nextEffect=null,8&Yi.flags&&((E=Yi).sibling=null,E.stateNode=null),Yi=t;if(0===(a=e.pendingLanes)&&(Xi=null),1===a?e===sl?ol++:(ol=0,sl=e):ol=0,n=n.stateNode,Er&&"function"==typeof Er.onCommitFiberRoot)try{Er.onCommitFiberRoot(Sr,n,void 0,64==(64&n.current.flags))}catch(C){}if(hl(e,$r()),Ki)throw Ki=!1,e=Qi,Qi=null,e;return 0!=(8&Oi)||Wr(),null}function Il(){for(;null!==Yi;){var e=Yi.alternate;dl||null===ul||(0!=(8&Yi.flags)?Je(Yi,ul)&&(dl=!0):13===Yi.tag&&qi(e,Yi)&&Je(Yi,ul)&&(dl=!0));var t=Yi.flags;0!=(256&t)&&hi(e,Yi),0==(512&t)||Ji||(Ji=!0,Vr(97,(function(){return Rl(),null}))),Yi=Yi.nextEffect}}function Rl(){if(90!==tl){var e=97<tl?97:tl;return tl=90,Hr(e,Fl)}return!1}function Ml(e,t){nl.push(t,e),Ji||(Ji=!0,Vr(97,(function(){return Rl(),null})))}function Dl(e,t){al.push(t,e),Ji||(Ji=!0,Vr(97,(function(){return Rl(),null})))}function Fl(){if(null===el)return!1;var e=el;if(el=null,0!=(48&Oi))throw Error(s(331));var t=Oi;Oi|=32;var n=al;al=[];for(var a=0;a<n.length;a+=2){var r=n[a],o=n[a+1],i=r.destroy;if(r.destroy=void 0,"function"==typeof i)try{i()}catch(c){if(null===o)throw Error(s(330));jl(o,c)}}for(n=nl,nl=[],a=0;a<n.length;a+=2){r=n[a],o=n[a+1];try{var l=r.create;r.destroy=l()}catch(c){if(null===o)throw Error(s(330));jl(o,c)}}for(l=e.current.firstEffect;null!==l;)e=l.nextEffect,l.nextEffect=null,8&l.flags&&(l.sibling=null,l.stateNode=null),l=e;return Oi=t,Wr(),!0}function Bl(e,t,n){uo(e,t=fi(0,t=ci(n,t),1)),t=fl(),null!==(e=gl(e,1))&&($t(e,1,t),hl(e,t))}function jl(e,t){if(3===e.tag)Bl(e,e,t);else for(var n=e.return;null!==n;){if(3===n.tag){Bl(n,e,t);break}if(1===n.tag){var a=n.stateNode;if("function"==typeof n.type.getDerivedStateFromError||"function"==typeof a.componentDidCatch&&(null===Xi||!Xi.has(a))){var r=pi(n,e=ci(t,e),1);if(uo(n,r),r=fl(),null!==(n=gl(n,1)))$t(n,1,r),hl(n,r);else if("function"==typeof a.componentDidCatch&&(null===Xi||!Xi.has(a)))try{a.componentDidCatch(t,e)}catch(o){}break}}n=n.return}}function zl(e,t,n){var a=e.pingCache;null!==a&&a.delete(t),t=fl(),e.pingedLanes|=e.suspendedLanes&n,Pi===e&&(Ri&n)===n&&(4===Fi||3===Fi&&(62914560&Ri)===Ri&&500>$r()-Hi?kl(e,0):Ui|=n),hl(e,t)}function $l(e,t){var n=e.stateNode;null!==n&&n.delete(t),0===(t=0)&&(0==(2&(t=e.mode))?t=1:0==(4&t)?t=99===Ur()?1:2:(0===ll&&(ll=ji),0===(t=jt(62914560&~ll))&&(t=4194304))),n=fl(),null!==(e=gl(e,t))&&($t(e,t,n),hl(e,n))}function Ul(e,t,n,a){this.tag=e,this.key=n,this.sibling=this.child=this.return=this.stateNode=this.type=this.elementType=null,this.index=0,this.ref=null,this.pendingProps=t,this.dependencies=this.memoizedState=this.updateQueue=this.memoizedProps=null,this.mode=a,this.flags=0,this.lastEffect=this.firstEffect=this.nextEffect=null,this.childLanes=this.lanes=0,this.alternate=null}function Zl(e,t,n,a){return new Ul(e,t,n,a)}function Hl(e){return!(!(e=e.prototype)||!e.isReactComponent)}function Vl(e,t){var n=e.alternate;return null===n?((n=Zl(e.tag,t,e.key,e.mode)).elementType=e.elementType,n.type=e.type,n.stateNode=e.stateNode,n.alternate=e,e.alternate=n):(n.pendingProps=t,n.type=e.type,n.flags=0,n.nextEffect=null,n.firstEffect=null,n.lastEffect=null),n.childLanes=e.childLanes,n.lanes=e.lanes,n.child=e.child,n.memoizedProps=e.memoizedProps,n.memoizedState=e.memoizedState,n.updateQueue=e.updateQueue,t=e.dependencies,n.dependencies=null===t?null:{lanes:t.lanes,firstContext:t.firstContext},n.sibling=e.sibling,n.index=e.index,n.ref=e.ref,n}function Wl(e,t,n,a,r,o){var i=2;if(a=e,"function"==typeof e)Hl(e)&&(i=1);else if("string"==typeof e)i=5;else e:switch(e){case k:return Gl(n.children,r,o,t);case M:i=8,r|=16;break;case _:i=8,r|=1;break;case C:return(e=Zl(12,n,t,8|r)).elementType=C,e.type=C,e.lanes=o,e;case L:return(e=Zl(13,n,t,r)).type=L,e.elementType=L,e.lanes=o,e;case N:return(e=Zl(19,n,t,r)).elementType=N,e.lanes=o,e;case D:return Yl(n,r,o,t);case F:return(e=Zl(24,n,t,r)).elementType=F,e.lanes=o,e;default:if("object"==typeof e&&null!==e)switch(e.$$typeof){case T:i=10;break e;case q:i=9;break e;case A:i=11;break e;case O:i=14;break e;case P:i=16,a=null;break e;case I:i=22;break e}throw Error(s(130,null==e?e:typeof e,""))}return(t=Zl(i,n,t,r)).elementType=e,t.type=a,t.lanes=o,t}function Gl(e,t,n,a){return(e=Zl(7,e,a,t)).lanes=n,e}function Yl(e,t,n,a){return(e=Zl(23,e,a,t)).elementType=D,e.lanes=n,e}function Kl(e,t,n){return(e=Zl(6,e,null,t)).lanes=n,e}function Ql(e,t,n){return(t=Zl(4,null!==e.children?e.children:[],e.key,t)).lanes=n,t.stateNode={containerInfo:e.containerInfo,pendingChildren:null,implementation:e.implementation},t}function Xl(e,t,n){this.tag=t,this.containerInfo=e,this.finishedWork=this.pingCache=this.current=this.pendingChildren=null,this.timeoutHandle=-1,this.pendingContext=this.context=null,this.hydrate=n,this.callbackNode=null,this.callbackPriority=0,this.eventTimes=zt(0),this.expirationTimes=zt(-1),this.entangledLanes=this.finishedLanes=this.mutableReadLanes=this.expiredLanes=this.pingedLanes=this.suspendedLanes=this.pendingLanes=0,this.entanglements=zt(0),this.mutableSourceEagerHydrationData=null}function Jl(e,t,n,a){var r=t.current,o=fl(),i=pl(r);e:if(n){t:{if(Ye(n=n._reactInternals)!==n||1!==n.tag)throw Error(s(170));var l=n;do{switch(l.tag){case 3:l=l.stateNode.context;break t;case 1:if(hr(l.type)){l=l.stateNode.__reactInternalMemoizedMergedChildContext;break t}}l=l.return}while(null!==l);throw Error(s(171))}if(1===n.tag){var c=n.type;if(hr(c)){n=yr(n,c,l);break e}}n=l}else n=dr;return null===t.context?t.context=n:t.pendingContext=n,(t=co(o,i)).payload={element:e},null!==(a=void 0===a?null:a)&&(t.callback=a),uo(r,t),ml(r,i,o),i}function ec(e){return(e=e.current).child?(e.child.tag,e.child.stateNode):null}function tc(e,t){if(null!==(e=e.memoizedState)&&null!==e.dehydrated){var n=e.retryLane;e.retryLane=0!==n&&n<t?n:t}}function nc(e,t){tc(e,t),(e=e.alternate)&&tc(e,t)}function ac(e,t,n){var a=null!=n&&null!=n.hydrationOptions&&n.hydrationOptions.mutableSources||null;if(n=new Xl(e,t,null!=n&&!0===n.hydrate),t=Zl(3,null,null,2===t?7:1===t?3:0),n.current=t,t.stateNode=n,io(t),e[Ja]=n.current,Na(8===e.nodeType?e.parentNode:e),a)for(e=0;e<a.length;e++){var r=(t=a[e])._getVersion;r=r(t._source),null==n.mutableSourceEagerHydrationData?n.mutableSourceEagerHydrationData=[t,r]:n.mutableSourceEagerHydrationData.push(t,r)}this._internalRoot=n}function rc(e){return!(!e||1!==e.nodeType&&9!==e.nodeType&&11!==e.nodeType&&(8!==e.nodeType||" react-mount-point-unstable "!==e.nodeValue))}function oc(e,t,n,a,r){var o=n._reactRootContainer;if(o){var s=o._internalRoot;if("function"==typeof r){var i=r;r=function(){var e=ec(s);i.call(e)}}Jl(t,s,e,r)}else{if(o=n._reactRootContainer=function(e,t){if(t||(t=!(!(t=e?9===e.nodeType?e.documentElement:e.firstChild:null)||1!==t.nodeType||!t.hasAttribute("data-reactroot"))),!t)for(var n;n=e.lastChild;)e.removeChild(n);return new ac(e,0,t?{hydrate:!0}:void 0)}(n,a),s=o._internalRoot,"function"==typeof r){var l=r;r=function(){var e=ec(s);l.call(e)}}wl((function(){Jl(t,s,e,r)}))}return ec(s)}function sc(e,t){var n=2<arguments.length&&void 0!==arguments[2]?arguments[2]:null;if(!rc(t))throw Error(s(200));return function(e,t,n){var a=3<arguments.length&&void 0!==arguments[3]?arguments[3]:null;return{$$typeof:E,key:null==a?null:""+a,children:e,containerInfo:t,implementation:n}}(e,t,null,n)}Gi=function(e,t,n){var a=t.lanes;if(null!==e)if(e.memoizedProps!==t.pendingProps||pr.current)Ms=!0;else{if(0==(n&a)){switch(Ms=!1,t.tag){case 3:Vs(t),Wo();break;case 5:Ro(t);break;case 1:hr(t.type)&&xr(t);break;case 4:Po(t,t.stateNode.containerInfo);break;case 10:a=t.memoizedProps.value;var r=t.type._context;ur(Qr,r._currentValue),r._currentValue=a;break;case 13:if(null!==t.memoizedState)return 0!=(n&t.child.childLanes)?Xs(e,t,n):(ur(Do,1&Do.current),null!==(t=oi(e,t,n))?t.sibling:null);ur(Do,1&Do.current);break;case 19:if(a=0!=(n&t.childLanes),0!=(64&e.flags)){if(a)return ri(e,t,n);t.flags|=64}if(null!==(r=t.memoizedState)&&(r.rendering=null,r.tail=null,r.lastEffect=null),ur(Do,Do.current),a)break;return null;case 23:case 24:return t.lanes=0,zs(e,t,n)}return oi(e,t,n)}Ms=0!=(16384&e.flags)}else Ms=!1;switch(t.lanes=0,t.tag){case 2:if(a=t.type,null!==e&&(e.alternate=null,t.alternate=null,t.flags|=2),e=t.pendingProps,r=gr(t,fr.current),ro(t,n),r=ss(null,t,a,e,r,n),t.flags|=1,"object"==typeof r&&null!==r&&"function"==typeof r.render&&void 0===r.$$typeof){if(t.tag=1,t.memoizedState=null,t.updateQueue=null,hr(a)){var o=!0;xr(t)}else o=!1;t.memoizedState=null!==r.state&&void 0!==r.state?r.state:null,io(t);var i=a.getDerivedStateFromProps;"function"==typeof i&&ho(t,a,i,e),r.updater=bo,t.stateNode=r,r._reactInternals=t,wo(t,a,e,n),t=Hs(null,t,a,!0,o,n)}else t.tag=0,Ds(null,t,r,n),t=t.child;return t;case 16:r=t.elementType;e:{switch(null!==e&&(e.alternate=null,t.alternate=null,t.flags|=2),e=t.pendingProps,r=(o=r._init)(r._payload),t.type=r,o=t.tag=function(e){if("function"==typeof e)return Hl(e)?1:0;if(null!=e){if((e=e.$$typeof)===A)return 11;if(e===O)return 14}return 2}(r),e=Kr(r,e),o){case 0:t=Us(null,t,r,e,n);break e;case 1:t=Zs(null,t,r,e,n);break e;case 11:t=Fs(null,t,r,e,n);break e;case 14:t=Bs(null,t,r,Kr(r.type,e),a,n);break e}throw Error(s(306,r,""))}return t;case 0:return a=t.type,r=t.pendingProps,Us(e,t,a,r=t.elementType===a?r:Kr(a,r),n);case 1:return a=t.type,r=t.pendingProps,Zs(e,t,a,r=t.elementType===a?r:Kr(a,r),n);case 3:if(Vs(t),a=t.updateQueue,null===e||null===a)throw Error(s(282));if(a=t.pendingProps,r=null!==(r=t.memoizedState)?r.element:null,lo(e,t),po(t,a,null,n),(a=t.memoizedState.element)===r)Wo(),t=oi(e,t,n);else{if((o=(r=t.stateNode).hydrate)&&(jo=Wa(t.stateNode.containerInfo.firstChild),Bo=t,o=zo=!0),o){if(null!=(e=r.mutableSourceEagerHydrationData))for(r=0;r<e.length;r+=2)(o=e[r])._workInProgressVersionPrimary=e[r+1],Go.push(o);for(n=To(t,null,a,n),t.child=n;n;)n.flags=-3&n.flags|1024,n=n.sibling}else Ds(e,t,a,n),Wo();t=t.child}return t;case 5:return Ro(t),null===e&&Zo(t),a=t.type,r=t.pendingProps,o=null!==e?e.memoizedProps:null,i=r.children,Ua(a,r)?i=null:null!==o&&Ua(a,o)&&(t.flags|=16),$s(e,t),Ds(e,t,i,n),t.child;case 6:return null===e&&Zo(t),null;case 13:return Xs(e,t,n);case 4:return Po(t,t.stateNode.containerInfo),a=t.pendingProps,null===e?t.child=Co(t,null,a,n):Ds(e,t,a,n),t.child;case 11:return a=t.type,r=t.pendingProps,Fs(e,t,a,r=t.elementType===a?r:Kr(a,r),n);case 7:return Ds(e,t,t.pendingProps,n),t.child;case 8:case 12:return Ds(e,t,t.pendingProps.children,n),t.child;case 10:e:{a=t.type._context,r=t.pendingProps,i=t.memoizedProps,o=r.value;var l=t.type._context;if(ur(Qr,l._currentValue),l._currentValue=o,null!==i)if(l=i.value,0===(o=ca(l,o)?0:0|("function"==typeof a._calculateChangedBits?a._calculateChangedBits(l,o):1073741823))){if(i.children===r.children&&!pr.current){t=oi(e,t,n);break e}}else for(null!==(l=t.child)&&(l.return=t);null!==l;){var c=l.dependencies;if(null!==c){i=l.child;for(var u=c.firstContext;null!==u;){if(u.context===a&&0!=(u.observedBits&o)){1===l.tag&&((u=co(-1,n&-n)).tag=2,uo(l,u)),l.lanes|=n,null!==(u=l.alternate)&&(u.lanes|=n),ao(l.return,n),c.lanes|=n;break}u=u.next}}else i=10===l.tag&&l.type===t.type?null:l.child;if(null!==i)i.return=l;else for(i=l;null!==i;){if(i===t){i=null;break}if(null!==(l=i.sibling)){l.return=i.return,i=l;break}i=i.return}l=i}Ds(e,t,r.children,n),t=t.child}return t;case 9:return r=t.type,a=(o=t.pendingProps).children,ro(t,n),a=a(r=oo(r,o.unstable_observedBits)),t.flags|=1,Ds(e,t,a,n),t.child;case 14:return o=Kr(r=t.type,t.pendingProps),Bs(e,t,r,o=Kr(r.type,o),a,n);case 15:return js(e,t,t.type,t.pendingProps,a,n);case 17:return a=t.type,r=t.pendingProps,r=t.elementType===a?r:Kr(a,r),null!==e&&(e.alternate=null,t.alternate=null,t.flags|=2),t.tag=1,hr(a)?(e=!0,xr(t)):e=!1,ro(t,n),yo(t,a,r),wo(t,a,r,n),Hs(null,t,a,!0,e,n);case 19:return ri(e,t,n);case 23:case 24:return zs(e,t,n)}throw Error(s(156,t.tag))},ac.prototype.render=function(e){Jl(e,this._internalRoot,null,null)},ac.prototype.unmount=function(){var e=this._internalRoot,t=e.containerInfo;Jl(null,e,null,(function(){t[Ja]=null}))},et=function(e){13===e.tag&&(ml(e,4,fl()),nc(e,4))},tt=function(e){13===e.tag&&(ml(e,67108864,fl()),nc(e,67108864))},nt=function(e){if(13===e.tag){var t=fl(),n=pl(e);ml(e,n,t),nc(e,n)}},at=function(e,t){return t()},Ce=function(e,t,n){switch(t){case"input":if(ne(e,n),t=n.name,"radio"===n.type&&null!=t){for(n=e;n.parentNode;)n=n.parentNode;for(n=n.querySelectorAll("input[name="+JSON.stringify(""+t)+'][type="radio"]'),t=0;t<n.length;t++){var a=n[t];if(a!==e&&a.form===e.form){var r=rr(a);if(!r)throw Error(s(90));Q(a),ne(a,r)}}}break;case"textarea":ce(e,n);break;case"select":null!=(t=n.value)&&se(e,!!n.multiple,t,!1)}},Oe=xl,Pe=function(e,t,n,a,r){var o=Oi;Oi|=4;try{return Hr(98,e.bind(null,t,n,a,r))}finally{0===(Oi=o)&&(Wi(),Wr())}},Ie=function(){0==(49&Oi)&&(function(){if(null!==rl){var e=rl;rl=null,e.forEach((function(e){e.expiredLanes|=24&e.pendingLanes,hl(e,$r())}))}Wr()}(),Rl())},Re=function(e,t){var n=Oi;Oi|=2;try{return e(t)}finally{0===(Oi=n)&&(Wi(),Wr())}};var ic={Events:[nr,ar,rr,Le,Ne,Rl,{current:!1}]},lc={findFiberByHostInstance:tr,bundleType:0,version:"17.0.2",rendererPackageName:"react-dom"},cc={bundleType:lc.bundleType,version:lc.version,rendererPackageName:lc.rendererPackageName,rendererConfig:lc.rendererConfig,overrideHookState:null,overrideHookStateDeletePath:null,overrideHookStateRenamePath:null,overrideProps:null,overridePropsDeletePath:null,overridePropsRenamePath:null,setSuspenseHandler:null,scheduleUpdate:null,currentDispatcherRef:w.ReactCurrentDispatcher,findHostInstanceByFiber:function(e){return null===(e=Xe(e))?null:e.stateNode},findFiberByHostInstance:lc.findFiberByHostInstance||function(){return null},findHostInstancesForRefresh:null,scheduleRefresh:null,scheduleRoot:null,setRefreshHandler:null,getCurrentFiber:null};if("undefined"!=typeof __REACT_DEVTOOLS_GLOBAL_HOOK__){var uc=__REACT_DEVTOOLS_GLOBAL_HOOK__;if(!uc.isDisabled&&uc.supportsFiber)try{Sr=uc.inject(cc),Er=uc}catch(ge){}}t.hydrate=function(e,t,n){if(!rc(t))throw Error(s(200));return oc(null,e,t,!0,n)}},3935:(e,t,n)=>{"use strict";!function e(){if("undefined"!=typeof __REACT_DEVTOOLS_GLOBAL_HOOK__&&"function"==typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE)try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(e)}catch(t){console.error(t)}}(),e.exports=n(4448)},9590:e=>{var t="undefined"!=typeof Element,n="function"==typeof Map,a="function"==typeof Set,r="function"==typeof ArrayBuffer&&!!ArrayBuffer.isView;function o(e,s){if(e===s)return!0;if(e&&s&&"object"==typeof e&&"object"==typeof s){if(e.constructor!==s.constructor)return!1;var i,l,c,u;if(Array.isArray(e)){if((i=e.length)!=s.length)return!1;for(l=i;0!=l--;)if(!o(e[l],s[l]))return!1;return!0}if(n&&e instanceof Map&&s instanceof Map){if(e.size!==s.size)return!1;for(u=e.entries();!(l=u.next()).done;)if(!s.has(l.value[0]))return!1;for(u=e.entries();!(l=u.next()).done;)if(!o(l.value[1],s.get(l.value[0])))return!1;return!0}if(a&&e instanceof Set&&s instanceof Set){if(e.size!==s.size)return!1;for(u=e.entries();!(l=u.next()).done;)if(!s.has(l.value[0]))return!1;return!0}if(r&&ArrayBuffer.isView(e)&&ArrayBuffer.isView(s)){if((i=e.length)!=s.length)return!1;for(l=i;0!=l--;)if(e[l]!==s[l])return!1;return!0}if(e.constructor===RegExp)return e.source===s.source&&e.flags===s.flags;if(e.valueOf!==Object.prototype.valueOf&&"function"==typeof e.valueOf&&"function"==typeof s.valueOf)return e.valueOf()===s.valueOf();if(e.toString!==Object.prototype.toString&&"function"==typeof e.toString&&"function"==typeof s.toString)return e.toString()===s.toString();if((i=(c=Object.keys(e)).length)!==Object.keys(s).length)return!1;for(l=i;0!=l--;)if(!Object.prototype.hasOwnProperty.call(s,c[l]))return!1;if(t&&e instanceof Element)return!1;for(l=i;0!=l--;)if(("_owner"!==c[l]&&"__v"!==c[l]&&"__o"!==c[l]||!e.$$typeof)&&!o(e[c[l]],s[c[l]]))return!1;return!0}return e!=e&&s!=s}e.exports=function(e,t){try{return o(e,t)}catch(n){if((n.message||"").match(/stack|recursion/i))return console.warn("react-fast-compare cannot handle circular refs"),!1;throw n}}},405:(e,t,n)=>{"use strict";n.d(t,{B6:()=>H,ql:()=>J});var a=n(7294),r=n(5697),o=n.n(r),s=n(9590),i=n.n(s),l=n(1143),c=n.n(l),u=n(6774),d=n.n(u);function f(){return f=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var a in n)Object.prototype.hasOwnProperty.call(n,a)&&(e[a]=n[a])}return e},f.apply(this,arguments)}function p(e,t){e.prototype=Object.create(t.prototype),e.prototype.constructor=e,m(e,t)}function m(e,t){return m=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e},m(e,t)}function g(e,t){if(null==e)return{};var n,a,r={},o=Object.keys(e);for(a=0;a<o.length;a++)t.indexOf(n=o[a])>=0||(r[n]=e[n]);return r}var h={BASE:"base",BODY:"body",HEAD:"head",HTML:"html",LINK:"link",META:"meta",NOSCRIPT:"noscript",SCRIPT:"script",STYLE:"style",TITLE:"title",FRAGMENT:"Symbol(react.fragment)"},b={rel:["amphtml","canonical","alternate"]},v={type:["application/ld+json"]},y={charset:"",name:["robots","description"],property:["og:type","og:title","og:url","og:image","og:image:alt","og:description","twitter:url","twitter:title","twitter:description","twitter:image","twitter:image:alt","twitter:card","twitter:site"]},x=Object.keys(h).map((function(e){return h[e]})),w={accesskey:"accessKey",charset:"charSet",class:"className",contenteditable:"contentEditable",contextmenu:"contextMenu","http-equiv":"httpEquiv",itemprop:"itemProp",tabindex:"tabIndex"},S=Object.keys(w).reduce((function(e,t){return e[w[t]]=t,e}),{}),E=function(e,t){for(var n=e.length-1;n>=0;n-=1){var a=e[n];if(Object.prototype.hasOwnProperty.call(a,t))return a[t]}return null},k=function(e){var t=E(e,h.TITLE),n=E(e,"titleTemplate");if(Array.isArray(t)&&(t=t.join("")),n&&t)return n.replace(/%s/g,(function(){return t}));var a=E(e,"defaultTitle");return t||a||void 0},_=function(e){return E(e,"onChangeClientState")||function(){}},C=function(e,t){return t.filter((function(t){return void 0!==t[e]})).map((function(t){return t[e]})).reduce((function(e,t){return f({},e,t)}),{})},T=function(e,t){return t.filter((function(e){return void 0!==e[h.BASE]})).map((function(e){return e[h.BASE]})).reverse().reduce((function(t,n){if(!t.length)for(var a=Object.keys(n),r=0;r<a.length;r+=1){var o=a[r].toLowerCase();if(-1!==e.indexOf(o)&&n[o])return t.concat(n)}return t}),[])},q=function(e,t,n){var a={};return n.filter((function(t){return!!Array.isArray(t[e])||(void 0!==t[e]&&console&&"function"==typeof console.warn&&console.warn("Helmet: "+e+' should be of type "Array". Instead found type "'+typeof t[e]+'"'),!1)})).map((function(t){return t[e]})).reverse().reduce((function(e,n){var r={};n.filter((function(e){for(var n,o=Object.keys(e),s=0;s<o.length;s+=1){var i=o[s],l=i.toLowerCase();-1===t.indexOf(l)||"rel"===n&&"canonical"===e[n].toLowerCase()||"rel"===l&&"stylesheet"===e[l].toLowerCase()||(n=l),-1===t.indexOf(i)||"innerHTML"!==i&&"cssText"!==i&&"itemprop"!==i||(n=i)}if(!n||!e[n])return!1;var c=e[n].toLowerCase();return a[n]||(a[n]={}),r[n]||(r[n]={}),!a[n][c]&&(r[n][c]=!0,!0)})).reverse().forEach((function(t){return e.push(t)}));for(var o=Object.keys(r),s=0;s<o.length;s+=1){var i=o[s],l=f({},a[i],r[i]);a[i]=l}return e}),[]).reverse()},A=function(e,t){if(Array.isArray(e)&&e.length)for(var n=0;n<e.length;n+=1)if(e[n][t])return!0;return!1},L=function(e){return Array.isArray(e)?e.join(""):e},N=function(e,t){return Array.isArray(e)?e.reduce((function(e,n){return function(e,t){for(var n=Object.keys(e),a=0;a<n.length;a+=1)if(t[n[a]]&&t[n[a]].includes(e[n[a]]))return!0;return!1}(n,t)?e.priority.push(n):e.default.push(n),e}),{priority:[],default:[]}):{default:e}},O=function(e,t){var n;return f({},e,((n={})[t]=void 0,n))},P=[h.NOSCRIPT,h.SCRIPT,h.STYLE],I=function(e,t){return void 0===t&&(t=!0),!1===t?String(e):String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")},R=function(e){return Object.keys(e).reduce((function(t,n){var a=void 0!==e[n]?n+'="'+e[n]+'"':""+n;return t?t+" "+a:a}),"")},M=function(e,t){return void 0===t&&(t={}),Object.keys(e).reduce((function(t,n){return t[w[n]||n]=e[n],t}),t)},D=function(e,t){return t.map((function(t,n){var r,o=((r={key:n})["data-rh"]=!0,r);return Object.keys(t).forEach((function(e){var n=w[e]||e;"innerHTML"===n||"cssText"===n?o.dangerouslySetInnerHTML={__html:t.innerHTML||t.cssText}:o[n]=t[e]})),a.createElement(e,o)}))},F=function(e,t,n){switch(e){case h.TITLE:return{toComponent:function(){return n=t.titleAttributes,(r={key:e=t.title})["data-rh"]=!0,o=M(n,r),[a.createElement(h.TITLE,o,e)];var e,n,r,o},toString:function(){return function(e,t,n,a){var r=R(n),o=L(t);return r?"<"+e+' data-rh="true" '+r+">"+I(o,a)+"</"+e+">":"<"+e+' data-rh="true">'+I(o,a)+"</"+e+">"}(e,t.title,t.titleAttributes,n)}};case"bodyAttributes":case"htmlAttributes":return{toComponent:function(){return M(t)},toString:function(){return R(t)}};default:return{toComponent:function(){return D(e,t)},toString:function(){return function(e,t,n){return t.reduce((function(t,a){var r=Object.keys(a).filter((function(e){return!("innerHTML"===e||"cssText"===e)})).reduce((function(e,t){var r=void 0===a[t]?t:t+'="'+I(a[t],n)+'"';return e?e+" "+r:r}),""),o=a.innerHTML||a.cssText||"",s=-1===P.indexOf(e);return t+"<"+e+' data-rh="true" '+r+(s?"/>":">"+o+"</"+e+">")}),"")}(e,t,n)}}}},B=function(e){var t=e.baseTag,n=e.bodyAttributes,a=e.encode,r=e.htmlAttributes,o=e.noscriptTags,s=e.styleTags,i=e.title,l=void 0===i?"":i,c=e.titleAttributes,u=e.linkTags,d=e.metaTags,f=e.scriptTags,p={toComponent:function(){},toString:function(){return""}};if(e.prioritizeSeoTags){var m=function(e){var t=e.linkTags,n=e.scriptTags,a=e.encode,r=N(e.metaTags,y),o=N(t,b),s=N(n,v);return{priorityMethods:{toComponent:function(){return[].concat(D(h.META,r.priority),D(h.LINK,o.priority),D(h.SCRIPT,s.priority))},toString:function(){return F(h.META,r.priority,a)+" "+F(h.LINK,o.priority,a)+" "+F(h.SCRIPT,s.priority,a)}},metaTags:r.default,linkTags:o.default,scriptTags:s.default}}(e);p=m.priorityMethods,u=m.linkTags,d=m.metaTags,f=m.scriptTags}return{priority:p,base:F(h.BASE,t,a),bodyAttributes:F("bodyAttributes",n,a),htmlAttributes:F("htmlAttributes",r,a),link:F(h.LINK,u,a),meta:F(h.META,d,a),noscript:F(h.NOSCRIPT,o,a),script:F(h.SCRIPT,f,a),style:F(h.STYLE,s,a),title:F(h.TITLE,{title:l,titleAttributes:c},a)}},j=[],z=function(e,t){var n=this;void 0===t&&(t="undefined"!=typeof document),this.instances=[],this.value={setHelmet:function(e){n.context.helmet=e},helmetInstances:{get:function(){return n.canUseDOM?j:n.instances},add:function(e){(n.canUseDOM?j:n.instances).push(e)},remove:function(e){var t=(n.canUseDOM?j:n.instances).indexOf(e);(n.canUseDOM?j:n.instances).splice(t,1)}}},this.context=e,this.canUseDOM=t,t||(e.helmet=B({baseTag:[],bodyAttributes:{},encodeSpecialCharacters:!0,htmlAttributes:{},linkTags:[],metaTags:[],noscriptTags:[],scriptTags:[],styleTags:[],title:"",titleAttributes:{}}))},$=a.createContext({}),U=o().shape({setHelmet:o().func,helmetInstances:o().shape({get:o().func,add:o().func,remove:o().func})}),Z="undefined"!=typeof document,H=function(e){function t(n){var a;return(a=e.call(this,n)||this).helmetData=new z(a.props.context,t.canUseDOM),a}return p(t,e),t.prototype.render=function(){return a.createElement($.Provider,{value:this.helmetData.value},this.props.children)},t}(a.Component);H.canUseDOM=Z,H.propTypes={context:o().shape({helmet:o().shape()}),children:o().node.isRequired},H.defaultProps={context:{}},H.displayName="HelmetProvider";var V=function(e,t){var n,a=document.head||document.querySelector(h.HEAD),r=a.querySelectorAll(e+"[data-rh]"),o=[].slice.call(r),s=[];return t&&t.length&&t.forEach((function(t){var a=document.createElement(e);for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&("innerHTML"===r?a.innerHTML=t.innerHTML:"cssText"===r?a.styleSheet?a.styleSheet.cssText=t.cssText:a.appendChild(document.createTextNode(t.cssText)):a.setAttribute(r,void 0===t[r]?"":t[r]));a.setAttribute("data-rh","true"),o.some((function(e,t){return n=t,a.isEqualNode(e)}))?o.splice(n,1):s.push(a)})),o.forEach((function(e){return e.parentNode.removeChild(e)})),s.forEach((function(e){return a.appendChild(e)})),{oldTags:o,newTags:s}},W=function(e,t){var n=document.getElementsByTagName(e)[0];if(n){for(var a=n.getAttribute("data-rh"),r=a?a.split(","):[],o=[].concat(r),s=Object.keys(t),i=0;i<s.length;i+=1){var l=s[i],c=t[l]||"";n.getAttribute(l)!==c&&n.setAttribute(l,c),-1===r.indexOf(l)&&r.push(l);var u=o.indexOf(l);-1!==u&&o.splice(u,1)}for(var d=o.length-1;d>=0;d-=1)n.removeAttribute(o[d]);r.length===o.length?n.removeAttribute("data-rh"):n.getAttribute("data-rh")!==s.join(",")&&n.setAttribute("data-rh",s.join(","))}},G=function(e,t){var n=e.baseTag,a=e.htmlAttributes,r=e.linkTags,o=e.metaTags,s=e.noscriptTags,i=e.onChangeClientState,l=e.scriptTags,c=e.styleTags,u=e.title,d=e.titleAttributes;W(h.BODY,e.bodyAttributes),W(h.HTML,a),function(e,t){void 0!==e&&document.title!==e&&(document.title=L(e)),W(h.TITLE,t)}(u,d);var f={baseTag:V(h.BASE,n),linkTags:V(h.LINK,r),metaTags:V(h.META,o),noscriptTags:V(h.NOSCRIPT,s),scriptTags:V(h.SCRIPT,l),styleTags:V(h.STYLE,c)},p={},m={};Object.keys(f).forEach((function(e){var t=f[e],n=t.newTags,a=t.oldTags;n.length&&(p[e]=n),a.length&&(m[e]=f[e].oldTags)})),t&&t(),i(e,p,m)},Y=null,K=function(e){function t(){for(var t,n=arguments.length,a=new Array(n),r=0;r<n;r++)a[r]=arguments[r];return(t=e.call.apply(e,[this].concat(a))||this).rendered=!1,t}p(t,e);var n=t.prototype;return n.shouldComponentUpdate=function(e){return!d()(e,this.props)},n.componentDidUpdate=function(){this.emitChange()},n.componentWillUnmount=function(){this.props.context.helmetInstances.remove(this),this.emitChange()},n.emitChange=function(){var e,t,n=this.props.context,a=n.setHelmet,r=null,o=(e=n.helmetInstances.get().map((function(e){var t=f({},e.props);return delete t.context,t})),{baseTag:T(["href"],e),bodyAttributes:C("bodyAttributes",e),defer:E(e,"defer"),encode:E(e,"encodeSpecialCharacters"),htmlAttributes:C("htmlAttributes",e),linkTags:q(h.LINK,["rel","href"],e),metaTags:q(h.META,["name","charset","http-equiv","property","itemprop"],e),noscriptTags:q(h.NOSCRIPT,["innerHTML"],e),onChangeClientState:_(e),scriptTags:q(h.SCRIPT,["src","innerHTML"],e),styleTags:q(h.STYLE,["cssText"],e),title:k(e),titleAttributes:C("titleAttributes",e),prioritizeSeoTags:A(e,"prioritizeSeoTags")});H.canUseDOM?(t=o,Y&&cancelAnimationFrame(Y),t.defer?Y=requestAnimationFrame((function(){G(t,(function(){Y=null}))})):(G(t),Y=null)):B&&(r=B(o)),a(r)},n.init=function(){this.rendered||(this.rendered=!0,this.props.context.helmetInstances.add(this),this.emitChange())},n.render=function(){return this.init(),null},t}(a.Component);K.propTypes={context:U.isRequired},K.displayName="HelmetDispatcher";var Q=["children"],X=["children"],J=function(e){function t(){return e.apply(this,arguments)||this}p(t,e);var n=t.prototype;return n.shouldComponentUpdate=function(e){return!i()(O(this.props,"helmetData"),O(e,"helmetData"))},n.mapNestedChildrenToProps=function(e,t){if(!t)return null;switch(e.type){case h.SCRIPT:case h.NOSCRIPT:return{innerHTML:t};case h.STYLE:return{cssText:t};default:throw new Error("<"+e.type+" /> elements are self-closing and can not contain children. Refer to our API for more information.")}},n.flattenArrayTypeChildren=function(e){var t,n=e.child,a=e.arrayTypeChildren;return f({},a,((t={})[n.type]=[].concat(a[n.type]||[],[f({},e.newChildProps,this.mapNestedChildrenToProps(n,e.nestedChildren))]),t))},n.mapObjectTypeChildren=function(e){var t,n,a=e.child,r=e.newProps,o=e.newChildProps,s=e.nestedChildren;switch(a.type){case h.TITLE:return f({},r,((t={})[a.type]=s,t.titleAttributes=f({},o),t));case h.BODY:return f({},r,{bodyAttributes:f({},o)});case h.HTML:return f({},r,{htmlAttributes:f({},o)});default:return f({},r,((n={})[a.type]=f({},o),n))}},n.mapArrayTypeChildrenToProps=function(e,t){var n=f({},t);return Object.keys(e).forEach((function(t){var a;n=f({},n,((a={})[t]=e[t],a))})),n},n.warnOnInvalidChildren=function(e,t){return c()(x.some((function(t){return e.type===t})),"function"==typeof e.type?"You may be attempting to nest <Helmet> components within each other, which is not allowed. Refer to our API for more information.":"Only elements types "+x.join(", ")+" are allowed. Helmet does not support rendering <"+e.type+"> elements. Refer to our API for more information."),c()(!t||"string"==typeof t||Array.isArray(t)&&!t.some((function(e){return"string"!=typeof e})),"Helmet expects a string as a child of <"+e.type+">. Did you forget to wrap your children in braces? ( <"+e.type+">{``}</"+e.type+"> ) Refer to our API for more information."),!0},n.mapChildrenToProps=function(e,t){var n=this,r={};return a.Children.forEach(e,(function(e){if(e&&e.props){var a=e.props,o=a.children,s=g(a,Q),i=Object.keys(s).reduce((function(e,t){return e[S[t]||t]=s[t],e}),{}),l=e.type;switch("symbol"==typeof l?l=l.toString():n.warnOnInvalidChildren(e,o),l){case h.FRAGMENT:t=n.mapChildrenToProps(o,t);break;case h.LINK:case h.META:case h.NOSCRIPT:case h.SCRIPT:case h.STYLE:r=n.flattenArrayTypeChildren({child:e,arrayTypeChildren:r,newChildProps:i,nestedChildren:o});break;default:t=n.mapObjectTypeChildren({child:e,newProps:t,newChildProps:i,nestedChildren:o})}}})),this.mapArrayTypeChildrenToProps(r,t)},n.render=function(){var e=this.props,t=e.children,n=g(e,X),r=f({},n),o=n.helmetData;return t&&(r=this.mapChildrenToProps(t,r)),!o||o instanceof z||(o=new z(o.context,o.instances)),o?a.createElement(K,f({},r,{context:o.value,helmetData:void 0})):a.createElement($.Consumer,null,(function(e){return a.createElement(K,f({},r,{context:e}))}))},t}(a.Component);J.propTypes={base:o().object,bodyAttributes:o().object,children:o().oneOfType([o().arrayOf(o().node),o().node]),defaultTitle:o().string,defer:o().bool,encodeSpecialCharacters:o().bool,htmlAttributes:o().object,link:o().arrayOf(o().object),meta:o().arrayOf(o().object),noscript:o().arrayOf(o().object),onChangeClientState:o().func,script:o().arrayOf(o().object),style:o().arrayOf(o().object),title:o().string,titleAttributes:o().object,titleTemplate:o().string,prioritizeSeoTags:o().bool,helmetData:o().object},J.defaultProps={defer:!0,encodeSpecialCharacters:!0,prioritizeSeoTags:!1},J.displayName="Helmet"},9921:(e,t)=>{"use strict";var n="function"==typeof Symbol&&Symbol.for,a=n?Symbol.for("react.element"):60103,r=n?Symbol.for("react.portal"):60106,o=n?Symbol.for("react.fragment"):60107,s=n?Symbol.for("react.strict_mode"):60108,i=n?Symbol.for("react.profiler"):60114,l=n?Symbol.for("react.provider"):60109,c=n?Symbol.for("react.context"):60110,u=n?Symbol.for("react.async_mode"):60111,d=n?Symbol.for("react.concurrent_mode"):60111,f=n?Symbol.for("react.forward_ref"):60112,p=n?Symbol.for("react.suspense"):60113,m=n?Symbol.for("react.suspense_list"):60120,g=n?Symbol.for("react.memo"):60115,h=n?Symbol.for("react.lazy"):60116,b=n?Symbol.for("react.block"):60121,v=n?Symbol.for("react.fundamental"):60117,y=n?Symbol.for("react.responder"):60118,x=n?Symbol.for("react.scope"):60119;function w(e){if("object"==typeof e&&null!==e){var t=e.$$typeof;switch(t){case a:switch(e=e.type){case u:case d:case o:case i:case s:case p:return e;default:switch(e=e&&e.$$typeof){case c:case f:case h:case g:case l:return e;default:return t}}case r:return t}}}function S(e){return w(e)===d}t.AsyncMode=u,t.ConcurrentMode=d,t.ContextConsumer=c,t.ContextProvider=l,t.Element=a,t.ForwardRef=f,t.Fragment=o,t.Lazy=h,t.Memo=g,t.Portal=r,t.Profiler=i,t.StrictMode=s,t.Suspense=p,t.isAsyncMode=function(e){return S(e)||w(e)===u},t.isConcurrentMode=S,t.isContextConsumer=function(e){return w(e)===c},t.isContextProvider=function(e){return w(e)===l},t.isElement=function(e){return"object"==typeof e&&null!==e&&e.$$typeof===a},t.isForwardRef=function(e){return w(e)===f},t.isFragment=function(e){return w(e)===o},t.isLazy=function(e){return w(e)===h},t.isMemo=function(e){return w(e)===g},t.isPortal=function(e){return w(e)===r},t.isProfiler=function(e){return w(e)===i},t.isStrictMode=function(e){return w(e)===s},t.isSuspense=function(e){return w(e)===p},t.isValidElementType=function(e){return"string"==typeof e||"function"==typeof e||e===o||e===d||e===i||e===s||e===p||e===m||"object"==typeof e&&null!==e&&(e.$$typeof===h||e.$$typeof===g||e.$$typeof===l||e.$$typeof===c||e.$$typeof===f||e.$$typeof===v||e.$$typeof===y||e.$$typeof===x||e.$$typeof===b)},t.typeOf=w},9864:(e,t,n)=>{"use strict";e.exports=n(9921)},8356:(e,t,n)=>{"use strict";function a(e,t){e.prototype=Object.create(t.prototype),e.prototype.constructor=e,e.__proto__=t}function r(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function s(){return s=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var a in n)Object.prototype.hasOwnProperty.call(n,a)&&(e[a]=n[a])}return e},s.apply(this,arguments)}var i=n(7294),l=n(5697),c=[],u=[];function d(e){var t=e(),n={loading:!0,loaded:null,error:null};return n.promise=t.then((function(e){return n.loading=!1,n.loaded=e,e})).catch((function(e){throw n.loading=!1,n.error=e,e})),n}function f(e){var t={loading:!1,loaded:{},error:null},n=[];try{Object.keys(e).forEach((function(a){var r=d(e[a]);r.loading?t.loading=!0:(t.loaded[a]=r.loaded,t.error=r.error),n.push(r.promise),r.promise.then((function(e){t.loaded[a]=e})).catch((function(e){t.error=e}))}))}catch(a){t.error=a}return t.promise=Promise.all(n).then((function(e){return t.loading=!1,e})).catch((function(e){throw t.loading=!1,e})),t}function p(e,t){return i.createElement((n=e)&&n.__esModule?n.default:n,t);var n}function m(e,t){var d,f;if(!t.loading)throw new Error("react-loadable requires a `loading` component");var m=s({loader:null,loading:null,delay:200,timeout:null,render:p,webpack:null,modules:null},t),g=null;function h(){return g||(g=e(m.loader)),g.promise}return c.push(h),"function"==typeof m.webpack&&u.push((function(){if((0,m.webpack)().every((function(e){return void 0!==e&&void 0!==n.m[e]})))return h()})),f=d=function(t){function n(n){var a;return o(r(r(a=t.call(this,n)||this)),"retry",(function(){a.setState({error:null,loading:!0,timedOut:!1}),g=e(m.loader),a._loadModule()})),h(),a.state={error:g.error,pastDelay:!1,timedOut:!1,loading:g.loading,loaded:g.loaded},a}a(n,t),n.preload=function(){return h()};var s=n.prototype;return s.UNSAFE_componentWillMount=function(){this._loadModule()},s.componentDidMount=function(){this._mounted=!0},s._loadModule=function(){var e=this;if(this.context.loadable&&Array.isArray(m.modules)&&m.modules.forEach((function(t){e.context.loadable.report(t)})),g.loading){var t=function(t){e._mounted&&e.setState(t)};"number"==typeof m.delay&&(0===m.delay?this.setState({pastDelay:!0}):this._delay=setTimeout((function(){t({pastDelay:!0})}),m.delay)),"number"==typeof m.timeout&&(this._timeout=setTimeout((function(){t({timedOut:!0})}),m.timeout));var n=function(){t({error:g.error,loaded:g.loaded,loading:g.loading}),e._clearTimeouts()};g.promise.then((function(){return n(),null})).catch((function(e){return n(),null}))}},s.componentWillUnmount=function(){this._mounted=!1,this._clearTimeouts()},s._clearTimeouts=function(){clearTimeout(this._delay),clearTimeout(this._timeout)},s.render=function(){return this.state.loading||this.state.error?i.createElement(m.loading,{isLoading:this.state.loading,pastDelay:this.state.pastDelay,timedOut:this.state.timedOut,error:this.state.error,retry:this.retry}):this.state.loaded?m.render(this.state.loaded,this.props):null},n}(i.Component),o(d,"contextTypes",{loadable:l.shape({report:l.func.isRequired})}),f}function g(e){return m(d,e)}g.Map=function(e){if("function"!=typeof e.render)throw new Error("LoadableMap requires a `render(loaded, props)` function");return m(f,e)};var h=function(e){function t(){return e.apply(this,arguments)||this}a(t,e);var n=t.prototype;return n.getChildContext=function(){return{loadable:{report:this.props.report}}},n.render=function(){return i.Children.only(this.props.children)},t}(i.Component);function b(e){for(var t=[];e.length;){var n=e.pop();t.push(n())}return Promise.all(t).then((function(){if(e.length)return b(e)}))}o(h,"propTypes",{report:l.func.isRequired}),o(h,"childContextTypes",{loadable:l.shape({report:l.func.isRequired}).isRequired}),g.Capture=h,g.preloadAll=function(){return new Promise((function(e,t){b(c).then(e,t)}))},g.preloadReady=function(){return new Promise((function(e,t){b(u).then(e,e)}))},e.exports=g},8790:(e,t,n)=>{"use strict";n.d(t,{H:()=>i,f:()=>s});var a=n(6550),r=n(7462),o=n(7294);function s(e,t,n){return void 0===n&&(n=[]),e.some((function(e){var r=e.path?(0,a.LX)(t,e):n.length?n[n.length-1].match:a.F0.computeRootMatch(t);return r&&(n.push({route:e,match:r}),e.routes&&s(e.routes,t,n)),r})),n}function i(e,t,n){return void 0===t&&(t={}),void 0===n&&(n={}),e?o.createElement(a.rs,n,e.map((function(e,n){return o.createElement(a.AW,{key:e.key||n,path:e.path,exact:e.exact,strict:e.strict,render:function(n){return e.render?e.render((0,r.Z)({},n,{},t,{route:e})):o.createElement(e.component,(0,r.Z)({},n,t,{route:e}))}})}))):null}},3727:(e,t,n)=>{"use strict";n.d(t,{OL:()=>y,VK:()=>u,rU:()=>h});var a=n(6550),r=n(5068),o=n(7294),s=n(9318),i=n(7462),l=n(3366),c=n(8776),u=function(e){function t(){for(var t,n=arguments.length,a=new Array(n),r=0;r<n;r++)a[r]=arguments[r];return(t=e.call.apply(e,[this].concat(a))||this).history=(0,s.lX)(t.props),t}return(0,r.Z)(t,e),t.prototype.render=function(){return o.createElement(a.F0,{history:this.history,children:this.props.children})},t}(o.Component);o.Component;var d=function(e,t){return"function"==typeof e?e(t):e},f=function(e,t){return"string"==typeof e?(0,s.ob)(e,null,null,t):e},p=function(e){return e},m=o.forwardRef;void 0===m&&(m=p);var g=m((function(e,t){var n=e.innerRef,a=e.navigate,r=e.onClick,s=(0,l.Z)(e,["innerRef","navigate","onClick"]),c=s.target,u=(0,i.Z)({},s,{onClick:function(e){try{r&&r(e)}catch(t){throw e.preventDefault(),t}e.defaultPrevented||0!==e.button||c&&"_self"!==c||function(e){return!!(e.metaKey||e.altKey||e.ctrlKey||e.shiftKey)}(e)||(e.preventDefault(),a())}});return u.ref=p!==m&&t||n,o.createElement("a",u)}));var h=m((function(e,t){var n=e.component,r=void 0===n?g:n,u=e.replace,h=e.to,b=e.innerRef,v=(0,l.Z)(e,["component","replace","to","innerRef"]);return o.createElement(a.s6.Consumer,null,(function(e){e||(0,c.Z)(!1);var n=e.history,a=f(d(h,e.location),e.location),l=a?n.createHref(a):"",g=(0,i.Z)({},v,{href:l,navigate:function(){var t=d(h,e.location),a=(0,s.Ep)(e.location)===(0,s.Ep)(f(t));(u||a?n.replace:n.push)(t)}});return p!==m?g.ref=t||b:g.innerRef=b,o.createElement(r,g)}))})),b=function(e){return e},v=o.forwardRef;void 0===v&&(v=b);var y=v((function(e,t){var n=e["aria-current"],r=void 0===n?"page":n,s=e.activeClassName,u=void 0===s?"active":s,p=e.activeStyle,m=e.className,g=e.exact,y=e.isActive,x=e.location,w=e.sensitive,S=e.strict,E=e.style,k=e.to,_=e.innerRef,C=(0,l.Z)(e,["aria-current","activeClassName","activeStyle","className","exact","isActive","location","sensitive","strict","style","to","innerRef"]);return o.createElement(a.s6.Consumer,null,(function(e){e||(0,c.Z)(!1);var n=x||e.location,s=f(d(k,n),n),l=s.pathname,T=l&&l.replace(/([.+*?=^!:${}()[\]|/\\])/g,"\\$1"),q=T?(0,a.LX)(n.pathname,{path:T,exact:g,sensitive:w,strict:S}):null,A=!!(y?y(q,n):q),L="function"==typeof m?m(A):m,N="function"==typeof E?E(A):E;A&&(L=function(){for(var e=arguments.length,t=new Array(e),n=0;n<e;n++)t[n]=arguments[n];return t.filter((function(e){return e})).join(" ")}(L,u),N=(0,i.Z)({},N,p));var O=(0,i.Z)({"aria-current":A&&r||null,className:L,style:N,to:s},C);return b!==v?O.ref=t||_:O.innerRef=_,o.createElement(h,O)}))}))},6550:(e,t,n)=>{"use strict";n.d(t,{AW:()=>k,F0:()=>y,LX:()=>E,TH:()=>P,k6:()=>O,rs:()=>L,s6:()=>v});var a=n(5068),r=n(7294),o=n(5697),s=n.n(o),i=n(9318),l=n(8776),c=n(7462),u=n(9658),d=n.n(u),f=(n(9864),n(3366)),p=(n(8679),1073741823),m="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:void 0!==n.g?n.g:{};var g=r.createContext||function(e,t){var n,o,i="__create-react-context-"+function(){var e="__global_unique_id__";return m[e]=(m[e]||0)+1}()+"__",l=function(e){function n(){for(var t,n,a,r=arguments.length,o=new Array(r),s=0;s<r;s++)o[s]=arguments[s];return(t=e.call.apply(e,[this].concat(o))||this).emitter=(n=t.props.value,a=[],{on:function(e){a.push(e)},off:function(e){a=a.filter((function(t){return t!==e}))},get:function(){return n},set:function(e,t){n=e,a.forEach((function(e){return e(n,t)}))}}),t}(0,a.Z)(n,e);var r=n.prototype;return r.getChildContext=function(){var e;return(e={})[i]=this.emitter,e},r.componentWillReceiveProps=function(e){if(this.props.value!==e.value){var n,a=this.props.value,r=e.value;((o=a)===(s=r)?0!==o||1/o==1/s:o!=o&&s!=s)?n=0:(n="function"==typeof t?t(a,r):p,0!==(n|=0)&&this.emitter.set(e.value,n))}var o,s},r.render=function(){return this.props.children},n}(r.Component);l.childContextTypes=((n={})[i]=s().object.isRequired,n);var c=function(t){function n(){for(var e,n=arguments.length,a=new Array(n),r=0;r<n;r++)a[r]=arguments[r];return(e=t.call.apply(t,[this].concat(a))||this).observedBits=void 0,e.state={value:e.getValue()},e.onUpdate=function(t,n){0!=((0|e.observedBits)&n)&&e.setState({value:e.getValue()})},e}(0,a.Z)(n,t);var r=n.prototype;return r.componentWillReceiveProps=function(e){var t=e.observedBits;this.observedBits=null==t?p:t},r.componentDidMount=function(){this.context[i]&&this.context[i].on(this.onUpdate);var e=this.props.observedBits;this.observedBits=null==e?p:e},r.componentWillUnmount=function(){this.context[i]&&this.context[i].off(this.onUpdate)},r.getValue=function(){return this.context[i]?this.context[i].get():e},r.render=function(){return(e=this.props.children,Array.isArray(e)?e[0]:e)(this.state.value);var e},n}(r.Component);return c.contextTypes=((o={})[i]=s().object,o),{Provider:l,Consumer:c}},h=function(e){var t=g();return t.displayName=e,t},b=h("Router-History"),v=h("Router"),y=function(e){function t(t){var n;return(n=e.call(this,t)||this).state={location:t.history.location},n._isMounted=!1,n._pendingLocation=null,t.staticContext||(n.unlisten=t.history.listen((function(e){n._pendingLocation=e}))),n}(0,a.Z)(t,e),t.computeRootMatch=function(e){return{path:"/",url:"/",params:{},isExact:"/"===e}};var n=t.prototype;return n.componentDidMount=function(){var e=this;this._isMounted=!0,this.unlisten&&this.unlisten(),this.props.staticContext||(this.unlisten=this.props.history.listen((function(t){e._isMounted&&e.setState({location:t})}))),this._pendingLocation&&this.setState({location:this._pendingLocation})},n.componentWillUnmount=function(){this.unlisten&&(this.unlisten(),this._isMounted=!1,this._pendingLocation=null)},n.render=function(){return r.createElement(v.Provider,{value:{history:this.props.history,location:this.state.location,match:t.computeRootMatch(this.state.location.pathname),staticContext:this.props.staticContext}},r.createElement(b.Provider,{children:this.props.children||null,value:this.props.history}))},t}(r.Component);r.Component;r.Component;var x={},w=1e4,S=0;function E(e,t){void 0===t&&(t={}),("string"==typeof t||Array.isArray(t))&&(t={path:t});var n=t,a=n.path,r=n.exact,o=void 0!==r&&r,s=n.strict,i=void 0!==s&&s,l=n.sensitive,c=void 0!==l&&l;return[].concat(a).reduce((function(t,n){if(!n&&""!==n)return null;if(t)return t;var a=function(e,t){var n=""+t.end+t.strict+t.sensitive,a=x[n]||(x[n]={});if(a[e])return a[e];var r=[],o={regexp:d()(e,r,t),keys:r};return S<w&&(a[e]=o,S++),o}(n,{end:o,strict:i,sensitive:c}),r=a.regexp,s=a.keys,l=r.exec(e);if(!l)return null;var u=l[0],f=l.slice(1),p=e===u;return o&&!p?null:{path:n,url:"/"===n&&""===u?"/":u,isExact:p,params:s.reduce((function(e,t,n){return e[t.name]=f[n],e}),{})}}),null)}var k=function(e){function t(){return e.apply(this,arguments)||this}return(0,a.Z)(t,e),t.prototype.render=function(){var e=this;return r.createElement(v.Consumer,null,(function(t){t||(0,l.Z)(!1);var n=e.props.location||t.location,a=e.props.computedMatch?e.props.computedMatch:e.props.path?E(n.pathname,e.props):t.match,o=(0,c.Z)({},t,{location:n,match:a}),s=e.props,i=s.children,u=s.component,d=s.render;return Array.isArray(i)&&function(e){return 0===r.Children.count(e)}(i)&&(i=null),r.createElement(v.Provider,{value:o},o.match?i?"function"==typeof i?i(o):i:u?r.createElement(u,o):d?d(o):null:"function"==typeof i?i(o):null)}))},t}(r.Component);function _(e){return"/"===e.charAt(0)?e:"/"+e}function C(e,t){if(!e)return t;var n=_(e);return 0!==t.pathname.indexOf(n)?t:(0,c.Z)({},t,{pathname:t.pathname.substr(n.length)})}function T(e){return"string"==typeof e?e:(0,i.Ep)(e)}function q(e){return function(){(0,l.Z)(!1)}}function A(){}r.Component;var L=function(e){function t(){return e.apply(this,arguments)||this}return(0,a.Z)(t,e),t.prototype.render=function(){var e=this;return r.createElement(v.Consumer,null,(function(t){t||(0,l.Z)(!1);var n,a,o=e.props.location||t.location;return r.Children.forEach(e.props.children,(function(e){if(null==a&&r.isValidElement(e)){n=e;var s=e.props.path||e.props.from;a=s?E(o.pathname,(0,c.Z)({},e.props,{path:s})):t.match}})),a?r.cloneElement(n,{location:o,computedMatch:a}):null}))},t}(r.Component);var N=r.useContext;function O(){return N(b)}function P(){return N(v).location}},9658:(e,t,n)=>{var a=n(5826);e.exports=p,e.exports.parse=o,e.exports.compile=function(e,t){return i(o(e,t),t)},e.exports.tokensToFunction=i,e.exports.tokensToRegExp=f;var r=new RegExp(["(\\\\.)","([\\/.])?(?:(?:\\:(\\w+)(?:\\(((?:\\\\.|[^\\\\()])+)\\))?|\\(((?:\\\\.|[^\\\\()])+)\\))([+*?])?|(\\*))"].join("|"),"g");function o(e,t){for(var n,a=[],o=0,s=0,i="",u=t&&t.delimiter||"/";null!=(n=r.exec(e));){var d=n[0],f=n[1],p=n.index;if(i+=e.slice(s,p),s=p+d.length,f)i+=f[1];else{var m=e[s],g=n[2],h=n[3],b=n[4],v=n[5],y=n[6],x=n[7];i&&(a.push(i),i="");var w=null!=g&&null!=m&&m!==g,S="+"===y||"*"===y,E="?"===y||"*"===y,k=n[2]||u,_=b||v;a.push({name:h||o++,prefix:g||"",delimiter:k,optional:E,repeat:S,partial:w,asterisk:!!x,pattern:_?c(_):x?".*":"[^"+l(k)+"]+?"})}}return s<e.length&&(i+=e.substr(s)),i&&a.push(i),a}function s(e){return encodeURI(e).replace(/[\/?#]/g,(function(e){return"%"+e.charCodeAt(0).toString(16).toUpperCase()}))}function i(e,t){for(var n=new Array(e.length),r=0;r<e.length;r++)"object"==typeof e[r]&&(n[r]=new RegExp("^(?:"+e[r].pattern+")$",d(t)));return function(t,r){for(var o="",i=t||{},l=(r||{}).pretty?s:encodeURIComponent,c=0;c<e.length;c++){var u=e[c];if("string"!=typeof u){var d,f=i[u.name];if(null==f){if(u.optional){u.partial&&(o+=u.prefix);continue}throw new TypeError('Expected "'+u.name+'" to be defined')}if(a(f)){if(!u.repeat)throw new TypeError('Expected "'+u.name+'" to not repeat, but received `'+JSON.stringify(f)+"`");if(0===f.length){if(u.optional)continue;throw new TypeError('Expected "'+u.name+'" to not be empty')}for(var p=0;p<f.length;p++){if(d=l(f[p]),!n[c].test(d))throw new TypeError('Expected all "'+u.name+'" to match "'+u.pattern+'", but received `'+JSON.stringify(d)+"`");o+=(0===p?u.prefix:u.delimiter)+d}}else{if(d=u.asterisk?encodeURI(f).replace(/[?#]/g,(function(e){return"%"+e.charCodeAt(0).toString(16).toUpperCase()})):l(f),!n[c].test(d))throw new TypeError('Expected "'+u.name+'" to match "'+u.pattern+'", but received "'+d+'"');o+=u.prefix+d}}else o+=u}return o}}function l(e){return e.replace(/([.+*?=^!:${}()[\]|\/\\])/g,"\\$1")}function c(e){return e.replace(/([=!:$\/()])/g,"\\$1")}function u(e,t){return e.keys=t,e}function d(e){return e&&e.sensitive?"":"i"}function f(e,t,n){a(t)||(n=t||n,t=[]);for(var r=(n=n||{}).strict,o=!1!==n.end,s="",i=0;i<e.length;i++){var c=e[i];if("string"==typeof c)s+=l(c);else{var f=l(c.prefix),p="(?:"+c.pattern+")";t.push(c),c.repeat&&(p+="(?:"+f+p+")*"),s+=p=c.optional?c.partial?f+"("+p+")?":"(?:"+f+"("+p+"))?":f+"("+p+")"}}var m=l(n.delimiter||"/"),g=s.slice(-m.length)===m;return r||(s=(g?s.slice(0,-m.length):s)+"(?:"+m+"(?=$))?"),s+=o?"$":r&&g?"":"(?="+m+"|$)",u(new RegExp("^"+s,d(n)),t)}function p(e,t,n){return a(t)||(n=t||n,t=[]),n=n||{},e instanceof RegExp?function(e,t){var n=e.source.match(/\((?!\?)/g);if(n)for(var a=0;a<n.length;a++)t.push({name:a,prefix:null,delimiter:null,optional:!1,repeat:!1,partial:!1,asterisk:!1,pattern:null});return u(e,t)}(e,t):a(e)?function(e,t,n){for(var a=[],r=0;r<e.length;r++)a.push(p(e[r],t,n).source);return u(new RegExp("(?:"+a.join("|")+")",d(n)),t)}(e,t,n):function(e,t,n){return f(o(e,n),t,n)}(e,t,n)}},2408:(e,t,n)=>{"use strict";var a=n(7418),r=60103,o=60106;t.Fragment=60107,t.StrictMode=60108,t.Profiler=60114;var s=60109,i=60110,l=60112;t.Suspense=60113;var c=60115,u=60116;if("function"==typeof Symbol&&Symbol.for){var d=Symbol.for;r=d("react.element"),o=d("react.portal"),t.Fragment=d("react.fragment"),t.StrictMode=d("react.strict_mode"),t.Profiler=d("react.profiler"),s=d("react.provider"),i=d("react.context"),l=d("react.forward_ref"),t.Suspense=d("react.suspense"),c=d("react.memo"),u=d("react.lazy")}var f="function"==typeof Symbol&&Symbol.iterator;function p(e){for(var t="https://reactjs.org/docs/error-decoder.html?invariant="+e,n=1;n<arguments.length;n++)t+="&args[]="+encodeURIComponent(arguments[n]);return"Minified React error #"+e+"; visit "+t+" for the full message or use the non-minified dev environment for full errors and additional helpful warnings."}var m={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},g={};function h(e,t,n){this.props=e,this.context=t,this.refs=g,this.updater=n||m}function b(){}function v(e,t,n){this.props=e,this.context=t,this.refs=g,this.updater=n||m}h.prototype.isReactComponent={},h.prototype.setState=function(e,t){if("object"!=typeof e&&"function"!=typeof e&&null!=e)throw Error(p(85));this.updater.enqueueSetState(this,e,t,"setState")},h.prototype.forceUpdate=function(e){this.updater.enqueueForceUpdate(this,e,"forceUpdate")},b.prototype=h.prototype;var y=v.prototype=new b;y.constructor=v,a(y,h.prototype),y.isPureReactComponent=!0;var x={current:null},w=Object.prototype.hasOwnProperty,S={key:!0,ref:!0,__self:!0,__source:!0};function E(e,t,n){var a,o={},s=null,i=null;if(null!=t)for(a in void 0!==t.ref&&(i=t.ref),void 0!==t.key&&(s=""+t.key),t)w.call(t,a)&&!S.hasOwnProperty(a)&&(o[a]=t[a]);var l=arguments.length-2;if(1===l)o.children=n;else if(1<l){for(var c=Array(l),u=0;u<l;u++)c[u]=arguments[u+2];o.children=c}if(e&&e.defaultProps)for(a in l=e.defaultProps)void 0===o[a]&&(o[a]=l[a]);return{$$typeof:r,type:e,key:s,ref:i,props:o,_owner:x.current}}function k(e){return"object"==typeof e&&null!==e&&e.$$typeof===r}var _=/\/+/g;function C(e,t){return"object"==typeof e&&null!==e&&null!=e.key?function(e){var t={"=":"=0",":":"=2"};return"$"+e.replace(/[=:]/g,(function(e){return t[e]}))}(""+e.key):t.toString(36)}function T(e,t,n,a,s){var i=typeof e;"undefined"!==i&&"boolean"!==i||(e=null);var l=!1;if(null===e)l=!0;else switch(i){case"string":case"number":l=!0;break;case"object":switch(e.$$typeof){case r:case o:l=!0}}if(l)return s=s(l=e),e=""===a?"."+C(l,0):a,Array.isArray(s)?(n="",null!=e&&(n=e.replace(_,"$&/")+"/"),T(s,t,n,"",(function(e){return e}))):null!=s&&(k(s)&&(s=function(e,t){return{$$typeof:r,type:e.type,key:t,ref:e.ref,props:e.props,_owner:e._owner}}(s,n+(!s.key||l&&l.key===s.key?"":(""+s.key).replace(_,"$&/")+"/")+e)),t.push(s)),1;if(l=0,a=""===a?".":a+":",Array.isArray(e))for(var c=0;c<e.length;c++){var u=a+C(i=e[c],c);l+=T(i,t,n,u,s)}else if(u=function(e){return null===e||"object"!=typeof e?null:"function"==typeof(e=f&&e[f]||e["@@iterator"])?e:null}(e),"function"==typeof u)for(e=u.call(e),c=0;!(i=e.next()).done;)l+=T(i=i.value,t,n,u=a+C(i,c++),s);else if("object"===i)throw t=""+e,Error(p(31,"[object Object]"===t?"object with keys {"+Object.keys(e).join(", ")+"}":t));return l}function q(e,t,n){if(null==e)return e;var a=[],r=0;return T(e,a,"","",(function(e){return t.call(n,e,r++)})),a}function A(e){if(-1===e._status){var t=e._result;t=t(),e._status=0,e._result=t,t.then((function(t){0===e._status&&(t=t.default,e._status=1,e._result=t)}),(function(t){0===e._status&&(e._status=2,e._result=t)}))}if(1===e._status)return e._result;throw e._result}var L={current:null};function N(){var e=L.current;if(null===e)throw Error(p(321));return e}var O={ReactCurrentDispatcher:L,ReactCurrentBatchConfig:{transition:0},ReactCurrentOwner:x,IsSomeRendererActing:{current:!1},assign:a};t.Children={map:q,forEach:function(e,t,n){q(e,(function(){t.apply(this,arguments)}),n)},count:function(e){var t=0;return q(e,(function(){t++})),t},toArray:function(e){return q(e,(function(e){return e}))||[]},only:function(e){if(!k(e))throw Error(p(143));return e}},t.Component=h,t.PureComponent=v,t.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED=O,t.cloneElement=function(e,t,n){if(null==e)throw Error(p(267,e));var o=a({},e.props),s=e.key,i=e.ref,l=e._owner;if(null!=t){if(void 0!==t.ref&&(i=t.ref,l=x.current),void 0!==t.key&&(s=""+t.key),e.type&&e.type.defaultProps)var c=e.type.defaultProps;for(u in t)w.call(t,u)&&!S.hasOwnProperty(u)&&(o[u]=void 0===t[u]&&void 0!==c?c[u]:t[u])}var u=arguments.length-2;if(1===u)o.children=n;else if(1<u){c=Array(u);for(var d=0;d<u;d++)c[d]=arguments[d+2];o.children=c}return{$$typeof:r,type:e.type,key:s,ref:i,props:o,_owner:l}},t.createContext=function(e,t){return void 0===t&&(t=null),(e={$$typeof:i,_calculateChangedBits:t,_currentValue:e,_currentValue2:e,_threadCount:0,Provider:null,Consumer:null}).Provider={$$typeof:s,_context:e},e.Consumer=e},t.createElement=E,t.createFactory=function(e){var t=E.bind(null,e);return t.type=e,t},t.createRef=function(){return{current:null}},t.forwardRef=function(e){return{$$typeof:l,render:e}},t.isValidElement=k,t.lazy=function(e){return{$$typeof:u,_payload:{_status:-1,_result:e},_init:A}},t.memo=function(e,t){return{$$typeof:c,type:e,compare:void 0===t?null:t}},t.useCallback=function(e,t){return N().useCallback(e,t)},t.useContext=function(e,t){return N().useContext(e,t)},t.useDebugValue=function(){},t.useEffect=function(e,t){return N().useEffect(e,t)},t.useImperativeHandle=function(e,t,n){return N().useImperativeHandle(e,t,n)},t.useLayoutEffect=function(e,t){return N().useLayoutEffect(e,t)},t.useMemo=function(e,t){return N().useMemo(e,t)},t.useReducer=function(e,t,n){return N().useReducer(e,t,n)},t.useRef=function(e){return N().useRef(e)},t.useState=function(e){return N().useState(e)},t.version="17.0.2"},7294:(e,t,n)=>{"use strict";e.exports=n(2408)},53:(e,t)=>{"use strict";var n,a,r,o;if("object"==typeof performance&&"function"==typeof performance.now){var s=performance;t.unstable_now=function(){return s.now()}}else{var i=Date,l=i.now();t.unstable_now=function(){return i.now()-l}}if("undefined"==typeof window||"function"!=typeof MessageChannel){var c=null,u=null,d=function(){if(null!==c)try{var e=t.unstable_now();c(!0,e),c=null}catch(n){throw setTimeout(d,0),n}};n=function(e){null!==c?setTimeout(n,0,e):(c=e,setTimeout(d,0))},a=function(e,t){u=setTimeout(e,t)},r=function(){clearTimeout(u)},t.unstable_shouldYield=function(){return!1},o=t.unstable_forceFrameRate=function(){}}else{var f=window.setTimeout,p=window.clearTimeout;if("undefined"!=typeof console){var m=window.cancelAnimationFrame;"function"!=typeof window.requestAnimationFrame&&console.error("This browser doesn't support requestAnimationFrame. Make sure that you load a polyfill in older browsers. https://reactjs.org/link/react-polyfills"),"function"!=typeof m&&console.error("This browser doesn't support cancelAnimationFrame. Make sure that you load a polyfill in older browsers. https://reactjs.org/link/react-polyfills")}var g=!1,h=null,b=-1,v=5,y=0;t.unstable_shouldYield=function(){return t.unstable_now()>=y},o=function(){},t.unstable_forceFrameRate=function(e){0>e||125<e?console.error("forceFrameRate takes a positive int between 0 and 125, forcing frame rates higher than 125 fps is not supported"):v=0<e?Math.floor(1e3/e):5};var x=new MessageChannel,w=x.port2;x.port1.onmessage=function(){if(null!==h){var e=t.unstable_now();y=e+v;try{h(!0,e)?w.postMessage(null):(g=!1,h=null)}catch(n){throw w.postMessage(null),n}}else g=!1},n=function(e){h=e,g||(g=!0,w.postMessage(null))},a=function(e,n){b=f((function(){e(t.unstable_now())}),n)},r=function(){p(b),b=-1}}function S(e,t){var n=e.length;e.push(t);e:for(;;){var a=n-1>>>1,r=e[a];if(!(void 0!==r&&0<_(r,t)))break e;e[a]=t,e[n]=r,n=a}}function E(e){return void 0===(e=e[0])?null:e}function k(e){var t=e[0];if(void 0!==t){var n=e.pop();if(n!==t){e[0]=n;e:for(var a=0,r=e.length;a<r;){var o=2*(a+1)-1,s=e[o],i=o+1,l=e[i];if(void 0!==s&&0>_(s,n))void 0!==l&&0>_(l,s)?(e[a]=l,e[i]=n,a=i):(e[a]=s,e[o]=n,a=o);else{if(!(void 0!==l&&0>_(l,n)))break e;e[a]=l,e[i]=n,a=i}}}return t}return null}function _(e,t){var n=e.sortIndex-t.sortIndex;return 0!==n?n:e.id-t.id}var C=[],T=[],q=1,A=null,L=3,N=!1,O=!1,P=!1;function I(e){for(var t=E(T);null!==t;){if(null===t.callback)k(T);else{if(!(t.startTime<=e))break;k(T),t.sortIndex=t.expirationTime,S(C,t)}t=E(T)}}function R(e){if(P=!1,I(e),!O)if(null!==E(C))O=!0,n(M);else{var t=E(T);null!==t&&a(R,t.startTime-e)}}function M(e,n){O=!1,P&&(P=!1,r()),N=!0;var o=L;try{for(I(n),A=E(C);null!==A&&(!(A.expirationTime>n)||e&&!t.unstable_shouldYield());){var s=A.callback;if("function"==typeof s){A.callback=null,L=A.priorityLevel;var i=s(A.expirationTime<=n);n=t.unstable_now(),"function"==typeof i?A.callback=i:A===E(C)&&k(C),I(n)}else k(C);A=E(C)}if(null!==A)var l=!0;else{var c=E(T);null!==c&&a(R,c.startTime-n),l=!1}return l}finally{A=null,L=o,N=!1}}var D=o;t.unstable_IdlePriority=5,t.unstable_ImmediatePriority=1,t.unstable_LowPriority=4,t.unstable_NormalPriority=3,t.unstable_Profiling=null,t.unstable_UserBlockingPriority=2,t.unstable_cancelCallback=function(e){e.callback=null},t.unstable_continueExecution=function(){O||N||(O=!0,n(M))},t.unstable_getCurrentPriorityLevel=function(){return L},t.unstable_getFirstCallbackNode=function(){return E(C)},t.unstable_next=function(e){switch(L){case 1:case 2:case 3:var t=3;break;default:t=L}var n=L;L=t;try{return e()}finally{L=n}},t.unstable_pauseExecution=function(){},t.unstable_requestPaint=D,t.unstable_runWithPriority=function(e,t){switch(e){case 1:case 2:case 3:case 4:case 5:break;default:e=3}var n=L;L=e;try{return t()}finally{L=n}},t.unstable_scheduleCallback=function(e,o,s){var i=t.unstable_now();switch("object"==typeof s&&null!==s?s="number"==typeof(s=s.delay)&&0<s?i+s:i:s=i,e){case 1:var l=-1;break;case 2:l=250;break;case 5:l=1073741823;break;case 4:l=1e4;break;default:l=5e3}return e={id:q++,callback:o,priorityLevel:e,startTime:s,expirationTime:l=s+l,sortIndex:-1},s>i?(e.sortIndex=s,S(T,e),null===E(C)&&e===E(T)&&(P?r():P=!0,a(R,s-i))):(e.sortIndex=l,S(C,e),O||N||(O=!0,n(M))),e},t.unstable_wrapCallback=function(e){var t=L;return function(){var n=L;L=t;try{return e.apply(this,arguments)}finally{L=n}}}},3840:(e,t,n)=>{"use strict";e.exports=n(53)},6774:e=>{e.exports=function(e,t,n,a){var r=n?n.call(a,e,t):void 0;if(void 0!==r)return!!r;if(e===t)return!0;if("object"!=typeof e||!e||"object"!=typeof t||!t)return!1;var o=Object.keys(e),s=Object.keys(t);if(o.length!==s.length)return!1;for(var i=Object.prototype.hasOwnProperty.bind(t),l=0;l<o.length;l++){var c=o[l];if(!i(c))return!1;var u=e[c],d=t[c];if(!1===(r=n?n.call(a,u,d,c):void 0)||void 0===r&&u!==d)return!1}return!0}},3250:(e,t,n)=>{"use strict";var a=n(7294);var r="function"==typeof Object.is?Object.is:function(e,t){return e===t&&(0!==e||1/e==1/t)||e!=e&&t!=t},o=a.useState,s=a.useEffect,i=a.useLayoutEffect,l=a.useDebugValue;function c(e){var t=e.getSnapshot;e=e.value;try{var n=t();return!r(e,n)}catch(a){return!0}}var u="undefined"==typeof window||void 0===window.document||void 0===window.document.createElement?function(e,t){return t()}:function(e,t){var n=t(),a=o({inst:{value:n,getSnapshot:t}}),r=a[0].inst,u=a[1];return i((function(){r.value=n,r.getSnapshot=t,c(r)&&u({inst:r})}),[e,n,t]),s((function(){return c(r)&&u({inst:r}),e((function(){c(r)&&u({inst:r})}))}),[e]),l(n),n};void 0!==a.useSyncExternalStore&&a.useSyncExternalStore},1688:(e,t,n)=>{"use strict";n(3250)},6809:(e,t,n)=>{"use strict";n.d(t,{default:()=>a});const a={title:"GlueSQL",tagline:"GlueSQL is quite sticky. It attaches to anywhere",favicon:"img/favicon.ico",url:"https://gluesql.org",baseUrl:"/docs/dev/",onBrokenLinks:"throw",onBrokenMarkdownLinks:"warn",i18n:{defaultLocale:"en",locales:["en"],path:"i18n",localeConfigs:{}},presets:[["classic",{theme:{customCss:"/home/runner/work/gluesql/gluesql/docs/src/css/custom.css"},pages:!1,docs:{sidebarPath:"/home/runner/work/gluesql/gluesql/docs/sidebars.js",routeBasePath:"/"}}]],themeConfig:{colorMode:{disableSwitch:!1,respectPrefersColorScheme:!0,defaultMode:"light"},navbar:{title:"GlueSQL",items:[{to:"getting-started/rust",position:"left",label:"Getting Started",activeBasePath:"getting-started"},{to:"sql-syntax/intro",position:"left",label:"SQL Syntax",activeBasePath:"sql-syntax"},{to:"ast-builder/intro",position:"left",label:"AST Builder",activeBasePath:"ast-builder"},{to:"storages/intro",position:"left",label:"Storages",activeBasePath:"storages"},{href:"https://gluesql.org/blog",label:"Blog",position:"right"},{href:"https://github.com/gluesql/gluesql",label:"GitHub",position:"right"}],hideOnScroll:!1},prism:{theme:{plain:{color:"#393A34",backgroundColor:"#f6f8fa"},styles:[{types:["comment","prolog","doctype","cdata"],style:{color:"#999988",fontStyle:"italic"}},{types:["namespace"],style:{opacity:.7}},{types:["string","attr-value"],style:{color:"#e3116c"}},{types:["punctuation","operator"],style:{color:"#393A34"}},{types:["entity","url","symbol","number","boolean","variable","constant","property","regex","inserted"],style:{color:"#36acaa"}},{types:["atrule","keyword","attr-name","selector"],style:{color:"#00a4db"}},{types:["function","deleted","tag"],style:{color:"#d73a49"}},{types:["function-variable"],style:{color:"#6f42c1"}},{types:["tag","selector","keyword"],style:{color:"#00009f"}}]},darkTheme:{plain:{color:"#F8F8F2",backgroundColor:"#282A36"},styles:[{types:["prolog","constant","builtin"],style:{color:"rgb(189, 147, 249)"}},{types:["inserted","function"],style:{color:"rgb(80, 250, 123)"}},{types:["deleted"],style:{color:"rgb(255, 85, 85)"}},{types:["changed"],style:{color:"rgb(255, 184, 108)"}},{types:["punctuation","symbol"],style:{color:"rgb(248, 248, 242)"}},{types:["string","char","tag","selector"],style:{color:"rgb(255, 121, 198)"}},{types:["keyword","variable"],style:{color:"rgb(189, 147, 249)",fontStyle:"italic"}},{types:["comment"],style:{color:"rgb(98, 114, 164)"}},{types:["attr-name"],style:{color:"rgb(241, 250, 140)"}}]},additionalLanguages:["rust","toml"],magicComments:[{className:"theme-code-block-highlighted-line",line:"highlight-next-line",block:{start:"highlight-start",end:"highlight-end"}}]},docs:{versionPersistence:"localStorage",sidebar:{hideable:!1,autoCollapseCategories:!1}},metadata:[],tableOfContents:{minHeadingLevel:2,maxHeadingLevel:3}},baseUrlIssueBanner:!0,onDuplicateRoutes:"warn",staticDirectories:["static"],customFields:{},plugins:[],themes:[],scripts:[],headTags:[],stylesheets:[],clientModules:[],titleDelimiter:"|",noIndex:!1,markdown:{mermaid:!1}}},7462:(e,t,n)=>{"use strict";function a(){return a=Object.assign?Object.assign.bind():function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var a in n)Object.prototype.hasOwnProperty.call(n,a)&&(e[a]=n[a])}return e},a.apply(this,arguments)}n.d(t,{Z:()=>a})},5068:(e,t,n)=>{"use strict";function a(e,t){return a=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(e,t){return e.__proto__=t,e},a(e,t)}function r(e,t){e.prototype=Object.create(t.prototype),e.prototype.constructor=e,a(e,t)}n.d(t,{Z:()=>r})},3366:(e,t,n)=>{"use strict";function a(e,t){if(null==e)return{};var n,a,r={},o=Object.keys(e);for(a=0;a<o.length;a++)n=o[a],t.indexOf(n)>=0||(r[n]=e[n]);return r}n.d(t,{Z:()=>a})},8776:(e,t,n)=>{"use strict";n.d(t,{Z:()=>o});var a=!0,r="Invariant failed";function o(e,t){if(!e){if(a)throw new Error(r);var n="function"==typeof t?t():t,o=n?"".concat(r,": ").concat(n):r;throw new Error(o)}}},7529:e=>{"use strict";e.exports={}},6887:e=>{"use strict";e.exports=JSON.parse('{"/docs/dev/blog-9f6":{"__comp":"a6aa9e1f","__context":{"plugin":"1c41eae2"},"sidebar":"814f3328","items":[{"content":"20e2ece2"},{"content":"5058a078"},{"content":"8417e7a5"},{"content":"23f93eeb"}],"metadata":"81cb5929"},"/docs/dev/blog/archive-f0a":{"__comp":"9e4087bc","__context":{"plugin":"1c41eae2"},"archive":"b1f622a1"},"/docs/dev/blog/breaking-the-boundary-between-sql-and-nosql-150":{"__comp":"ccc49370","__context":{"plugin":"1c41eae2"},"sidebar":"814f3328","content":"7d170ab0"},"/docs/dev/blog/release-v0.14-d1b":{"__comp":"ccc49370","__context":{"plugin":"1c41eae2"},"sidebar":"814f3328","content":"234733fd"},"/docs/dev/blog/revolutionizing-databases-by-unifying-query-interfaces-c88":{"__comp":"ccc49370","__context":{"plugin":"1c41eae2"},"sidebar":"814f3328","content":"772fc39d"},"/docs/dev/blog/tags-946":{"__comp":"01a85c17","__context":{"plugin":"1c41eae2"},"sidebar":"814f3328","tags":"89739c9f"},"/docs/dev/blog/tags/automation-7a5":{"__comp":"6875c492","__context":{"plugin":"1c41eae2"},"sidebar":"814f3328","items":[{"content":"5058a078"}],"tag":"31f1dbb1","listMetadata":"2bed8b6f"},"/docs/dev/blog/tags/chat-gpt-65d":{"__comp":"6875c492","__context":{"plugin":"1c41eae2"},"sidebar":"814f3328","items":[{"content":"5058a078"}],"tag":"9624c11c","listMetadata":"db5d1fe1"},"/docs/dev/blog/tags/database-53f":{"__comp":"6875c492","__context":{"plugin":"1c41eae2"},"sidebar":"814f3328","items":[{"content":"20e2ece2"},{"content":"5058a078"},{"content":"8417e7a5"}],"tag":"9bbfd40a","listMetadata":"38a882bf"},"/docs/dev/blog/tags/documentation-7d2":{"__comp":"6875c492","__context":{"plugin":"1c41eae2"},"sidebar":"814f3328","items":[{"content":"5058a078"}],"tag":"79c85cd0","listMetadata":"93e7cfc5"},"/docs/dev/blog/tags/gluesql-22b":{"__comp":"6875c492","__context":{"plugin":"1c41eae2"},"sidebar":"814f3328","items":[{"content":"20e2ece2"}],"tag":"daad7c1d","listMetadata":"40386700"},"/docs/dev/blog/tags/nosql-582":{"__comp":"6875c492","__context":{"plugin":"1c41eae2"},"sidebar":"814f3328","items":[{"content":"8417e7a5"}],"tag":"768594c0","listMetadata":"0ccdbf16"},"/docs/dev/blog/tags/proposal-5c5":{"__comp":"6875c492","__context":{"plugin":"1c41eae2"},"sidebar":"814f3328","items":[{"content":"20e2ece2"}],"tag":"e519b4b4","listMetadata":"67002961"},"/docs/dev/blog/tags/query-interface-ee0":{"__comp":"6875c492","__context":{"plugin":"1c41eae2"},"sidebar":"814f3328","items":[{"content":"20e2ece2"}],"tag":"9d02ad31","listMetadata":"a6177d3d"},"/docs/dev/blog/tags/release-note-991":{"__comp":"6875c492","__context":{"plugin":"1c41eae2"},"sidebar":"814f3328","items":[{"content":"23f93eeb"}],"tag":"54df49be","listMetadata":"ee6dd1d2"},"/docs/dev/blog/tags/sql-959":{"__comp":"6875c492","__context":{"plugin":"1c41eae2"},"sidebar":"814f3328","items":[{"content":"8417e7a5"}],"tag":"65f7a26b","listMetadata":"ebfca923"},"/docs/dev/blog/tags/tdd-ff0":{"__comp":"6875c492","__context":{"plugin":"1c41eae2"},"sidebar":"814f3328","items":[{"content":"5058a078"}],"tag":"153137de","listMetadata":"dc5cc32c"},"/docs/dev/blog/tags/test-driven-documentation-fcc":{"__comp":"6875c492","__context":{"plugin":"1c41eae2"},"sidebar":"814f3328","items":[{"content":"5058a078"}],"tag":"f81fb924","listMetadata":"77b9a1ed"},"/docs/dev/blog/tags/v-0-14-b4d":{"__comp":"6875c492","__context":{"plugin":"1c41eae2"},"sidebar":"814f3328","items":[{"content":"23f93eeb"}],"tag":"9017a27d","listMetadata":"65722401"},"/docs/dev/blog/test-driven-documentation-af8":{"__comp":"ccc49370","__context":{"plugin":"1c41eae2"},"sidebar":"814f3328","content":"25196878"},"/docs/dev/-52e":{"__comp":"1be78505","__context":{"plugin":"1e4e1fb6"},"versionMetadata":"935f2afb"},"/docs/dev/-666":{"__comp":"17896441","content":"c377a04b"},"/docs/dev/ast-builder/expressions/conditional-32d":{"__comp":"17896441","content":"a4bc1622"},"/docs/dev/ast-builder/expressions/nested-dcd":{"__comp":"17896441","content":"5df6e7df"},"/docs/dev/ast-builder/expressions/operator-based-172":{"__comp":"17896441","content":"44954150"},"/docs/dev/ast-builder/expressions/pattern-matching-8b6":{"__comp":"17896441","content":"2b265210"},"/docs/dev/ast-builder/expressions/value-checking-c44":{"__comp":"17896441","content":"b6bceaff"},"/docs/dev/ast-builder/functions/date-&-time/conversion-bf0":{"__comp":"17896441","content":"acfabe81"},"/docs/dev/ast-builder/functions/date-&-time/current-date-and-time-16a":{"__comp":"17896441","content":"8c7569e5"},"/docs/dev/ast-builder/functions/date-&-time/date-and-time-extraction-273":{"__comp":"17896441","content":"7ea7f008"},"/docs/dev/ast-builder/functions/date-&-time/formatting-b9b":{"__comp":"17896441","content":"463dc00f"},"/docs/dev/ast-builder/functions/geometry/coordinate-extraction-5d6":{"__comp":"17896441","content":"f6ca3de5"},"/docs/dev/ast-builder/functions/geometry/distance-calculation-900":{"__comp":"17896441","content":"89fc5f00"},"/docs/dev/ast-builder/functions/geometry/point-creation-1a3":{"__comp":"17896441","content":"a6b6486c"},"/docs/dev/ast-builder/functions/list-&-map/list-and-map-concatenation-35b":{"__comp":"17896441","content":"81bf07f5"},"/docs/dev/ast-builder/functions/list-&-map/list-manipulation-2cf":{"__comp":"17896441","content":"a2ab2bad"},"/docs/dev/ast-builder/functions/math/basic-arithmetic-f0a":{"__comp":"17896441","content":"9c5158ac"},"/docs/dev/ast-builder/functions/math/conversion-7c8":{"__comp":"17896441","content":"02aa4531"},"/docs/dev/ast-builder/functions/math/logarithmic-and-exponential-fb1":{"__comp":"17896441","content":"980f8d5e"},"/docs/dev/ast-builder/functions/math/rounding-7ca":{"__comp":"17896441","content":"1ce64703"},"/docs/dev/ast-builder/functions/math/special-mathematical-3ee":{"__comp":"17896441","content":"89196f72"},"/docs/dev/ast-builder/functions/math/trigonometric-29b":{"__comp":"17896441","content":"c5e834bc"},"/docs/dev/ast-builder/functions/others/null-handling-948":{"__comp":"17896441","content":"078a6308"},"/docs/dev/ast-builder/functions/others/type-conversion-a77":{"__comp":"17896441","content":"26c0a43c"},"/docs/dev/ast-builder/functions/others/unique-identifier-0a6":{"__comp":"17896441","content":"d5aa49f9"},"/docs/dev/ast-builder/functions/text/case-conversion-605":{"__comp":"17896441","content":"d7a493e6"},"/docs/dev/ast-builder/functions/text/character-conversion-919":{"__comp":"17896441","content":"3cfbc8af"},"/docs/dev/ast-builder/functions/text/padding-7b6":{"__comp":"17896441","content":"07294b24"},"/docs/dev/ast-builder/functions/text/position-and-indexing-1ed":{"__comp":"17896441","content":"f9553497"},"/docs/dev/ast-builder/functions/text/text-manipulation-762":{"__comp":"17896441","content":"1cdac986"},"/docs/dev/ast-builder/functions/text/trimming-63b":{"__comp":"17896441","content":"02bfc02d"},"/docs/dev/ast-builder/intro-06b":{"__comp":"17896441","content":"4add0c6c"},"/docs/dev/ast-builder/statements/data-manipulation/deleting-data-9f7":{"__comp":"17896441","content":"376759eb"},"/docs/dev/ast-builder/statements/data-manipulation/inserting-data-83e":{"__comp":"17896441","content":"bac2c42d"},"/docs/dev/ast-builder/statements/data-manipulation/updating-data-6c8":{"__comp":"17896441","content":"037683de"},"/docs/dev/ast-builder/statements/querying/creating-derived-subqueries-f4d":{"__comp":"17896441","content":"017e736e"},"/docs/dev/ast-builder/statements/querying/data-aggregation-5f9":{"__comp":"17896441","content":"b3de9677"},"/docs/dev/ast-builder/statements/querying/data-injection-a84":{"__comp":"17896441","content":"4be897c9"},"/docs/dev/ast-builder/statements/querying/data-joining-2c0":{"__comp":"17896441","content":"e5f53749"},"/docs/dev/ast-builder/statements/querying/data-selection-and-projection-34f":{"__comp":"17896441","content":"f914cfe8"},"/docs/dev/ast-builder/statements/querying/data-sorting-and-limiting-234":{"__comp":"17896441","content":"16815c2a"},"/docs/dev/ast-builder/statements/querying/fetching-data-from-storage-b2e":{"__comp":"17896441","content":"ee244d12"},"/docs/dev/ast-builder/statements/querying/using-preloaded-data-35f":{"__comp":"17896441","content":"d97b7d4d"},"/docs/dev/getting-started/cli-f3c":{"__comp":"17896441","content":"1c93e70c"},"/docs/dev/getting-started/javascript-web-ae6":{"__comp":"17896441","content":"e10f7c24"},"/docs/dev/getting-started/nodejs-37e":{"__comp":"17896441","content":"01a12966"},"/docs/dev/getting-started/rust-3fc":{"__comp":"17896441","content":"72c409f7"},"/docs/dev/sql-syntax/data-types/boolean-c7f":{"__comp":"17896441","content":"e68f8ad6"},"/docs/dev/sql-syntax/data-types/bytea-ed8":{"__comp":"17896441","content":"1798d0b3"},"/docs/dev/sql-syntax/data-types/date-612":{"__comp":"17896441","content":"a5971d1a"},"/docs/dev/sql-syntax/data-types/decimal-3f2":{"__comp":"17896441","content":"0b621d16"},"/docs/dev/sql-syntax/data-types/float-f0c":{"__comp":"17896441","content":"f33f2c05"},"/docs/dev/sql-syntax/data-types/inet-5c7":{"__comp":"17896441","content":"a9e26133"},"/docs/dev/sql-syntax/data-types/integers-171":{"__comp":"17896441","content":"aa1cf9a2"},"/docs/dev/sql-syntax/data-types/interval-59c":{"__comp":"17896441","content":"6ff6e7c9"},"/docs/dev/sql-syntax/data-types/list-0c2":{"__comp":"17896441","content":"2c0d2b92"},"/docs/dev/sql-syntax/data-types/map-744":{"__comp":"17896441","content":"50818478"},"/docs/dev/sql-syntax/data-types/text-f2f":{"__comp":"17896441","content":"d077f377"},"/docs/dev/sql-syntax/data-types/time-66e":{"__comp":"17896441","content":"ff7b8d8e"},"/docs/dev/sql-syntax/data-types/timestamp-546":{"__comp":"17896441","content":"a8d11699"},"/docs/dev/sql-syntax/data-types/uuid-5fa":{"__comp":"17896441","content":"bfb64759"},"/docs/dev/sql-syntax/functions/datetime/extract-ae9":{"__comp":"17896441","content":"4f675ae9"},"/docs/dev/sql-syntax/functions/datetime/format-2c8":{"__comp":"17896441","content":"f18bbaf6"},"/docs/dev/sql-syntax/functions/datetime/now-93b":{"__comp":"17896441","content":"98306a23"},"/docs/dev/sql-syntax/functions/datetime/to-date-8b3":{"__comp":"17896441","content":"928a5d6f"},"/docs/dev/sql-syntax/functions/datetime/to-time-b6e":{"__comp":"17896441","content":"a7153b78"},"/docs/dev/sql-syntax/functions/datetime/to-timestamp-52a":{"__comp":"17896441","content":"c2e5ab4f"},"/docs/dev/sql-syntax/functions/geometry/calc-distance-e9f":{"__comp":"17896441","content":"aff456d7"},"/docs/dev/sql-syntax/functions/geometry/get-x-2ae":{"__comp":"17896441","content":"9a3e57da"},"/docs/dev/sql-syntax/functions/geometry/get-y-54a":{"__comp":"17896441","content":"2a4d41ed"},"/docs/dev/sql-syntax/functions/geometry/point-12a":{"__comp":"17896441","content":"1a3daba8"},"/docs/dev/sql-syntax/functions/list-map/append-be2":{"__comp":"17896441","content":"0c18287f"},"/docs/dev/sql-syntax/functions/list-map/concat-cc9":{"__comp":"17896441","content":"cf518063"},"/docs/dev/sql-syntax/functions/list-map/prepend-7d8":{"__comp":"17896441","content":"77cc432a"},"/docs/dev/sql-syntax/functions/math/abs-b85":{"__comp":"17896441","content":"5a8c7729"},"/docs/dev/sql-syntax/functions/math/acos-ec1":{"__comp":"17896441","content":"6ba4a510"},"/docs/dev/sql-syntax/functions/math/asin-c78":{"__comp":"17896441","content":"68c17ba1"},"/docs/dev/sql-syntax/functions/math/atan-ad0":{"__comp":"17896441","content":"ba43b2d5"},"/docs/dev/sql-syntax/functions/math/ceil-0d5":{"__comp":"17896441","content":"56ccfc32"},"/docs/dev/sql-syntax/functions/math/cos-8ae":{"__comp":"17896441","content":"2f7bd5c8"},"/docs/dev/sql-syntax/functions/math/degrees-e0e":{"__comp":"17896441","content":"c97e0540"},"/docs/dev/sql-syntax/functions/math/div-048":{"__comp":"17896441","content":"920bdc78"},"/docs/dev/sql-syntax/functions/math/exp-a31":{"__comp":"17896441","content":"faca410e"},"/docs/dev/sql-syntax/functions/math/floor-03a":{"__comp":"17896441","content":"1b8ca8c3"},"/docs/dev/sql-syntax/functions/math/gcd-f38":{"__comp":"17896441","content":"cdaafcc9"},"/docs/dev/sql-syntax/functions/math/lcm-1c7":{"__comp":"17896441","content":"e4f709d1"},"/docs/dev/sql-syntax/functions/math/ln-700":{"__comp":"17896441","content":"ae3eef3e"},"/docs/dev/sql-syntax/functions/math/log-4e6":{"__comp":"17896441","content":"db0d9cb2"},"/docs/dev/sql-syntax/functions/math/log10-09d":{"__comp":"17896441","content":"afebe5f1"},"/docs/dev/sql-syntax/functions/math/log2-204":{"__comp":"17896441","content":"f1257df2"},"/docs/dev/sql-syntax/functions/math/mod-1fe":{"__comp":"17896441","content":"4a9d0f4c"},"/docs/dev/sql-syntax/functions/math/pi-4b0":{"__comp":"17896441","content":"eceb3b9b"},"/docs/dev/sql-syntax/functions/math/power-a7d":{"__comp":"17896441","content":"a7e6874c"},"/docs/dev/sql-syntax/functions/math/radians-09d":{"__comp":"17896441","content":"160faf1d"},"/docs/dev/sql-syntax/functions/math/rand-5c1":{"__comp":"17896441","content":"385623dc"},"/docs/dev/sql-syntax/functions/math/round-73f":{"__comp":"17896441","content":"7e0ce508"},"/docs/dev/sql-syntax/functions/math/sign-da7":{"__comp":"17896441","content":"6870612e"},"/docs/dev/sql-syntax/functions/math/sin-98d":{"__comp":"17896441","content":"9a1c8bc6"},"/docs/dev/sql-syntax/functions/math/sqrt-d79":{"__comp":"17896441","content":"5242ac2d"},"/docs/dev/sql-syntax/functions/math/tan-a32":{"__comp":"17896441","content":"85afcbde"},"/docs/dev/sql-syntax/functions/others/cast-5c2":{"__comp":"17896441","content":"bb43b8ce"},"/docs/dev/sql-syntax/functions/others/generate-uuid-7ff":{"__comp":"17896441","content":"0ea64360"},"/docs/dev/sql-syntax/functions/others/ifnull-bfe":{"__comp":"17896441","content":"fa5466f2"},"/docs/dev/sql-syntax/functions/text/ascii-6f0":{"__comp":"17896441","content":"e06425d1"},"/docs/dev/sql-syntax/functions/text/chr-791":{"__comp":"17896441","content":"8cf2dd9c"},"/docs/dev/sql-syntax/functions/text/concat-2d3":{"__comp":"17896441","content":"a470b55c"},"/docs/dev/sql-syntax/functions/text/concat-ws-7cc":{"__comp":"17896441","content":"c5b25a7c"},"/docs/dev/sql-syntax/functions/text/find-idx-e63":{"__comp":"17896441","content":"d4251823"},"/docs/dev/sql-syntax/functions/text/initcap-d0b":{"__comp":"17896441","content":"06322d53"},"/docs/dev/sql-syntax/functions/text/left-6d7":{"__comp":"17896441","content":"dafe2799"},"/docs/dev/sql-syntax/functions/text/lower-913":{"__comp":"17896441","content":"81f6aa2c"},"/docs/dev/sql-syntax/functions/text/lpad-832":{"__comp":"17896441","content":"97081ee7"},"/docs/dev/sql-syntax/functions/text/ltrim-076":{"__comp":"17896441","content":"007e0817"},"/docs/dev/sql-syntax/functions/text/position-184":{"__comp":"17896441","content":"15868c40"},"/docs/dev/sql-syntax/functions/text/repeat-6c9":{"__comp":"17896441","content":"b57ca7d5"},"/docs/dev/sql-syntax/functions/text/reverse-007":{"__comp":"17896441","content":"ae967838"},"/docs/dev/sql-syntax/functions/text/right-f07":{"__comp":"17896441","content":"5eabd930"},"/docs/dev/sql-syntax/functions/text/rpad-93e":{"__comp":"17896441","content":"7457c448"},"/docs/dev/sql-syntax/functions/text/rtrim-e76":{"__comp":"17896441","content":"c9d1eb08"},"/docs/dev/sql-syntax/functions/text/substr-d8c":{"__comp":"17896441","content":"d8746e52"},"/docs/dev/sql-syntax/functions/text/trim-ce4":{"__comp":"17896441","content":"41718851"},"/docs/dev/sql-syntax/functions/text/upper-6b6":{"__comp":"17896441","content":"b7661aba"},"/docs/dev/sql-syntax/intro-d94":{"__comp":"17896441","content":"31526b20"},"/docs/dev/sql-syntax/statements/data-definition/alter-table-259":{"__comp":"17896441","content":"0c94c658"},"/docs/dev/sql-syntax/statements/data-definition/create-index-ba4":{"__comp":"17896441","content":"0544f90b"},"/docs/dev/sql-syntax/statements/data-definition/create-table-9fd":{"__comp":"17896441","content":"86a1f821"},"/docs/dev/sql-syntax/statements/data-definition/drop-index-69c":{"__comp":"17896441","content":"4aa001c0"},"/docs/dev/sql-syntax/statements/data-definition/drop-table-f80":{"__comp":"17896441","content":"402da695"},"/docs/dev/sql-syntax/statements/data-manipulation/delete-927":{"__comp":"17896441","content":"92dd0956"},"/docs/dev/sql-syntax/statements/data-manipulation/insert-10a":{"__comp":"17896441","content":"df2eb7da"},"/docs/dev/sql-syntax/statements/data-manipulation/update-967":{"__comp":"17896441","content":"8be9dc67"},"/docs/dev/sql-syntax/statements/metadata/data-dictionary-114":{"__comp":"17896441","content":"6c5232c2"},"/docs/dev/sql-syntax/statements/metadata/show-tables-1bf":{"__comp":"17896441","content":"c30ee527"},"/docs/dev/sql-syntax/statements/querying/aggregation-5df":{"__comp":"17896441","content":"3245f64b"},"/docs/dev/sql-syntax/statements/querying/join-796":{"__comp":"17896441","content":"dc8f2f6c"},"/docs/dev/sql-syntax/statements/querying/limit-762":{"__comp":"17896441","content":"b7da1136"},"/docs/dev/sql-syntax/statements/querying/schemaless-afa":{"__comp":"17896441","content":"7310a4fe"},"/docs/dev/sql-syntax/statements/querying/where-bb5":{"__comp":"17896441","content":"2d9479c4"},"/docs/dev/sql-syntax/statements/transaction-411":{"__comp":"17896441","content":"e158c27a"},"/docs/dev/storages/developing-custom-storages/intro-c6d":{"__comp":"17896441","content":"c251e734"},"/docs/dev/storages/developing-custom-storages/store-traits/alter-table-4c5":{"__comp":"17896441","content":"194e858c"},"/docs/dev/storages/developing-custom-storages/store-traits/custom-function-e5b":{"__comp":"17896441","content":"83b912d4"},"/docs/dev/storages/developing-custom-storages/store-traits/custom-function-mut-0cc":{"__comp":"17896441","content":"44f79c8d"},"/docs/dev/storages/developing-custom-storages/store-traits/index-mut-78f":{"__comp":"17896441","content":"5cdfb1f2"},"/docs/dev/storages/developing-custom-storages/store-traits/index-trait-aa3":{"__comp":"17896441","content":"d941076d"},"/docs/dev/storages/developing-custom-storages/store-traits/metadata-2a5":{"__comp":"17896441","content":"e329d2fa"},"/docs/dev/storages/developing-custom-storages/store-traits/store-262":{"__comp":"17896441","content":"482a391c"},"/docs/dev/storages/developing-custom-storages/store-traits/store-mut-853":{"__comp":"17896441","content":"ebe12d94"},"/docs/dev/storages/developing-custom-storages/store-traits/transaction-bd7":{"__comp":"17896441","content":"488157d7"},"/docs/dev/storages/developing-custom-storages/using-test-suite-a37":{"__comp":"17896441","content":"345c600d"},"/docs/dev/storages/intro-8d9":{"__comp":"17896441","content":"b209ab8a"},"/docs/dev/storages/supported-storages/composite-storage-93e":{"__comp":"17896441","content":"67d1434e"},"/docs/dev/storages/supported-storages/idb-storage-787":{"__comp":"17896441","content":"952dfacb"},"/docs/dev/storages/supported-storages/json-storage-207":{"__comp":"17896441","content":"3961e600"},"/docs/dev/storages/supported-storages/memory-storage-695":{"__comp":"17896441","content":"6e772156"},"/docs/dev/storages/supported-storages/shared-memory-storage-418":{"__comp":"17896441","content":"e46b95eb"},"/docs/dev/storages/supported-storages/sled-storage-fb0":{"__comp":"17896441","content":"8d6e802b"},"/docs/dev/storages/supported-storages/web-storage-14a":{"__comp":"17896441","content":"edb9b0b8"}}')}},e=>{e.O(0,[532],(()=>{return t=9383,e(e.s=t);var t}));e.O()}]); \ No newline at end of file diff --git a/docs/dev/assets/js/runtime~main.7546ec27.js b/docs/dev/assets/js/runtime~main.7546ec27.js deleted file mode 100644 index 6b279822..00000000 --- a/docs/dev/assets/js/runtime~main.7546ec27.js +++ /dev/null @@ -1 +0,0 @@ -(()=>{"use strict";var e,a,c,d,f,b={},t={};function r(e){var a=t[e];if(void 0!==a)return a.exports;var c=t[e]={exports:{}};return b[e].call(c.exports,c,c.exports,r),c.exports}r.m=b,e=[],r.O=(a,c,d,f)=>{if(!c){var b=1/0;for(i=0;i<e.length;i++){c=e[i][0],d=e[i][1],f=e[i][2];for(var t=!0,o=0;o<c.length;o++)(!1&f||b>=f)&&Object.keys(r.O).every((e=>r.O[e](c[o])))?c.splice(o--,1):(t=!1,f<b&&(b=f));if(t){e.splice(i--,1);var n=d();void 0!==n&&(a=n)}}return a}f=f||0;for(var i=e.length;i>0&&e[i-1][2]>f;i--)e[i]=e[i-1];e[i]=[c,d,f]},r.n=e=>{var a=e&&e.__esModule?()=>e.default:()=>e;return r.d(a,{a:a}),a},c=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__,r.t=function(e,d){if(1&d&&(e=this(e)),8&d)return e;if("object"==typeof e&&e){if(4&d&&e.__esModule)return e;if(16&d&&"function"==typeof e.then)return e}var f=Object.create(null);r.r(f);var b={};a=a||[null,c({}),c([]),c(c)];for(var t=2&d&&e;"object"==typeof t&&!~a.indexOf(t);t=c(t))Object.getOwnPropertyNames(t).forEach((a=>b[a]=()=>e[a]));return b.default=()=>e,r.d(f,b),f},r.d=(e,a)=>{for(var c in a)r.o(a,c)&&!r.o(e,c)&&Object.defineProperty(e,c,{enumerable:!0,get:a[c]})},r.f={},r.e=e=>Promise.all(Object.keys(r.f).reduce(((a,c)=>(r.f[c](e,a),a)),[])),r.u=e=>"assets/js/"+({16:"376759eb",53:"935f2afb",104:"92dd0956",127:"2bed8b6f",156:"a5971d1a",203:"9624c11c",221:"e06425d1",314:"fa5466f2",340:"a7e6874c",438:"f81fb924",560:"edb9b0b8",636:"afebe5f1",689:"15868c40",777:"db0d9cb2",811:"f18bbaf6",846:"02bfc02d",930:"e5f53749",950:"a7153b78",998:"acfabe81",1003:"4aa001c0",1164:"dc8f2f6c",1279:"06322d53",1354:"9017a27d",1375:"345c600d",1395:"25196878",1452:"b1f622a1",1470:"9c5158ac",1500:"cdaafcc9",1530:"ee244d12",1610:"bac2c42d",1715:"a2ab2bad",1768:"7d170ab0",1788:"9bbfd40a",1827:"6870612e",1849:"aff456d7",1929:"d077f377",1965:"01a12966",1983:"a4bc1622",2047:"7310a4fe",2177:"a9e26133",2215:"1cdac986",2305:"194e858c",2365:"160faf1d",2463:"daad7c1d",2535:"814f3328",2616:"68c17ba1",2627:"89fc5f00",2690:"f914cfe8",2691:"3cfbc8af",2809:"2d9479c4",2842:"3961e600",2988:"e68f8ad6",3004:"5a8c7729",3020:"d7a493e6",3058:"2f7bd5c8",3089:"a6aa9e1f",3151:"c2e5ab4f",3159:"77cc432a",3188:"234733fd",3193:"81cb5929",3216:"b7da1136",3317:"5242ac2d",3337:"1ce64703",3344:"ff7b8d8e",3357:"44954150",3367:"81bf07f5",3371:"16815c2a",3372:"0ea64360",3390:"85afcbde",3394:"7e0ce508",3454:"0c94c658",3475:"0c18287f",3554:"078a6308",3575:"54df49be",3587:"b6bceaff",3608:"9e4087bc",3619:"97081ee7",3704:"93e7cfc5",3726:"07294b24",3768:"8417e7a5",3851:"772fc39d",3905:"8be9dc67",3944:"768594c0",4004:"2a4d41ed",4013:"01a85c17",4033:"f9553497",4046:"1798d0b3",4176:"d4251823",4213:"e10f7c24",4244:"41718851",4450:"1c41eae2",4452:"7457c448",4538:"463dc00f",4561:"ae967838",4637:"ebfca923",4706:"f6ca3de5",4734:"ee6dd1d2",4746:"5058a078",4785:"20e2ece2",4792:"e329d2fa",4875:"67002961",4909:"1e4e1fb6",4945:"1a3daba8",5085:"e46b95eb",5123:"98306a23",5297:"b57ca7d5",5315:"0ccdbf16",5391:"a8d11699",5401:"bfb64759",5458:"72c409f7",5558:"5eabd930",5589:"e158c27a",5667:"02aa4531",5682:"402da695",5737:"8c7569e5",5756:"81f6aa2c",5843:"8d6e802b",5889:"ebe12d94",5906:"b209ab8a",5944:"2c0d2b92",5952:"c251e734",5962:"79c85cd0",6017:"9d02ad31",6044:"db5d1fe1",6094:"50818478",6103:"ccc49370",6132:"3245f64b",6155:"952dfacb",6186:"dc5cc32c",6199:"153137de",6212:"ae3eef3e",6350:"89739c9f",6448:"c9d1eb08",6470:"f33f2c05",6489:"928a5d6f",6508:"482a391c",6533:"e4f709d1",6555:"b3de9677",6669:"920bdc78",6685:"017e736e",6694:"df2eb7da",6741:"4be897c9",6811:"faca410e",6971:"c377a04b",6979:"cf518063",6989:"a470b55c",7062:"77b9a1ed",7123:"44f79c8d",7194:"56ccfc32",7219:"89196f72",7233:"4f675ae9",7257:"f1257df2",7332:"c97e0540",7344:"980f8d5e",7385:"4a9d0f4c",7449:"83b912d4",7462:"0b621d16",7486:"5cdfb1f2",7496:"ba43b2d5",7513:"65722401",7518:"6ba4a510",7669:"9a1c8bc6",7677:"037683de",7785:"26c0a43c",7793:"23f93eeb",7839:"a6b6486c",7870:"bb43b8ce",7901:"d5aa49f9",7918:"17896441",8142:"2b265210",8215:"6ff6e7c9",8253:"6e772156",8506:"1c93e70c",8599:"6c5232c2",8610:"6875c492",8662:"d941076d",8697:"d8746e52",8851:"eceb3b9b",8894:"9a3e57da",8905:"7ea7f008",9020:"31526b20",9054:"b7661aba",9063:"007e0817",9101:"e519b4b4",9132:"4add0c6c",9147:"1b8ca8c3",9162:"488157d7",9266:"c5b25a7c",9385:"c5e834bc",9502:"67d1434e",9514:"1be78505",9586:"d97b7d4d",9600:"0544f90b",9616:"dafe2799",9643:"385623dc",9661:"c30ee527",9667:"38a882bf",9695:"40386700",9722:"8cf2dd9c",9760:"65f7a26b",9818:"a6177d3d",9903:"31f1dbb1",9978:"5df6e7df",9986:"aa1cf9a2",9992:"86a1f821"}[e]||e)+"."+{16:"f0143aca",53:"6ae40558",104:"1a95dd6f",127:"6c35bd0b",156:"2ddaa6c8",203:"2d436350",221:"24dae45f",314:"6cae2b31",340:"61f09544",438:"9105c0e1",560:"43f97c7e",636:"a6dcb42f",689:"bc24a74e",777:"4a41ead9",811:"af600d96",846:"a846ad63",930:"64c9f090",950:"7d21bcc4",998:"40e0679f",1003:"e6e02f8e",1164:"4e8f9014",1279:"19c4e18a",1354:"158ddff3",1375:"32f2c407",1395:"63ed3781",1452:"6224d282",1470:"3b686c7e",1500:"b6bb1966",1530:"2429282b",1610:"6a0971e5",1715:"17af2301",1768:"0bfdf1ec",1788:"df08973b",1827:"1a535468",1849:"6ab5288b",1929:"02c130f9",1965:"e624b5b0",1983:"cf5c3efa",2047:"28a29c7e",2177:"2fa70c63",2215:"927e6f22",2305:"8683b66e",2365:"76526d55",2463:"7770827c",2535:"a7d57a47",2616:"c299310a",2627:"23609afa",2690:"fcea67b6",2691:"c550c228",2809:"2743ad51",2842:"fde60b55",2988:"a9305a10",3004:"4efe6d0f",3020:"ca5719aa",3058:"8d2baaf0",3089:"845cad8c",3151:"448fdf11",3159:"70485db0",3188:"e54974f4",3193:"f3f7b9c3",3216:"cefea56d",3317:"c86c6573",3337:"7bdf8e65",3344:"8b7db25b",3357:"821b1811",3367:"2b3ed4fb",3371:"8833df51",3372:"9888bb74",3390:"23543644",3394:"6e093c40",3454:"87f78ad3",3475:"74853166",3554:"129076c2",3575:"7687342d",3587:"d3ee5eff",3608:"064ee4cb",3619:"926834d2",3704:"4727baaf",3726:"6bb83857",3768:"ac10b2b2",3851:"9f22ee89",3905:"f807be43",3944:"ea58dbe0",4004:"b9fde1cf",4013:"44f4b362",4033:"5f4a3317",4046:"f50bdee5",4176:"d52e2d5c",4213:"c2426f9c",4244:"98e01ad8",4450:"308271a0",4452:"b5ef6742",4538:"03b52d57",4561:"542e2305",4637:"eef347af",4706:"0373150b",4734:"2425cf24",4746:"5dcf9c7d",4785:"93932fae",4792:"c6a1a21f",4875:"cc17f56d",4909:"bb6129fc",4945:"350ec93b",4972:"96c55074",5085:"9d24edd6",5123:"103a8ca0",5297:"d12fa993",5315:"419ff39d",5391:"8b646c5f",5401:"1600775d",5458:"2eac6138",5558:"4ffd8fa6",5589:"6ddfe5ad",5667:"8256d16e",5682:"ec89f648",5737:"8272001e",5756:"bef6994b",5843:"5b5fd69a",5889:"173ebcc7",5906:"75d78f76",5944:"20aa9f60",5952:"146b0a67",5962:"04df9409",6017:"a163b5d7",6044:"385880ad",6048:"b8e3eb8d",6094:"bf5eb4bf",6103:"d9c41d1e",6132:"692fef03",6155:"b4199040",6186:"22e17cc7",6199:"f7e21a8d",6212:"1bbc9c63",6350:"652f9696",6448:"589784fb",6470:"19133a69",6489:"ea3e3aee",6508:"56aaed9a",6533:"e288a898",6555:"87a3c41b",6669:"d82f3005",6685:"5c763729",6694:"5d459d62",6741:"0aca83b7",6811:"041d0b7a",6971:"c618e95e",6979:"9ef405bb",6989:"df88a961",7062:"cb063d01",7123:"8067102b",7194:"985c6211",7219:"8e456573",7233:"8448a496",7257:"433d18f6",7332:"2d90c993",7344:"5ec88372",7385:"02073b85",7449:"105ec02d",7462:"fff33ba6",7486:"5091e89c",7496:"9c203679",7513:"0cb7eac9",7518:"297732b3",7669:"63b5d495",7677:"06e9c439",7785:"afeae6c6",7793:"ef1aaac9",7839:"0f896e86",7870:"db808b9c",7901:"f981f00d",7918:"fc8b9592",8142:"4d93b412",8215:"5e675e3b",8253:"177df649",8506:"55f9488c",8599:"aa9f007e",8610:"f37b7b5c",8662:"7ae86871",8697:"872683ec",8851:"58ad7533",8894:"0bb59fe9",8905:"a6140792",9020:"09aa7811",9054:"27060343",9063:"aa07ff6f",9101:"d1af950d",9132:"b0b2e0b3",9147:"acd94369",9162:"5b53d945",9266:"9ed70bb6",9385:"963047f0",9502:"a98807cd",9514:"584d3a15",9586:"84bbc081",9600:"0aa1894c",9616:"5c248ad4",9643:"19f07cd6",9661:"9b4ec100",9667:"2d029f6e",9695:"15a66133",9722:"230aa8cc",9760:"67640917",9785:"0386875e",9818:"a62f8322",9903:"56c79677",9978:"050a254b",9986:"b51e283d",9992:"770c5c36"}[e]+".js",r.miniCssF=e=>{},r.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),r.o=(e,a)=>Object.prototype.hasOwnProperty.call(e,a),d={},f="docs:",r.l=(e,a,c,b)=>{if(d[e])d[e].push(a);else{var t,o;if(void 0!==c)for(var n=document.getElementsByTagName("script"),i=0;i<n.length;i++){var u=n[i];if(u.getAttribute("src")==e||u.getAttribute("data-webpack")==f+c){t=u;break}}t||(o=!0,(t=document.createElement("script")).charset="utf-8",t.timeout=120,r.nc&&t.setAttribute("nonce",r.nc),t.setAttribute("data-webpack",f+c),t.src=e),d[e]=[a];var l=(a,c)=>{t.onerror=t.onload=null,clearTimeout(s);var f=d[e];if(delete d[e],t.parentNode&&t.parentNode.removeChild(t),f&&f.forEach((e=>e(c))),a)return a(c)},s=setTimeout(l.bind(null,void 0,{type:"timeout",target:t}),12e4);t.onerror=l.bind(null,t.onerror),t.onload=l.bind(null,t.onload),o&&document.head.appendChild(t)}},r.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.p="/docs/dev/",r.gca=function(e){return e={17896441:"7918",25196878:"1395",40386700:"9695",41718851:"4244",44954150:"3357",50818478:"6094",65722401:"7513",67002961:"4875","376759eb":"16","935f2afb":"53","92dd0956":"104","2bed8b6f":"127",a5971d1a:"156","9624c11c":"203",e06425d1:"221",fa5466f2:"314",a7e6874c:"340",f81fb924:"438",edb9b0b8:"560",afebe5f1:"636","15868c40":"689",db0d9cb2:"777",f18bbaf6:"811","02bfc02d":"846",e5f53749:"930",a7153b78:"950",acfabe81:"998","4aa001c0":"1003",dc8f2f6c:"1164","06322d53":"1279","9017a27d":"1354","345c600d":"1375",b1f622a1:"1452","9c5158ac":"1470",cdaafcc9:"1500",ee244d12:"1530",bac2c42d:"1610",a2ab2bad:"1715","7d170ab0":"1768","9bbfd40a":"1788","6870612e":"1827",aff456d7:"1849",d077f377:"1929","01a12966":"1965",a4bc1622:"1983","7310a4fe":"2047",a9e26133:"2177","1cdac986":"2215","194e858c":"2305","160faf1d":"2365",daad7c1d:"2463","814f3328":"2535","68c17ba1":"2616","89fc5f00":"2627",f914cfe8:"2690","3cfbc8af":"2691","2d9479c4":"2809","3961e600":"2842",e68f8ad6:"2988","5a8c7729":"3004",d7a493e6:"3020","2f7bd5c8":"3058",a6aa9e1f:"3089",c2e5ab4f:"3151","77cc432a":"3159","234733fd":"3188","81cb5929":"3193",b7da1136:"3216","5242ac2d":"3317","1ce64703":"3337",ff7b8d8e:"3344","81bf07f5":"3367","16815c2a":"3371","0ea64360":"3372","85afcbde":"3390","7e0ce508":"3394","0c94c658":"3454","0c18287f":"3475","078a6308":"3554","54df49be":"3575",b6bceaff:"3587","9e4087bc":"3608","97081ee7":"3619","93e7cfc5":"3704","07294b24":"3726","8417e7a5":"3768","772fc39d":"3851","8be9dc67":"3905","768594c0":"3944","2a4d41ed":"4004","01a85c17":"4013",f9553497:"4033","1798d0b3":"4046",d4251823:"4176",e10f7c24:"4213","1c41eae2":"4450","7457c448":"4452","463dc00f":"4538",ae967838:"4561",ebfca923:"4637",f6ca3de5:"4706",ee6dd1d2:"4734","5058a078":"4746","20e2ece2":"4785",e329d2fa:"4792","1e4e1fb6":"4909","1a3daba8":"4945",e46b95eb:"5085","98306a23":"5123",b57ca7d5:"5297","0ccdbf16":"5315",a8d11699:"5391",bfb64759:"5401","72c409f7":"5458","5eabd930":"5558",e158c27a:"5589","02aa4531":"5667","402da695":"5682","8c7569e5":"5737","81f6aa2c":"5756","8d6e802b":"5843",ebe12d94:"5889",b209ab8a:"5906","2c0d2b92":"5944",c251e734:"5952","79c85cd0":"5962","9d02ad31":"6017",db5d1fe1:"6044",ccc49370:"6103","3245f64b":"6132","952dfacb":"6155",dc5cc32c:"6186","153137de":"6199",ae3eef3e:"6212","89739c9f":"6350",c9d1eb08:"6448",f33f2c05:"6470","928a5d6f":"6489","482a391c":"6508",e4f709d1:"6533",b3de9677:"6555","920bdc78":"6669","017e736e":"6685",df2eb7da:"6694","4be897c9":"6741",faca410e:"6811",c377a04b:"6971",cf518063:"6979",a470b55c:"6989","77b9a1ed":"7062","44f79c8d":"7123","56ccfc32":"7194","89196f72":"7219","4f675ae9":"7233",f1257df2:"7257",c97e0540:"7332","980f8d5e":"7344","4a9d0f4c":"7385","83b912d4":"7449","0b621d16":"7462","5cdfb1f2":"7486",ba43b2d5:"7496","6ba4a510":"7518","9a1c8bc6":"7669","037683de":"7677","26c0a43c":"7785","23f93eeb":"7793",a6b6486c:"7839",bb43b8ce:"7870",d5aa49f9:"7901","2b265210":"8142","6ff6e7c9":"8215","6e772156":"8253","1c93e70c":"8506","6c5232c2":"8599","6875c492":"8610",d941076d:"8662",d8746e52:"8697",eceb3b9b:"8851","9a3e57da":"8894","7ea7f008":"8905","31526b20":"9020",b7661aba:"9054","007e0817":"9063",e519b4b4:"9101","4add0c6c":"9132","1b8ca8c3":"9147","488157d7":"9162",c5b25a7c:"9266",c5e834bc:"9385","67d1434e":"9502","1be78505":"9514",d97b7d4d:"9586","0544f90b":"9600",dafe2799:"9616","385623dc":"9643",c30ee527:"9661","38a882bf":"9667","8cf2dd9c":"9722","65f7a26b":"9760",a6177d3d:"9818","31f1dbb1":"9903","5df6e7df":"9978",aa1cf9a2:"9986","86a1f821":"9992"}[e]||e,r.p+r.u(e)},(()=>{var e={1303:0,532:0};r.f.j=(a,c)=>{var d=r.o(e,a)?e[a]:void 0;if(0!==d)if(d)c.push(d[2]);else if(/^(1303|532)$/.test(a))e[a]=0;else{var f=new Promise(((c,f)=>d=e[a]=[c,f]));c.push(d[2]=f);var b=r.p+r.u(a),t=new Error;r.l(b,(c=>{if(r.o(e,a)&&(0!==(d=e[a])&&(e[a]=void 0),d)){var f=c&&("load"===c.type?"missing":c.type),b=c&&c.target&&c.target.src;t.message="Loading chunk "+a+" failed.\n("+f+": "+b+")",t.name="ChunkLoadError",t.type=f,t.request=b,d[1](t)}}),"chunk-"+a,a)}},r.O.j=a=>0===e[a];var a=(a,c)=>{var d,f,b=c[0],t=c[1],o=c[2],n=0;if(b.some((a=>0!==e[a]))){for(d in t)r.o(t,d)&&(r.m[d]=t[d]);if(o)var i=o(r)}for(a&&a(c);n<b.length;n++)f=b[n],r.o(e,f)&&e[f]&&e[f][0](),e[f]=0;return r.O(i)},c=self.webpackChunkdocs=self.webpackChunkdocs||[];c.forEach(a.bind(null,0)),c.push=a.bind(null,c.push.bind(c))})()})(); \ No newline at end of file diff --git a/docs/dev/assets/js/runtime~main.dcb01b7b.js b/docs/dev/assets/js/runtime~main.dcb01b7b.js new file mode 100644 index 00000000..5a02baa5 --- /dev/null +++ b/docs/dev/assets/js/runtime~main.dcb01b7b.js @@ -0,0 +1 @@ +(()=>{"use strict";var e,a,c,d,f,b={},t={};function r(e){var a=t[e];if(void 0!==a)return a.exports;var c=t[e]={exports:{}};return b[e].call(c.exports,c,c.exports,r),c.exports}r.m=b,e=[],r.O=(a,c,d,f)=>{if(!c){var b=1/0;for(i=0;i<e.length;i++){c=e[i][0],d=e[i][1],f=e[i][2];for(var t=!0,o=0;o<c.length;o++)(!1&f||b>=f)&&Object.keys(r.O).every((e=>r.O[e](c[o])))?c.splice(o--,1):(t=!1,f<b&&(b=f));if(t){e.splice(i--,1);var n=d();void 0!==n&&(a=n)}}return a}f=f||0;for(var i=e.length;i>0&&e[i-1][2]>f;i--)e[i]=e[i-1];e[i]=[c,d,f]},r.n=e=>{var a=e&&e.__esModule?()=>e.default:()=>e;return r.d(a,{a:a}),a},c=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__,r.t=function(e,d){if(1&d&&(e=this(e)),8&d)return e;if("object"==typeof e&&e){if(4&d&&e.__esModule)return e;if(16&d&&"function"==typeof e.then)return e}var f=Object.create(null);r.r(f);var b={};a=a||[null,c({}),c([]),c(c)];for(var t=2&d&&e;"object"==typeof t&&!~a.indexOf(t);t=c(t))Object.getOwnPropertyNames(t).forEach((a=>b[a]=()=>e[a]));return b.default=()=>e,r.d(f,b),f},r.d=(e,a)=>{for(var c in a)r.o(a,c)&&!r.o(e,c)&&Object.defineProperty(e,c,{enumerable:!0,get:a[c]})},r.f={},r.e=e=>Promise.all(Object.keys(r.f).reduce(((a,c)=>(r.f[c](e,a),a)),[])),r.u=e=>"assets/js/"+({16:"376759eb",53:"935f2afb",104:"92dd0956",127:"2bed8b6f",156:"a5971d1a",203:"9624c11c",221:"e06425d1",314:"fa5466f2",340:"a7e6874c",438:"f81fb924",560:"edb9b0b8",636:"afebe5f1",689:"15868c40",777:"db0d9cb2",811:"f18bbaf6",846:"02bfc02d",930:"e5f53749",950:"a7153b78",998:"acfabe81",1003:"4aa001c0",1164:"dc8f2f6c",1279:"06322d53",1354:"9017a27d",1375:"345c600d",1395:"25196878",1452:"b1f622a1",1470:"9c5158ac",1500:"cdaafcc9",1530:"ee244d12",1610:"bac2c42d",1715:"a2ab2bad",1768:"7d170ab0",1788:"9bbfd40a",1827:"6870612e",1849:"aff456d7",1929:"d077f377",1965:"01a12966",1983:"a4bc1622",2047:"7310a4fe",2177:"a9e26133",2215:"1cdac986",2305:"194e858c",2365:"160faf1d",2463:"daad7c1d",2535:"814f3328",2616:"68c17ba1",2627:"89fc5f00",2690:"f914cfe8",2691:"3cfbc8af",2809:"2d9479c4",2842:"3961e600",2988:"e68f8ad6",3004:"5a8c7729",3020:"d7a493e6",3058:"2f7bd5c8",3089:"a6aa9e1f",3151:"c2e5ab4f",3159:"77cc432a",3188:"234733fd",3193:"81cb5929",3216:"b7da1136",3317:"5242ac2d",3337:"1ce64703",3344:"ff7b8d8e",3357:"44954150",3367:"81bf07f5",3371:"16815c2a",3372:"0ea64360",3390:"85afcbde",3394:"7e0ce508",3454:"0c94c658",3475:"0c18287f",3554:"078a6308",3575:"54df49be",3587:"b6bceaff",3608:"9e4087bc",3619:"97081ee7",3704:"93e7cfc5",3726:"07294b24",3768:"8417e7a5",3851:"772fc39d",3905:"8be9dc67",3944:"768594c0",4004:"2a4d41ed",4013:"01a85c17",4033:"f9553497",4046:"1798d0b3",4176:"d4251823",4213:"e10f7c24",4244:"41718851",4450:"1c41eae2",4452:"7457c448",4538:"463dc00f",4561:"ae967838",4637:"ebfca923",4706:"f6ca3de5",4734:"ee6dd1d2",4746:"5058a078",4785:"20e2ece2",4792:"e329d2fa",4818:"4d9df5b1",4875:"67002961",4909:"1e4e1fb6",4945:"1a3daba8",5085:"e46b95eb",5123:"98306a23",5297:"b57ca7d5",5315:"0ccdbf16",5391:"a8d11699",5401:"bfb64759",5458:"72c409f7",5558:"5eabd930",5589:"e158c27a",5667:"02aa4531",5682:"402da695",5737:"8c7569e5",5756:"81f6aa2c",5843:"8d6e802b",5889:"ebe12d94",5906:"b209ab8a",5944:"2c0d2b92",5952:"c251e734",5962:"79c85cd0",6017:"9d02ad31",6044:"db5d1fe1",6094:"50818478",6103:"ccc49370",6132:"3245f64b",6155:"952dfacb",6186:"dc5cc32c",6199:"153137de",6212:"ae3eef3e",6350:"89739c9f",6448:"c9d1eb08",6470:"f33f2c05",6489:"928a5d6f",6508:"482a391c",6533:"e4f709d1",6555:"b3de9677",6669:"920bdc78",6685:"017e736e",6694:"df2eb7da",6741:"4be897c9",6811:"faca410e",6971:"c377a04b",6979:"cf518063",6989:"a470b55c",7062:"77b9a1ed",7123:"44f79c8d",7194:"56ccfc32",7219:"89196f72",7233:"4f675ae9",7257:"f1257df2",7332:"c97e0540",7344:"980f8d5e",7385:"4a9d0f4c",7449:"83b912d4",7462:"0b621d16",7486:"5cdfb1f2",7496:"ba43b2d5",7513:"65722401",7518:"6ba4a510",7669:"9a1c8bc6",7677:"037683de",7785:"26c0a43c",7793:"23f93eeb",7839:"a6b6486c",7870:"bb43b8ce",7901:"d5aa49f9",7918:"17896441",8142:"2b265210",8215:"6ff6e7c9",8253:"6e772156",8506:"1c93e70c",8599:"6c5232c2",8610:"6875c492",8662:"d941076d",8697:"d8746e52",8851:"eceb3b9b",8894:"9a3e57da",8905:"7ea7f008",9020:"31526b20",9054:"b7661aba",9063:"007e0817",9101:"e519b4b4",9132:"4add0c6c",9147:"1b8ca8c3",9162:"488157d7",9266:"c5b25a7c",9385:"c5e834bc",9502:"67d1434e",9514:"1be78505",9586:"d97b7d4d",9600:"0544f90b",9616:"dafe2799",9643:"385623dc",9661:"c30ee527",9667:"38a882bf",9695:"40386700",9722:"8cf2dd9c",9760:"65f7a26b",9818:"a6177d3d",9903:"31f1dbb1",9978:"5df6e7df",9986:"aa1cf9a2",9992:"86a1f821"}[e]||e)+"."+{16:"f0143aca",53:"a58568b0",104:"1a95dd6f",127:"6c35bd0b",156:"2ddaa6c8",203:"2d436350",221:"24dae45f",314:"6cae2b31",340:"61f09544",438:"9105c0e1",560:"43f97c7e",636:"a6dcb42f",689:"bc24a74e",777:"4a41ead9",811:"af600d96",846:"a846ad63",930:"64c9f090",950:"7d21bcc4",998:"40e0679f",1003:"e6e02f8e",1164:"4e8f9014",1279:"19c4e18a",1354:"158ddff3",1375:"32f2c407",1395:"63ed3781",1452:"6224d282",1470:"3b686c7e",1500:"b6bb1966",1530:"2429282b",1610:"6a0971e5",1715:"17af2301",1768:"0bfdf1ec",1788:"df08973b",1827:"1a535468",1849:"dbcb844c",1929:"02c130f9",1965:"e624b5b0",1983:"cf5c3efa",2047:"28a29c7e",2177:"2fa70c63",2215:"927e6f22",2305:"8683b66e",2365:"76526d55",2463:"7770827c",2535:"a7d57a47",2616:"c299310a",2627:"23609afa",2690:"fcea67b6",2691:"c550c228",2809:"2743ad51",2842:"fde60b55",2988:"a9305a10",3004:"4efe6d0f",3020:"ca5719aa",3058:"8d2baaf0",3089:"845cad8c",3151:"448fdf11",3159:"45eddf85",3188:"e54974f4",3193:"f3f7b9c3",3216:"cefea56d",3317:"c86c6573",3337:"7bdf8e65",3344:"8b7db25b",3357:"821b1811",3367:"2b3ed4fb",3371:"8833df51",3372:"9888bb74",3390:"23543644",3394:"6e093c40",3454:"87f78ad3",3475:"74853166",3554:"129076c2",3575:"7687342d",3587:"d3ee5eff",3608:"064ee4cb",3619:"926834d2",3704:"4727baaf",3726:"6bb83857",3768:"ac10b2b2",3851:"9f22ee89",3905:"f807be43",3944:"ea58dbe0",4004:"b9fde1cf",4013:"44f4b362",4033:"5f4a3317",4046:"f50bdee5",4176:"d52e2d5c",4213:"c2426f9c",4244:"98e01ad8",4450:"308271a0",4452:"b5ef6742",4538:"03b52d57",4561:"542e2305",4637:"eef347af",4706:"0373150b",4734:"2425cf24",4746:"5dcf9c7d",4785:"93932fae",4792:"c6a1a21f",4818:"b04a94c6",4875:"cc17f56d",4909:"bb6129fc",4945:"350ec93b",4972:"96c55074",5085:"9d24edd6",5123:"103a8ca0",5297:"d12fa993",5315:"419ff39d",5391:"8b646c5f",5401:"1600775d",5458:"2eac6138",5558:"4ffd8fa6",5589:"6ddfe5ad",5667:"8256d16e",5682:"ec89f648",5737:"8272001e",5756:"bef6994b",5843:"5b5fd69a",5889:"173ebcc7",5906:"75d78f76",5944:"20aa9f60",5952:"146b0a67",5962:"04df9409",6017:"a163b5d7",6044:"385880ad",6048:"fb279e73",6094:"bf5eb4bf",6103:"d9c41d1e",6132:"692fef03",6155:"b4199040",6186:"22e17cc7",6199:"f7e21a8d",6212:"1bbc9c63",6350:"652f9696",6448:"589784fb",6470:"19133a69",6489:"ea3e3aee",6508:"56aaed9a",6533:"e288a898",6555:"87a3c41b",6669:"d82f3005",6685:"5c763729",6694:"5d459d62",6741:"0aca83b7",6811:"041d0b7a",6971:"c618e95e",6979:"9ef405bb",6989:"df88a961",7062:"cb063d01",7123:"8067102b",7194:"985c6211",7219:"8e456573",7233:"8448a496",7257:"433d18f6",7332:"2d90c993",7344:"5ec88372",7385:"02073b85",7449:"105ec02d",7462:"fff33ba6",7486:"5091e89c",7496:"9c203679",7513:"0cb7eac9",7518:"297732b3",7669:"63b5d495",7677:"06e9c439",7785:"afeae6c6",7793:"ef1aaac9",7839:"0f896e86",7870:"db808b9c",7901:"f981f00d",7918:"fc8b9592",8142:"4d93b412",8215:"5e675e3b",8253:"177df649",8506:"55f9488c",8599:"aa9f007e",8610:"f37b7b5c",8662:"7ae86871",8697:"872683ec",8851:"58ad7533",8894:"0bb59fe9",8905:"a6140792",9020:"09aa7811",9054:"27060343",9063:"aa07ff6f",9101:"d1af950d",9132:"b0b2e0b3",9147:"acd94369",9162:"5b53d945",9266:"9ed70bb6",9385:"963047f0",9502:"a98807cd",9514:"efcc4864",9586:"84bbc081",9600:"0aa1894c",9616:"5c248ad4",9643:"19f07cd6",9661:"9b4ec100",9667:"2d029f6e",9695:"15a66133",9722:"230aa8cc",9760:"67640917",9785:"ee036d0a",9818:"a62f8322",9903:"56c79677",9978:"050a254b",9986:"b51e283d",9992:"770c5c36"}[e]+".js",r.miniCssF=e=>{},r.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),r.o=(e,a)=>Object.prototype.hasOwnProperty.call(e,a),d={},f="docs:",r.l=(e,a,c,b)=>{if(d[e])d[e].push(a);else{var t,o;if(void 0!==c)for(var n=document.getElementsByTagName("script"),i=0;i<n.length;i++){var u=n[i];if(u.getAttribute("src")==e||u.getAttribute("data-webpack")==f+c){t=u;break}}t||(o=!0,(t=document.createElement("script")).charset="utf-8",t.timeout=120,r.nc&&t.setAttribute("nonce",r.nc),t.setAttribute("data-webpack",f+c),t.src=e),d[e]=[a];var l=(a,c)=>{t.onerror=t.onload=null,clearTimeout(s);var f=d[e];if(delete d[e],t.parentNode&&t.parentNode.removeChild(t),f&&f.forEach((e=>e(c))),a)return a(c)},s=setTimeout(l.bind(null,void 0,{type:"timeout",target:t}),12e4);t.onerror=l.bind(null,t.onerror),t.onload=l.bind(null,t.onload),o&&document.head.appendChild(t)}},r.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.p="/docs/dev/",r.gca=function(e){return e={17896441:"7918",25196878:"1395",40386700:"9695",41718851:"4244",44954150:"3357",50818478:"6094",65722401:"7513",67002961:"4875","376759eb":"16","935f2afb":"53","92dd0956":"104","2bed8b6f":"127",a5971d1a:"156","9624c11c":"203",e06425d1:"221",fa5466f2:"314",a7e6874c:"340",f81fb924:"438",edb9b0b8:"560",afebe5f1:"636","15868c40":"689",db0d9cb2:"777",f18bbaf6:"811","02bfc02d":"846",e5f53749:"930",a7153b78:"950",acfabe81:"998","4aa001c0":"1003",dc8f2f6c:"1164","06322d53":"1279","9017a27d":"1354","345c600d":"1375",b1f622a1:"1452","9c5158ac":"1470",cdaafcc9:"1500",ee244d12:"1530",bac2c42d:"1610",a2ab2bad:"1715","7d170ab0":"1768","9bbfd40a":"1788","6870612e":"1827",aff456d7:"1849",d077f377:"1929","01a12966":"1965",a4bc1622:"1983","7310a4fe":"2047",a9e26133:"2177","1cdac986":"2215","194e858c":"2305","160faf1d":"2365",daad7c1d:"2463","814f3328":"2535","68c17ba1":"2616","89fc5f00":"2627",f914cfe8:"2690","3cfbc8af":"2691","2d9479c4":"2809","3961e600":"2842",e68f8ad6:"2988","5a8c7729":"3004",d7a493e6:"3020","2f7bd5c8":"3058",a6aa9e1f:"3089",c2e5ab4f:"3151","77cc432a":"3159","234733fd":"3188","81cb5929":"3193",b7da1136:"3216","5242ac2d":"3317","1ce64703":"3337",ff7b8d8e:"3344","81bf07f5":"3367","16815c2a":"3371","0ea64360":"3372","85afcbde":"3390","7e0ce508":"3394","0c94c658":"3454","0c18287f":"3475","078a6308":"3554","54df49be":"3575",b6bceaff:"3587","9e4087bc":"3608","97081ee7":"3619","93e7cfc5":"3704","07294b24":"3726","8417e7a5":"3768","772fc39d":"3851","8be9dc67":"3905","768594c0":"3944","2a4d41ed":"4004","01a85c17":"4013",f9553497:"4033","1798d0b3":"4046",d4251823:"4176",e10f7c24:"4213","1c41eae2":"4450","7457c448":"4452","463dc00f":"4538",ae967838:"4561",ebfca923:"4637",f6ca3de5:"4706",ee6dd1d2:"4734","5058a078":"4746","20e2ece2":"4785",e329d2fa:"4792","4d9df5b1":"4818","1e4e1fb6":"4909","1a3daba8":"4945",e46b95eb:"5085","98306a23":"5123",b57ca7d5:"5297","0ccdbf16":"5315",a8d11699:"5391",bfb64759:"5401","72c409f7":"5458","5eabd930":"5558",e158c27a:"5589","02aa4531":"5667","402da695":"5682","8c7569e5":"5737","81f6aa2c":"5756","8d6e802b":"5843",ebe12d94:"5889",b209ab8a:"5906","2c0d2b92":"5944",c251e734:"5952","79c85cd0":"5962","9d02ad31":"6017",db5d1fe1:"6044",ccc49370:"6103","3245f64b":"6132","952dfacb":"6155",dc5cc32c:"6186","153137de":"6199",ae3eef3e:"6212","89739c9f":"6350",c9d1eb08:"6448",f33f2c05:"6470","928a5d6f":"6489","482a391c":"6508",e4f709d1:"6533",b3de9677:"6555","920bdc78":"6669","017e736e":"6685",df2eb7da:"6694","4be897c9":"6741",faca410e:"6811",c377a04b:"6971",cf518063:"6979",a470b55c:"6989","77b9a1ed":"7062","44f79c8d":"7123","56ccfc32":"7194","89196f72":"7219","4f675ae9":"7233",f1257df2:"7257",c97e0540:"7332","980f8d5e":"7344","4a9d0f4c":"7385","83b912d4":"7449","0b621d16":"7462","5cdfb1f2":"7486",ba43b2d5:"7496","6ba4a510":"7518","9a1c8bc6":"7669","037683de":"7677","26c0a43c":"7785","23f93eeb":"7793",a6b6486c:"7839",bb43b8ce:"7870",d5aa49f9:"7901","2b265210":"8142","6ff6e7c9":"8215","6e772156":"8253","1c93e70c":"8506","6c5232c2":"8599","6875c492":"8610",d941076d:"8662",d8746e52:"8697",eceb3b9b:"8851","9a3e57da":"8894","7ea7f008":"8905","31526b20":"9020",b7661aba:"9054","007e0817":"9063",e519b4b4:"9101","4add0c6c":"9132","1b8ca8c3":"9147","488157d7":"9162",c5b25a7c:"9266",c5e834bc:"9385","67d1434e":"9502","1be78505":"9514",d97b7d4d:"9586","0544f90b":"9600",dafe2799:"9616","385623dc":"9643",c30ee527:"9661","38a882bf":"9667","8cf2dd9c":"9722","65f7a26b":"9760",a6177d3d:"9818","31f1dbb1":"9903","5df6e7df":"9978",aa1cf9a2:"9986","86a1f821":"9992"}[e]||e,r.p+r.u(e)},(()=>{var e={1303:0,532:0};r.f.j=(a,c)=>{var d=r.o(e,a)?e[a]:void 0;if(0!==d)if(d)c.push(d[2]);else if(/^(1303|532)$/.test(a))e[a]=0;else{var f=new Promise(((c,f)=>d=e[a]=[c,f]));c.push(d[2]=f);var b=r.p+r.u(a),t=new Error;r.l(b,(c=>{if(r.o(e,a)&&(0!==(d=e[a])&&(e[a]=void 0),d)){var f=c&&("load"===c.type?"missing":c.type),b=c&&c.target&&c.target.src;t.message="Loading chunk "+a+" failed.\n("+f+": "+b+")",t.name="ChunkLoadError",t.type=f,t.request=b,d[1](t)}}),"chunk-"+a,a)}},r.O.j=a=>0===e[a];var a=(a,c)=>{var d,f,b=c[0],t=c[1],o=c[2],n=0;if(b.some((a=>0!==e[a]))){for(d in t)r.o(t,d)&&(r.m[d]=t[d]);if(o)var i=o(r)}for(a&&a(c);n<b.length;n++)f=b[n],r.o(e,f)&&e[f]&&e[f][0](),e[f]=0;return r.O(i)},c=self.webpackChunkdocs=self.webpackChunkdocs||[];c.forEach(a.bind(null,0)),c.push=a.bind(null,c.push.bind(c))})()})(); \ No newline at end of file diff --git a/docs/dev/ast-builder/expressions/conditional/index.html b/docs/dev/ast-builder/expressions/conditional/index.html index 846b5d90..9d78f3f4 100644 --- a/docs/dev/ast-builder/expressions/conditional/index.html +++ b/docs/dev/ast-builder/expressions/conditional/index.html @@ -1,17 +1,17 @@ <!doctype html> -<html lang="en" dir="ltr" class="docs-wrapper docs-doc-page docs-version-current plugin-docs plugin-id-default docs-doc-id-ast-builder/expressions/conditional"> +<html lang="en" dir="ltr" class="docs-wrapper docs-doc-page docs-version-current plugin-docs plugin-id-default docs-doc-id-ast-builder/expressions/conditional" data-has-hydrated="false"> <head> <meta charset="UTF-8"> -<meta name="generator" content="Docusaurus v2.4.1"> +<meta name="generator" content="Docusaurus v2.4.3"> <title data-rh="true">Conditional | GlueSQL - - - + + + - - + + \ No newline at end of file diff --git a/docs/dev/ast-builder/expressions/nested/index.html b/docs/dev/ast-builder/expressions/nested/index.html index 4c2b9a05..44cb8bbf 100644 --- a/docs/dev/ast-builder/expressions/nested/index.html +++ b/docs/dev/ast-builder/expressions/nested/index.html @@ -1,17 +1,17 @@ - + - + Nested | GlueSQL - - - + + + - - + + \ No newline at end of file diff --git a/docs/dev/ast-builder/expressions/operator-based/index.html b/docs/dev/ast-builder/expressions/operator-based/index.html index c202766b..67af23c9 100644 --- a/docs/dev/ast-builder/expressions/operator-based/index.html +++ b/docs/dev/ast-builder/expressions/operator-based/index.html @@ -1,17 +1,17 @@ - + - + Operator Based | GlueSQL - - - + + + - - + + \ No newline at end of file diff --git a/docs/dev/ast-builder/expressions/pattern-matching/index.html b/docs/dev/ast-builder/expressions/pattern-matching/index.html index f7602f7b..b74bafbe 100644 --- a/docs/dev/ast-builder/expressions/pattern-matching/index.html +++ b/docs/dev/ast-builder/expressions/pattern-matching/index.html @@ -1,17 +1,17 @@ - + - + Pattern Matching | GlueSQL - - - + + +

Pattern Matching

Pattern matching is a crucial feature in SQL that allows you to match rows based on specific patterns in a column. GlueSQL provides 4 pattern matching operators: like, ilike, not_like, and not_ilike.

Here's how you can use these operators with two special characters:

  • %: Matches any number of characters, including zero characters
  • _: Matches exactly one character

LIKE Operator

The like operator is used in a WHERE clause to search for a specified pattern in a column.

Here is an example:

let actual = table("Category")
.select()
.filter(
col("name")
.like(text("D%"))
.or(col("name").like(text("M___"))),
)
.execute(glue)
.await;

In this example, the query will return all rows from the Category table where the name column starts with "D" or where the name is exactly four characters long and starts with "M".

ILIKE Operator

The ilike operator is used in a WHERE clause to search for a specified pattern in a column, regardless of case.

Here is an example:

let actual = table("Category")
.select()
.filter(
col("name")
.ilike(text("D%"))
.or(col("name").ilike(text("M___"))),
)
.execute(glue)
.await;

In this example, the query will return all rows from the Category table where the name column starts with "D" or "d", or where the name is exactly four characters long and starts with "M" or "m".

NOT_LIKE Operator

The not_like operator is used in a WHERE clause to match rows that don't follow the specific pattern.

Here is an example:

let actual = table("Category")
.select()
.filter(
col("name")
.not_like(text("D%"))
.and(col("name").not_like(text("M___"))),
)
.execute(glue)
.await;

In this example, the query will return all rows from the Category table where the name column does not start with "D" and the name is not exactly four characters long and does not start with "M".

NOT_ILIKE Operator

The not_ilike operator is used in a WHERE clause to match rows that don't follow the specific pattern, regardless of case.

Here is an example:

let actual = table("Category")
.select()
.filter(
col("name")
.not_ilike(text("D%"))
.and(col("name").not_ilike(text("M___"))),
)
.execute(glue)
.await;

In this example, the query will return all rows from the Category table where the name column does not start with "D" or "d", and the name is not exactly four characters long and does not start with "M" or "m".

- - + + \ No newline at end of file diff --git a/docs/dev/ast-builder/expressions/value-checking/index.html b/docs/dev/ast-builder/expressions/value-checking/index.html index 2d0ab40b..afc164e3 100644 --- a/docs/dev/ast-builder/expressions/value-checking/index.html +++ b/docs/dev/ast-builder/expressions/value-checking/index.html @@ -1,17 +1,17 @@ - + - + Value Checking | GlueSQL - - - + + + - - + + \ No newline at end of file diff --git a/docs/dev/ast-builder/functions/date-&-time/conversion/index.html b/docs/dev/ast-builder/functions/date-&-time/conversion/index.html index dad2ddcc..6b900815 100644 --- a/docs/dev/ast-builder/functions/date-&-time/conversion/index.html +++ b/docs/dev/ast-builder/functions/date-&-time/conversion/index.html @@ -1,17 +1,17 @@ - + - + Conversion | GlueSQL - - - + + +

Conversion

GlueSQL provides date and time conversion functions that allow you to convert text data to datetime data types such as Date, Time, and Timestamp. These functions are to_date, to_time, and to_timestamp.

For this tutorial, we assume there's a table named Visitor with various columns including visit_date, visit_time, and visit_time_stamp which are of TEXT type.

Date Conversion - to_date

The to_date function converts a text string to a date.

There are two ways to call the to_date function in GlueSQL:

let actual = table("Visitor")
.select()
.project("id")
.project("name")
.project(col("visit_date").to_date("'%Y-%m-%d'")) // Method 1: Calling the to_date method on a column
.project(to_date("visit_date", "'%Y-%m-%d'")) // Method 2: Using the to_date function directly
.execute(glue)
.await;

Time Conversion - to_time

The to_time function converts a text string to a time.

There are two ways to call the to_time function in GlueSQL:

let actual = table("Visitor")
.select()
.project("id")
.project("name")
.project(col("visit_time").to_time("'%H:%M:%S'")) // Method 1: Calling the to_time method on a column
.project(to_time("visit_time", "'%H:%M:%S'")) // Method 2: Using the to_time function directly
.execute(glue)
.await;

Timestamp Conversion - to_timestamp

The to_timestamp function converts a text string to a timestamp.

There are two ways to call the to_timestamp function in GlueSQL:

let actual = table("Visitor")
.select()
.project("id")
.project("name")
.project(col("visit_time_stamp").to_timestamp("'%Y-%m-%d %H:%M:%S'")) // Method 1: Calling the to_timestamp method on a column
.project(to_timestamp("visit_time_stamp", "'%Y-%m-%d %H:%M:%S'")) // Method 2: Using the to_timestamp function directly
.execute(glue)
.await;
- - + + \ No newline at end of file diff --git a/docs/dev/ast-builder/functions/date-&-time/current-date-and-time/index.html b/docs/dev/ast-builder/functions/date-&-time/current-date-and-time/index.html index 8a00db71..e9a493c5 100644 --- a/docs/dev/ast-builder/functions/date-&-time/current-date-and-time/index.html +++ b/docs/dev/ast-builder/functions/date-&-time/current-date-and-time/index.html @@ -1,17 +1,17 @@ - + - + Current Date and Time | GlueSQL - - - + + +

Current Date and Time

GlueSQL provides a function to get the current date and time: now.

Now - now

The now function returns the current date and time.

let actual = table("Record")
.select()
.filter(col("time_stamp").gt(now())) // select rows where "time_stamp" is later than current time
.project("id, time_stamp")
.execute(glue)
.await;

In the above example, the filter method uses now to select rows where the "time_stamp" column is later than the current time.

When inserting data into a table, you can use the now function to record the current time:

let actual = table("Record")
.insert()
.values(vec![
"1, '2022-12-23T05:30:11.164932863'",
"2, NOW()", // Inserts the current time
"3, '9999-12-31T23:59:40.364832862'",
])
.execute(glue)
.await;

In the example above, the "time_stamp" column for the row with id 2 is set to the current time at the moment of insertion.

- - + + \ No newline at end of file diff --git a/docs/dev/ast-builder/functions/date-&-time/date-and-time-extraction/index.html b/docs/dev/ast-builder/functions/date-&-time/date-and-time-extraction/index.html index 306175e7..fe066210 100644 --- a/docs/dev/ast-builder/functions/date-&-time/date-and-time-extraction/index.html +++ b/docs/dev/ast-builder/functions/date-&-time/date-and-time-extraction/index.html @@ -1,17 +1,17 @@ - + - + Date and Time Extraction | GlueSQL - - - + + + - - + + \ No newline at end of file diff --git a/docs/dev/ast-builder/functions/date-&-time/formatting/index.html b/docs/dev/ast-builder/functions/date-&-time/formatting/index.html index ef250b04..883cf2a1 100644 --- a/docs/dev/ast-builder/functions/date-&-time/formatting/index.html +++ b/docs/dev/ast-builder/functions/date-&-time/formatting/index.html @@ -1,17 +1,17 @@ - + - + Formatting | GlueSQL - - - + + +

Formatting

In GlueSQL, you can format date, time, and timestamp values to a specific format using the format function.

For this tutorial, we assume there's a table named Visitor with columns id, name, visit_date, visit_time, and visit_timestamp.

Formatting Date

The format function can be used to change the format of a date.

let actual = table("Visitor")
.select()
.project("name")
.project("visit_date")
.project(col("visit_date").format(text("%Y-%m"))) // Formats the visit_date to the year-month format
.project(format(col("visit_date"), text("%m"))) // Formats the visit_date to the month format
.execute(glue)
.await;

Formatting Time

The format function can also be used to change the format of a time.

let actual = table("Visitor")
.select()
.project("name")
.project("visit_time")
.project(col("visit_time").format(text("%H:%M:%S"))) // Formats the visit_time to the hour-minute-second format
.project(format(col("visit_time"), text("%M:%S"))) // Formats the visit_time to the minute-second format
.execute(glue)
.await;

Formatting Timestamp

The format function can be used to change the format of a timestamp.

let actual = table("Visitor")
.select()
.project("name")
.project("visit_timestamp")
.project(col("visit_timestamp").format(text("%Y-%m-%d %H:%M:%S"))) // Formats the visit_timestamp to the year-month-date hour-minute-second format
.project(format(col("visit_timestamp"), text("%Y-%m-%d %H:%M:%S"))) // Formats the visit_timestamp to the year-month-date hour-minute-second format
.execute(glue)
.await;
- - + + \ No newline at end of file diff --git a/docs/dev/ast-builder/functions/geometry/coordinate-extraction/index.html b/docs/dev/ast-builder/functions/geometry/coordinate-extraction/index.html index bf049f0b..f485a405 100644 --- a/docs/dev/ast-builder/functions/geometry/coordinate-extraction/index.html +++ b/docs/dev/ast-builder/functions/geometry/coordinate-extraction/index.html @@ -1,17 +1,17 @@ - + - + Coordinate Extraction | GlueSQL - - - + + + - - + + \ No newline at end of file diff --git a/docs/dev/ast-builder/functions/geometry/distance-calculation/index.html b/docs/dev/ast-builder/functions/geometry/distance-calculation/index.html index 1201800a..48c4f2ad 100644 --- a/docs/dev/ast-builder/functions/geometry/distance-calculation/index.html +++ b/docs/dev/ast-builder/functions/geometry/distance-calculation/index.html @@ -1,17 +1,17 @@ - + - + Distance Calculation | GlueSQL - - - + + + - - + + \ No newline at end of file diff --git a/docs/dev/ast-builder/functions/geometry/point-creation/index.html b/docs/dev/ast-builder/functions/geometry/point-creation/index.html index 9319c572..8a79772e 100644 --- a/docs/dev/ast-builder/functions/geometry/point-creation/index.html +++ b/docs/dev/ast-builder/functions/geometry/point-creation/index.html @@ -1,17 +1,17 @@ - + - + Point Creation | GlueSQL - - - + + + - - + + \ No newline at end of file diff --git a/docs/dev/ast-builder/functions/list-&-map/list-and-map-concatenation/index.html b/docs/dev/ast-builder/functions/list-&-map/list-and-map-concatenation/index.html index 33b34d59..fb68a911 100644 --- a/docs/dev/ast-builder/functions/list-&-map/list-and-map-concatenation/index.html +++ b/docs/dev/ast-builder/functions/list-&-map/list-and-map-concatenation/index.html @@ -1,17 +1,17 @@ - + - + List and Map Concatenation | GlueSQL - - - + + + - - + + \ No newline at end of file diff --git a/docs/dev/ast-builder/functions/list-&-map/list-manipulation/index.html b/docs/dev/ast-builder/functions/list-&-map/list-manipulation/index.html index 6a8e9b80..ab07f713 100644 --- a/docs/dev/ast-builder/functions/list-&-map/list-manipulation/index.html +++ b/docs/dev/ast-builder/functions/list-&-map/list-manipulation/index.html @@ -1,17 +1,17 @@ - + - + List Manipulation | GlueSQL - - - + + + - - + + \ No newline at end of file diff --git a/docs/dev/ast-builder/functions/math/basic-arithmetic/index.html b/docs/dev/ast-builder/functions/math/basic-arithmetic/index.html index 84f65b9c..7e193ccf 100644 --- a/docs/dev/ast-builder/functions/math/basic-arithmetic/index.html +++ b/docs/dev/ast-builder/functions/math/basic-arithmetic/index.html @@ -1,17 +1,17 @@ - + - + Basic Arithmetic | GlueSQL - - - + + +

Basic Arithmetic

GlueSQL provides a number of basic arithmetic operations such as absolute value (abs), division (divide), modulo (modulo), greatest common divisor (gcd), and least common multiple (lcm).

For this tutorial, we assume there's a table named Number with columns id and number.

Absolute Value - ABS

The abs function returns the absolute value of a number.

let actual = values(vec!["0, 0", "1, -3", "2, 4", "3, -29"])
.alias_as("number")
.select()
.project("column1")
.project(abs("column2")) // Takes the absolute value of column2
.project(col("column2").abs()) // Takes the absolute value of column2
.execute(glue)
.await;

Division - DIV

The divide function divides one number by another.

let actual = table("Number")
.select()
.project("id")
.project(divide("number", 3)) // Divides the number by 3
.project(divide(col("number"), 3)) // Divides the number by 3
.execute(glue)
.await;

Modulo - MOD

The modulo function returns the remainder of one number divided by another.

let actual = table("Number")
.select()
.project("id")
.project(modulo("number", 4)) // Gets the remainder of number divided by 4
.project(modulo(col("number"), 4)) // Gets the remainder of number divided by 4
.execute(glue)
.await;

Greatest Common Divisor - GCD

The gcd function returns the greatest common divisor of two numbers.

let actual = table("Number")
.select()
.project("id")
.project(gcd("number", 12)) // Gets the GCD of number and 12
.project(gcd(col("number"), 12)) // Gets the GCD of number and 12
.execute(glue)
.await;

Least Common Multiple - LCM

The lcm function returns the least common multiple of two numbers.

let actual = table("Number")
.select()
.project("id")
.project(lcm("number", 3)) // Gets the LCM of number and 3
.project(lcm(col("number"), 3)) // Gets the LCM of number and 3
.execute(glue)
.await;
- - + + \ No newline at end of file diff --git a/docs/dev/ast-builder/functions/math/conversion/index.html b/docs/dev/ast-builder/functions/math/conversion/index.html index 13e91272..2cf38fed 100644 --- a/docs/dev/ast-builder/functions/math/conversion/index.html +++ b/docs/dev/ast-builder/functions/math/conversion/index.html @@ -1,17 +1,17 @@ - + - + Conversion | GlueSQL - - - + + +

Conversion

The AST (Abstract Syntax Tree) Builder in GlueSQL provides mathematical conversion functions like degrees and radians. These functions convert angles expressed in radians to degrees and vice versa.

For the sake of this tutorial, we'll assume there's a table named Number with columns input (of type INTEGER) and number (of type FLOAT).

Degrees Function

The degrees function converts an angle from radians to degrees.

You can call this function in two ways in GlueSQL:

let actual = table("Number")
.select()
.project("input")
.project(degrees("number")) // Method 1: Using the degrees function directly
.project(col("number").degrees()) // Method 2: Calling the degrees method on a column
.execute(glue)
.await;

Radians Function

The radians function converts an angle from degrees to radians.

Just like with the degrees function, there are two ways to call this function:

let actual = table("Number")
.select()
.project("input")
.project(radians("number")) // Method 1: Using the radians function directly
.project(col("number").radians()) // Method 2: Calling the radians method on a column
.execute(glue)
.await;
- - + + \ No newline at end of file diff --git a/docs/dev/ast-builder/functions/math/logarithmic-and-exponential/index.html b/docs/dev/ast-builder/functions/math/logarithmic-and-exponential/index.html index b821557a..e6d1928a 100644 --- a/docs/dev/ast-builder/functions/math/logarithmic-and-exponential/index.html +++ b/docs/dev/ast-builder/functions/math/logarithmic-and-exponential/index.html @@ -1,17 +1,17 @@ - + - + Logarithmic and Exponential | GlueSQL - - - + + +

Logarithmic and Exponential

Todo

- EXP: Returns e raised to the power of a specified number.
- LN: Returns the natural logarithm of a number.
- LOG: Returns the logarithm of a number to a specified base.
- LOG10: Returns the base-10 logarithm of a number.
- LOG2: Returns the base-2 logarithm of a number.
- POWER: Raises a number to the power of another number.
- - + + \ No newline at end of file diff --git a/docs/dev/ast-builder/functions/math/rounding/index.html b/docs/dev/ast-builder/functions/math/rounding/index.html index b60ba3b3..e88aad22 100644 --- a/docs/dev/ast-builder/functions/math/rounding/index.html +++ b/docs/dev/ast-builder/functions/math/rounding/index.html @@ -1,17 +1,17 @@ - + - + Rounding | GlueSQL - - - + + +

Rounding

The AST (Abstract Syntax Tree) Builder in GlueSQL provides several mathematical functions, including round, ceil, and floor. These functions are used to perform rounding operations on floating-point numbers.

For the sake of this tutorial, we'll assume there's a table named Number with columns id (of type INTEGER) and number (of type FLOAT).

Ceil Function

The ceil function rounds up the number to the nearest integer value that is greater than or equal to number.

In GlueSQL, you can call this function in two ways. Both methods are shown below:

let actual = table("Number")
.select()
.project("id")
.project(ceil("number")) // Method 1: Using the ceil function directly
.project(col("number").ceil()) // Method 2: Calling the ceil method on a column
.execute(glue)
.await;

Floor Function

The floor function rounds down the number to the nearest integer value that is less than or equal to number.

Again, there are two ways to call this function in GlueSQL:

let actual = table("Number")
.select()
.project("id")
.project(floor("number")) // Method 1: Using the floor function directly
.project(col("number").floor()) // Method 2: Calling the floor method on a column
.execute(glue)
.await;

Round Function

The round function rounds the number to the nearest integer. If number is halfway between two integers, it rounds towards the nearest even number.

The round function can also be called in two ways, as demonstrated below:

let actual = table("Number")
.select()
.project("id")
.project(round("number")) // Method 1: Using the round function directly
.project(col("number").round()) // Method 2: Calling the round method on a column
.execute(glue)
.await;
- - + + \ No newline at end of file diff --git a/docs/dev/ast-builder/functions/math/special-mathematical/index.html b/docs/dev/ast-builder/functions/math/special-mathematical/index.html index d27c7443..5aaedc92 100644 --- a/docs/dev/ast-builder/functions/math/special-mathematical/index.html +++ b/docs/dev/ast-builder/functions/math/special-mathematical/index.html @@ -1,17 +1,17 @@ - + - + Special Mathematical | GlueSQL - - - + + + - - + + \ No newline at end of file diff --git a/docs/dev/ast-builder/functions/math/trigonometric/index.html b/docs/dev/ast-builder/functions/math/trigonometric/index.html index 7e15d0d1..dce076b8 100644 --- a/docs/dev/ast-builder/functions/math/trigonometric/index.html +++ b/docs/dev/ast-builder/functions/math/trigonometric/index.html @@ -1,17 +1,17 @@ - + - + Trigonometric | GlueSQL - - - + + + - - + + \ No newline at end of file diff --git a/docs/dev/ast-builder/functions/others/null-handling/index.html b/docs/dev/ast-builder/functions/others/null-handling/index.html index 3e940161..e5cabc9e 100644 --- a/docs/dev/ast-builder/functions/others/null-handling/index.html +++ b/docs/dev/ast-builder/functions/others/null-handling/index.html @@ -1,17 +1,17 @@ - + - + Null Handling | GlueSQL - - - + + +

Null Handling

In some cases, you may need to handle NULL values in your database. GlueSQL provides a function called ifnull to handle these cases.

IFNULL - ifnull

The ifnull function checks if the first expression is NULL, and if it is, it returns the value of the second expression. If the first expression is not NULL, it returns the value of the first expression.

let actual = table("Foo")
.select()
.project("id")
.project(col("name").ifnull(text("isnull"))) // If the "name" column is NULL, replace it with "isnull"
.execute(glue)
.await;

In the above example, if the "name" column is NULL, "isnull" is returned. Otherwise, the value of the "name" column is returned.

You can also use ifnull with another column:

let actual = table("Foo")
.select()
.project("id")
.project(col("name").ifnull(col("nickname"))) // If the "name" column is NULL, replace it with the value from the "nickname" column
.execute(glue)
.await;

In this example, if the "name" column is NULL, the value from the "nickname" column is returned. If "name" is not NULL, the value of the "name" column is returned.

The ifnull function can also be used without a table:

let actual = values(vec![
vec![ast_builder::ifnull(text("HELLO"), text("WORLD"))], // If "HELLO" is NULL (it's not), return "WORLD". Otherwise, return "HELLO".
vec![ast_builder::ifnull(null(), text("WORLD"))], // If NULL is NULL (it is), return "WORLD".
])
.execute(glue)
.await;

In the first case, "HELLO" is returned because it's not NULL. In the second case, "WORLD" is returned because the first value is NULL.

- - + + \ No newline at end of file diff --git a/docs/dev/ast-builder/functions/others/type-conversion/index.html b/docs/dev/ast-builder/functions/others/type-conversion/index.html index 03e4d2fb..6032895b 100644 --- a/docs/dev/ast-builder/functions/others/type-conversion/index.html +++ b/docs/dev/ast-builder/functions/others/type-conversion/index.html @@ -1,17 +1,17 @@ - + - + Type Conversion | GlueSQL - - - + + + - - + + \ No newline at end of file diff --git a/docs/dev/ast-builder/functions/others/unique-identifier/index.html b/docs/dev/ast-builder/functions/others/unique-identifier/index.html index 44d10ede..59e1d168 100644 --- a/docs/dev/ast-builder/functions/others/unique-identifier/index.html +++ b/docs/dev/ast-builder/functions/others/unique-identifier/index.html @@ -1,17 +1,17 @@ - + - + Unique Identifier | GlueSQL - - - + + + - - + + \ No newline at end of file diff --git a/docs/dev/ast-builder/functions/text/case-conversion/index.html b/docs/dev/ast-builder/functions/text/case-conversion/index.html index 08d71546..a2ab130b 100644 --- a/docs/dev/ast-builder/functions/text/case-conversion/index.html +++ b/docs/dev/ast-builder/functions/text/case-conversion/index.html @@ -1,17 +1,17 @@ - + - + Case Conversion | GlueSQL - - - + + +

Case Conversion

GlueSQL provides several text case conversion functions that allow you to convert text data to upper case, lower case or capitalize each word in a string.

For this tutorial, we assume there's a table named Item with various columns including name, opt_name, and capped_name which are of TEXT type.

Upper Case Conversion - upper

The upper function converts a text string to upper case.

let actual = table("Item")
.select()
.project(col("name").upper()) // Convert the 'name' column to upper case
.execute(glue)
.await;

Lower Case Conversion - lower

The lower function converts a text string to lower case.

let actual = table("Item")
.select()
.project(col("name").lower()) // Convert the 'name' column to lower case
.execute(glue)
.await;

You can also filter the records based on the lower case conversion:

let actual = table("Item")
.select()
.filter(col("name").lower().eq("'abcd'")) // Filter records where lower case of 'name' is 'abcd'
.project("name")
.project(lower("name"))
.execute(glue)
.await;

Initial Capital Case Conversion - initcap

The initcap function converts a text string to initial capital case, i.e., it capitalizes the first character of each word in the string.

let actual = table("Item")
.select()
.project(col("capped_name").initcap()) // Convert the 'capped_name' column to initial capital case
.execute(glue)
.await;

You can also filter the records based on the initial capital case conversion:

let actual = table("Item")
.select()
.filter(col("capped_name").initcap().eq("'H/I Jk'")) // Filter records where initial capital case of 'capped_name' is 'H/I Jk'
.project("capped_name")
.execute(glue)
.await;
- - + + \ No newline at end of file diff --git a/docs/dev/ast-builder/functions/text/character-conversion/index.html b/docs/dev/ast-builder/functions/text/character-conversion/index.html index c4adbc71..53e3e676 100644 --- a/docs/dev/ast-builder/functions/text/character-conversion/index.html +++ b/docs/dev/ast-builder/functions/text/character-conversion/index.html @@ -1,17 +1,17 @@ - + - + Character Conversion | GlueSQL - - - + + + - - + + \ No newline at end of file diff --git a/docs/dev/ast-builder/functions/text/padding/index.html b/docs/dev/ast-builder/functions/text/padding/index.html index 6747475e..fdc5f052 100644 --- a/docs/dev/ast-builder/functions/text/padding/index.html +++ b/docs/dev/ast-builder/functions/text/padding/index.html @@ -1,17 +1,17 @@ - + - + Padding | GlueSQL - - - + + + - - + + \ No newline at end of file diff --git a/docs/dev/ast-builder/functions/text/position-and-indexing/index.html b/docs/dev/ast-builder/functions/text/position-and-indexing/index.html index 27a745c4..008677fd 100644 --- a/docs/dev/ast-builder/functions/text/position-and-indexing/index.html +++ b/docs/dev/ast-builder/functions/text/position-and-indexing/index.html @@ -1,17 +1,17 @@ - + - + Position and Indexing | GlueSQL - - - + + +

Position and Indexing

GlueSQL provides several functions for text manipulation, including finding the index of a substring (find_idx), finding the position of a substring (position), and getting the leftmost or rightmost characters (left and right).

Find Index - find_idx

find_idx function returns the first position of the specified substring, starting from the beginning of the string or the specified position.

let test_num = find_idx(text("strawberry"), text("berry"), None);  // Returns 6
let test_num = find_idx(text("Oracle Database 12c Release"), text("as"), Some(num(15))); // Returns 25

You can also call find_idx directly on a string:

let test_num = text("Oracle Database 12c Release").find_idx(text("as"), Some(num(15)));  // Returns 25

Position - position

The position function is similar to find_idx, but it starts counting from 1 and does not take a third argument for the starting position.

let test_num = position(text("cake"), text("ke"));  // Returns 3

Left - left

The left function returns the leftmost characters of a string. The second argument specifies the number of characters to return.

let test_str = left(text("Hello, World"), num(7));  // Returns "Hello, "

Right - right

The right function returns the rightmost characters of a string. The second argument specifies the number of characters to return.

let test_str = right(text("Hello, World"), num(7));  // Returns ", World"
- - + + \ No newline at end of file diff --git a/docs/dev/ast-builder/functions/text/text-manipulation/index.html b/docs/dev/ast-builder/functions/text/text-manipulation/index.html index 9ad874f1..031a3589 100644 --- a/docs/dev/ast-builder/functions/text/text-manipulation/index.html +++ b/docs/dev/ast-builder/functions/text/text-manipulation/index.html @@ -1,17 +1,17 @@ - + - + Text Manipulation | GlueSQL - - - + + +

Text Manipulation

Todo

- CONCAT: Concatenates two or more strings into one.
- CONCAT_WS: Concatenates two or more strings into one with a separator.
- SUBSTR: Returns a part of a string.
- REPEAT: Repeats a string a specified number of times.
- REVERSE: Reverses the order of the characters in a string.
- - + + \ No newline at end of file diff --git a/docs/dev/ast-builder/functions/text/trimming/index.html b/docs/dev/ast-builder/functions/text/trimming/index.html index 513115be..577fbb1c 100644 --- a/docs/dev/ast-builder/functions/text/trimming/index.html +++ b/docs/dev/ast-builder/functions/text/trimming/index.html @@ -1,17 +1,17 @@ - + - + Trimming | GlueSQL - - - + + +

Trimming

GlueSQL provides several text trimming functions that allow you to remove leading or trailing characters from a text string.

For this tutorial, we assume there's a table named Food with an id column of INTEGER type and a name column of TEXT type.

Right Trimming - rtrim

The rtrim function removes trailing characters from a text string. You can specify the characters to be removed as an argument to the function. If no argument is provided, it trims spaces by default.

// Trims trailing spaces from "chicken   "
let test_text = text("chicken ").rtrim(Some(text(" ")));

let actual = table("Food")
.insert()
.columns("id, name")
.values(vec![vec![num(1), test_text]])
.execute(glue)
.await;

Left Trimming - ltrim

The ltrim function removes leading characters from a text string. You can specify the characters to be removed as an argument to the function. If no argument is provided, it trims spaces by default.

// Trims leading spaces from "   chicken"
let test_text = ltrim(text(" chicken"), Some(text(" ")));

let actual = table("Food")
.insert()
.columns("id, name")
.values(vec![vec![num(2), test_text]])
.execute(glue)
.await;

Right and Left Trimming

You can combine rtrim and ltrim to trim both sides of a string:

// Trims leading "ch" and trailing spaces from "chicken"
let test_text = text("chicken").ltrim(Some(text("ch"))).rtrim(None);

let actual = table("Food")
.insert()
.columns("id, name")
.values(vec![vec![num(3), test_text]])
.execute(glue)
.await;
// Trims trailing "en" and leading spaces from "chicken"
let test_text = text("chicken").rtrim(Some(text("en"))).ltrim(None);

let actual = table("Food")
.insert()
.columns("id, name")
.values(vec![vec![num(4), test_text]])
.execute(glue)
.await;
- - + + \ No newline at end of file diff --git a/docs/dev/ast-builder/intro/index.html b/docs/dev/ast-builder/intro/index.html index 14ac71be..46115bba 100644 --- a/docs/dev/ast-builder/intro/index.html +++ b/docs/dev/ast-builder/intro/index.html @@ -1,17 +1,17 @@ - + - + Introduction | GlueSQL - - - + + +

AST Builder

GlueSQL offers two ways to create and execute queries: using SQL statements or using the AST Builder. In this introductory page, we will focus on the AST Builder.

When executing SQL statements in GlueSQL, they need to be converted into an internal AST (Abstract Syntax Tree) format. The AST Builder allows users to directly create and manipulate ASTs, making it more efficient and flexible compared to traditional SQL statements.

The AST Builder has some similarities to ORM (Object Relational Mapping) query builders, but there are several key differences:

  • ORM query builders often support multiple databases, which can limit their features to a subset of each database's capabilities. However, the AST Builder is designed exclusively for GlueSQL, allowing it to take full advantage of all GlueSQL features.
  • The AST Builder is flexible in terms of input, accepting both its own API calls and SQL expressions.
  • ORM query builders typically generate SQL statements, which must then be executed by the database. This introduces overhead. In contrast, the GlueSQL AST Builder directly generates executable ASTs, making it highly efficient.
  • The AST Builder supports features that are not available with SQL, such as allowing users to directly specify the internal execution strategy. This is similar to SQL query hints, but with the AST Builder, the user's instructions are executed precisely, rather than being treated as suggestions.

Currently, the AST Builder only supports Rust language interfaces, but support for other languages, such as JavaScript, is planned for future releases.

Below are some sample code snippets using the GlueSQL AST Builder in Rust, categorized by query type:

CREATE TABLE

let actual = table("Foo")
.create_table()
.add_column("id INTEGER")
.add_column("name TEXT")
.execute(glue)
.await;

INSERT

let actual = table("Foo")
.insert()
.columns("id, name")
.values(vec![
vec![num(100), text("Pickle")],
vec![num(200), text("Lemon")],
])
.execute(glue)
.await;

SELECT

let actual = table("Foo")
.select()
.project("id, name")
.execute(glue)
.await;

UPDATE

let actual = table("Foo")
.update()
.set("id", col("id").mul(2))
.filter(col("id").eq(200))
.execute(glue)
.await;

SELECT with filtering

let actual = table("Foo")
.select()
.filter("name = 'Lemon'")
.project("id, name")
.build()
.expect("build and execute")
.execute(glue)
.await;

DELETE

let actual = table("Foo")
.delete()
.filter(col("id").gt(200))
.execute(glue)
.await;

Summary

In this introduction to the AST Builder, we have covered the key differences between the AST Builder and ORM query builders, and provided examples of how to use the AST Builder in Rust for various query types. The AST Builder is a powerful and efficient tool for working with GlueSQL, offering greater flexibility and control compared to traditional SQL statements.

Remember that the AST Builder currently supports only Rust language interfaces, but support for other languages, such as JavaScript, is planned for future releases.

By leveraging the AST Builder, you can take full advantage of GlueSQL's features, and build more efficient and flexible database applications.

- - + + \ No newline at end of file diff --git a/docs/dev/ast-builder/statements/data-manipulation/deleting-data/index.html b/docs/dev/ast-builder/statements/data-manipulation/deleting-data/index.html index b1d914ea..c129c8f5 100644 --- a/docs/dev/ast-builder/statements/data-manipulation/deleting-data/index.html +++ b/docs/dev/ast-builder/statements/data-manipulation/deleting-data/index.html @@ -1,17 +1,17 @@ - + - + Deleting Data | GlueSQL - - - + + +

Deleting Data

In this section, we will discuss how to delete data from a table using GlueSQL.

Delete with Filter

To delete specific rows from a table, you can use the delete method on a table object, followed by the filter method to provide a condition that the rows must meet. You can then use the execute method to apply the changes.

let actual = table("Foo")
.delete()
.filter(col("flag").eq(false))
.execute(glue)
.await;
let expected = Ok(Payload::Delete(1));
test(actual, expected);

This code deletes the rows in the table Foo where the flag column value is false.

Delete All Rows

To delete all rows from a table, you can use the delete method on a table object, followed by the execute method.

let actual = table("Foo").delete().execute(glue).await;
let expected = Ok(Payload::Delete(2));
test(actual, expected);

This code deletes all rows from the table Foo.

- - + + \ No newline at end of file diff --git a/docs/dev/ast-builder/statements/data-manipulation/inserting-data/index.html b/docs/dev/ast-builder/statements/data-manipulation/inserting-data/index.html index 1b136584..ee1e253e 100644 --- a/docs/dev/ast-builder/statements/data-manipulation/inserting-data/index.html +++ b/docs/dev/ast-builder/statements/data-manipulation/inserting-data/index.html @@ -1,17 +1,17 @@ - + - + Inserting Data | GlueSQL - - - + + +

Inserting Data

In this section, we will discuss how to insert data into a table using GlueSQL.

Basic Insert

To insert data into a table, you can use the insert method on a table object. You can then use the values method to provide the values you want to insert.

let actual = table("Foo")
.insert()
.values(vec!["1, 'Fruit', 0.1", "2, 'Meat', 0.8"])
.execute(glue)
.await;
let expected = Ok(Payload::Insert(2));
test(actual, expected);

This code inserts two rows into the table Foo. The first row has the values 1, 'Fruit', 0.1 and the second row has the values 2, 'Meat', 0.8.

Insert with Specified Columns

If you want to specify the columns to insert data into, you can use the columns method followed by the values method. The values method should contain the data for the specified columns.

let actual = table("Foo")
.insert()
.columns("id, name")
.values(vec![vec![num(3), text("Drink")]])
.execute(glue)
.await;
let expected = Ok(Payload::Insert(1));
test(actual, expected);

This code inserts a new row into the table Foo with the specified columns id and name. The rate column is not specified, so it will be set to its default value.

Insert from Source

You can also insert data into a table using a SELECT statement as the source. To do this, use the as_select method followed by the execute method.

let actual = table("Bar")
.insert()
.as_select(table("Foo").select().project("id, name"))
.execute(glue)
.await;
let expected = Ok(Payload::Insert(3));
test(actual, expected);

This code inserts data into the table Bar using the SELECT statement on the table Foo. The project method is used to specify the columns id and name as the source data.

- - + + \ No newline at end of file diff --git a/docs/dev/ast-builder/statements/data-manipulation/updating-data/index.html b/docs/dev/ast-builder/statements/data-manipulation/updating-data/index.html index d70c6d4c..7dd7f254 100644 --- a/docs/dev/ast-builder/statements/data-manipulation/updating-data/index.html +++ b/docs/dev/ast-builder/statements/data-manipulation/updating-data/index.html @@ -1,17 +1,17 @@ - + - + Updating Data | GlueSQL - - - + + +

Updating Data

In this section, we will discuss how to update data in a table using GlueSQL.

Basic Update

To update data in a table, you can use the update method on a table object, followed by the set method to specify the column and the new value. You can then use the execute method to apply the changes.

let actual = table("Foo")
.update()
.set("score", col("score").div(10))
.execute(glue)
.await;
let expected = Ok(Payload::Update(3));
test(actual, expected);

This code updates all rows in the table Foo, dividing the score column value by 10.

Update with Multiple Columns

To update multiple columns, you can chain multiple set methods with the desired column names and new values.

let actual = table("Foo")
.update()
.set("score", "score * 2 + 5")
.set("flag", col("flag").negate())
.execute(glue)
.await;
let expected = Ok(Payload::Update(3));
test(actual, expected);

This code updates all rows in the table Foo, applying the following changes:

  1. The score column value is multiplied by 2 and 5 is added.
  2. The flag column value is negated (i.e., true becomes false and false becomes true).

Update with Filter

If you want to update only specific rows, you can use the filter method to provide a condition that the rows must meet.

let actual = table("Foo")
.update()
.set("score", "score * 2 + 5")
.set("flag", col("flag").negate())
.filter(col("score").lte(30))
.execute(glue)
.await;
let expected = Ok(Payload::Update(2));
test(actual, expected);

This code updates the rows in the table Foo where the score column value is less than or equal to 30. The score and flag column values are updated as described in the previous example.

- - + + \ No newline at end of file diff --git a/docs/dev/ast-builder/statements/querying/creating-derived-subqueries/index.html b/docs/dev/ast-builder/statements/querying/creating-derived-subqueries/index.html index 46edfc08..480c84cd 100644 --- a/docs/dev/ast-builder/statements/querying/creating-derived-subqueries/index.html +++ b/docs/dev/ast-builder/statements/querying/creating-derived-subqueries/index.html @@ -1,17 +1,17 @@ - + - + Creating Derived Subqueries | GlueSQL - - - + + +

Creating Derived Subqueries

This document covers the alias_as functionality of the AST Builder in the GlueSQL project. The alias_as method allows you to create a derived subquery, which is similar to subqueries in SQL. It gives you the ability to use the output of a query as a table to perform further queries.

Basic Usage

To use the alias_as method, simply chain it to the end of a query builder method before executing the query. The derived subquery can then be used for further queries. Here's an example:

let actual = table("Item")
.select()
.alias_as("Sub")
.select()
.execute(glue)
.await;

In this example, the alias_as method is used after the select method, creating a derived subquery named "Sub" that can be used in subsequent queries.

Examples

The following examples demonstrate how to use the alias_as method with various query operations.

Derived Subquery with Filter

let actual = table("Item")
.select()
.filter("item_id = 300")
.alias_as("Sub")
.select()
.execute(glue)
.await;

Derived Subquery with Projection

let actual = table("Item")
.select()
.project("item_id")
.alias_as("Sub")
.select()
.execute(glue)
.await;

Derived Subquery with Join

let actual = table("Item")
.alias_as("i")
.select()
.join_as("Category", "c")
.on("c.category_id = i.category_id")
.alias_as("Sub")
.select()
.project("item_name")
.project("category_name")
.execute(glue)
.await;

Derived Subquery with Group By and Having

let actual = table("Category")
.select()
.project("category_name")
.alias_as("Sub1")
.select()
.group_by("category_name")
.having("category_name = 'Meat'")
.alias_as("Sub2")
.select()
.execute(glue)
.await;

Derived Subquery with Order By

let actual = table("Item")
.select()
.order_by("price DESC")
.alias_as("Sub")
.select()
.execute(glue)
.await;

Derived Subquery with Offset and Limit

This example shows how to create a derived subquery combined with both the offset and limit methods to control the range of rows returned:

let actual = table("Item")
.select()
.offset(3)
.limit(1)
.alias_as("Sub")
.select()
.execute(glue)
.await;
- - + + \ No newline at end of file diff --git a/docs/dev/ast-builder/statements/querying/data-aggregation/index.html b/docs/dev/ast-builder/statements/querying/data-aggregation/index.html index e3f8efa8..d876ebad 100644 --- a/docs/dev/ast-builder/statements/querying/data-aggregation/index.html +++ b/docs/dev/ast-builder/statements/querying/data-aggregation/index.html @@ -1,17 +1,17 @@ - + - + Data Aggregation | GlueSQL - - - + + +

Data Aggregation

The AST Builder API in GlueSQL allows you to construct SQL queries programmatically. This page provides an introduction to data aggregation using the AST Builder API.

Prerequisites

Before we explore data aggregation examples, let's set up a sample table called "User" with the following columns: "id" (INT), "name" (TEXT), and "age" (INT).

CREATE TABLE User (
id INT,
name TEXT,
age INT
);

We will use this table for the subsequent examples.

Grouping and Counting

To group records by a specific column and count the number of occurrences in each group, you can use the AST Builder's group_by() and project() methods.

table("User")
.select()
.group_by("age")
.project("age, count(*)")
.execute(glue);

The above code groups the records in the "User" table by the "age" column and returns the age value along with the count of occurrences in each group. The result would be:

age | count(*)
----|---------
20 | 1
30 | 2
50 | 2

Filtering Groups with HAVING

You can further filter the groups based on specific conditions using the having() method. The having() method allows you to apply conditions to the grouped data.

table("User")
.select()
.group_by("age")
.having("count(*) > 1")
.project("age, count(*)")
.execute(glue);

The above code groups the records in the "User" table by the "age" column, but it only includes groups where the count of occurrences is greater than 1. The result would be:

age | count(*)
----|---------
30 | 2
50 | 2

This concludes the introduction to data aggregation using the AST Builder API in GlueSQL. You can leverage these methods to perform various aggregations and analyze your data effectively.

- - + + \ No newline at end of file diff --git a/docs/dev/ast-builder/statements/querying/data-injection/index.html b/docs/dev/ast-builder/statements/querying/data-injection/index.html index c5291707..04e0fc10 100644 --- a/docs/dev/ast-builder/statements/querying/data-injection/index.html +++ b/docs/dev/ast-builder/statements/querying/data-injection/index.html @@ -1,17 +1,17 @@ - + - + Data Injection | GlueSQL - - - + + + - - + + \ No newline at end of file diff --git a/docs/dev/ast-builder/statements/querying/data-joining/index.html b/docs/dev/ast-builder/statements/querying/data-joining/index.html index 0bb70655..e2bbf579 100644 --- a/docs/dev/ast-builder/statements/querying/data-joining/index.html +++ b/docs/dev/ast-builder/statements/querying/data-joining/index.html @@ -1,17 +1,17 @@ - + - + Data Joining | GlueSQL - - - + + + - - + + \ No newline at end of file diff --git a/docs/dev/ast-builder/statements/querying/data-selection-and-projection/index.html b/docs/dev/ast-builder/statements/querying/data-selection-and-projection/index.html index 6535c20f..294340aa 100644 --- a/docs/dev/ast-builder/statements/querying/data-selection-and-projection/index.html +++ b/docs/dev/ast-builder/statements/querying/data-selection-and-projection/index.html @@ -1,17 +1,17 @@ - + - + Data Selection and Projection | GlueSQL - - - + + + - - + + \ No newline at end of file diff --git a/docs/dev/ast-builder/statements/querying/data-sorting-and-limiting/index.html b/docs/dev/ast-builder/statements/querying/data-sorting-and-limiting/index.html index 9dcce8e0..c6cc0091 100644 --- a/docs/dev/ast-builder/statements/querying/data-sorting-and-limiting/index.html +++ b/docs/dev/ast-builder/statements/querying/data-sorting-and-limiting/index.html @@ -1,17 +1,17 @@ - + - + Data Sorting and Limiting | GlueSQL - - - + + + - - + + \ No newline at end of file diff --git a/docs/dev/ast-builder/statements/querying/fetching-data-from-storage/index.html b/docs/dev/ast-builder/statements/querying/fetching-data-from-storage/index.html index 5ec1eb29..7553e925 100644 --- a/docs/dev/ast-builder/statements/querying/fetching-data-from-storage/index.html +++ b/docs/dev/ast-builder/statements/querying/fetching-data-from-storage/index.html @@ -1,17 +1,17 @@ - + - + Fetching Data from Storage | GlueSQL - - - + + +

Fetching Data from Storage

The AST Builder provides a powerful and flexible way to query data from your tables, similar to SQL's SELECT statement. This guide will show you how to use the AST Builder's table("foo").select() method to perform various query types, including filtering, joining, grouping, ordering, and pagination.

Basic SELECT

To perform a basic SELECT query using the AST Builder, simply call the select() method on a table object.

let actual = table("Category").select().execute(glue).await;

Filtering (WHERE)

To filter the results of a SELECT query, use the filter() method, providing a condition as a string.

let actual = table("Category")
.select()
.filter("name = 'Meat'")
.execute(glue)
.await;

Joining Tables

You can join tables using the join() or join_as() methods. The following example demonstrates an INNER JOIN:

let actual = table("Item")
.alias_as("i")
.select()
.join_as("Category", "c")
.on("c.id = i.category_id")
.filter("c.name = 'Fruit' OR c.name = 'Meat'")
.project("i.name AS item")
.project("c.name AS category")
.execute(glue)
.await;

For LEFT OUTER JOIN, use the left_join() method:

let actual = table("Category")
.select()
.left_join("Item")
.on(col("Category.id")
.eq(col("Item.category_id"))
.and(col("price").gt(50)))
.project(vec![
"Category.name AS category",
"Item.name AS item",
"price",
])
.execute(glue)
.await;

Grouping and Aggregating (GROUP BY, HAVING)

To group the results of a SELECT query, use the group_by() method. You can also filter the groups using the having() method.

let actual = table("Item")
.select()
.join("Category")
.on(col("Category.id").eq("Item.category_id"))
.group_by("Item.category_id")
.having("SUM(Item.price) > 80")
.project("Category.name AS category")
.project("SUM(Item.price) AS sum_price")
.execute(glue)
.await;

Sorting Results (ORDER BY)

To sort the results of a SELECT query, use the order_by() method.

let actual = table("Item")
.select()
.project("name, price")
.order_by("price DESC")
.execute(glue)
.await;

Pagination (OFFSET, LIMIT)

You can paginate the results of a SELECT query using the offset() and limit() methods.

let actual = table("Item")
.select()
.project("name, price")
.order_by("price DESC")
.offset(1)
.limit(2)
.execute(glue)
.await;
- - + + \ No newline at end of file diff --git a/docs/dev/ast-builder/statements/querying/using-preloaded-data/index.html b/docs/dev/ast-builder/statements/querying/using-preloaded-data/index.html index 500bcd18..4d74e08e 100644 --- a/docs/dev/ast-builder/statements/querying/using-preloaded-data/index.html +++ b/docs/dev/ast-builder/statements/querying/using-preloaded-data/index.html @@ -1,17 +1,17 @@ - + - + Using Preloaded Data | GlueSQL - - - + + +

Using Preloaded Data

This guide will show you how to use AST Builder to query data that has already been loaded into memory, as opposed to querying data from storage. This is similar to SQL's VALUES functionality.

Creating a Values Object

To create a values() object, you can either provide a vector of strings or a vector of vectors of strings. Each inner vector represents a row of data, and each string within the inner vector represents a value in that row.

use gluesql_core::ast_builder::values;

let actual = values(vec!["1, 'Glue'", "2, 'SQL'", "3, 'Rust'"])
.execute(glue)
.await;

let actual = values(vec![
vec!["1", "'Glue'"],
vec!["2", "'SQL'"],
vec!["3", "'Rust'"],
])
.execute(glue)
.await;

Sorting Results (ORDER BY)

To sort the results of a values() query, use the order_by() method.

let actual = values(vec!["1, 'Glue'", "2, 'SQL'", "3, 'Rust'"])
.order_by("column2 desc")
.execute(glue)
.await;

Pagination (OFFSET, LIMIT)

You can paginate the results of a values() query using the offset() and limit() methods.

let actual = values(vec!["1, 'Glue'", "2, 'SQL'", "3, 'Rust'"])
.offset(1)
.execute(glue)
.await;

let actual = values(vec!["1, 'Glue'", "2, 'SQL'", "3, 'Rust'"])
.limit(2)
.execute(glue)
.await;

Querying Preloaded Data

To query preloaded data using the values() object, you can call the select() method, and then use the project() method to specify the columns you want to include in the result.

let actual = values(vec!["1, 'Glue'", "2, 'SQL'", "3, 'Rust'"])
.alias_as("Sub")
.select()
.project("column1 AS id")
.project("column2 AS name")
.execute(glue)
.await;
- - + + \ No newline at end of file diff --git a/docs/dev/blog/archive/index.html b/docs/dev/blog/archive/index.html index e15fbac6..73b5cad0 100644 --- a/docs/dev/blog/archive/index.html +++ b/docs/dev/blog/archive/index.html @@ -1,17 +1,17 @@ - + - + Archive | GlueSQL - - - + + + - - + + \ No newline at end of file diff --git a/docs/dev/blog/breaking-the-boundary-between-sql-and-nosql/index.html b/docs/dev/blog/breaking-the-boundary-between-sql-and-nosql/index.html index 5e2b1f06..7278c8d4 100644 --- a/docs/dev/blog/breaking-the-boundary-between-sql-and-nosql/index.html +++ b/docs/dev/blog/breaking-the-boundary-between-sql-and-nosql/index.html @@ -1,16 +1,16 @@ - + - + Breaking the Boundary between SQL and NoSQL Databases | GlueSQL - - - + + +
-

Breaking the Boundary between SQL and NoSQL Databases

· 11 min read
Taehoon Moon

Introduction

The divide between SQL and NoSQL databases has often presented challenges in database management. GlueSQL, a unique database maker library, aims to blur this boundary, providing a versatile tool for handling these two distinct types of databases.

In this article, we explore how GlueSQL navigates the features of SQL and NoSQL databases, offering an integrated solution that promotes flexibility and efficiency. With its ability to unify disparate database types, GlueSQL heralds a new age of adaptable database creation and management.

The Interface Perspective: SQL & AST Builder

When we talk about SQL databases, it's almost a given that they support SQL - the standard query language. Although there are slight variations between databases, the convenience of using a similar SQL language across multiple databases cannot be overstated. However, from a software engineer's perspective, there's room for improvement. In most software development scenarios, a specific programming language is used. SQL is a separate language, which can cause friction when integrating it into your software. As a result, rather than using raw SQL, many developers employ query builders or ORMs to manipulate SQL conveniently using their preferred programming language. Although it's not efficient to generate SQL using a query builder and then parse it again in the database, it's a practical and effective choice.

On the other hand, NoSQL databases offer different mechanisms. Some of them have their own language similar to SQL, but most provide an interface library developed specifically for each programming language. While SQL databases rely on external query builder libraries to provide an interface for each programming language, NoSQL databases mostly develop and offer these libraries themselves. If we discount the convenience of SQL language, this is one of the major factors that make NoSQL databases more comfortable to use. Since query builder libraries supporting SQL databases often cater to multiple SQL databases, they are limited in fully supporting unique features of each database. NoSQL databases, on the other hand, can freely manage their interface libraries without these restrictions.

Providing a query interface for each programming language is not a fundamental difference between SQL and NoSQL, but we generally accept it implicitly.

Let's see what happens if we break down this boundary, using GlueSQL as an example. As you can see from the SQL postfix, GlueSQL supports SQL and can be classified as an SQL database.

CREATE TABLE Glue (id INTEGER, name TEXT);

INSERT INTO Glue VALUES (1, "hello"), (2, "gluesql");

SELECT * FROM Glue WHERE id = 1;

However, GlueSQL also supports its own query builder, like a NoSQL database. +

Breaking the Boundary between SQL and NoSQL Databases

· 11 min read
Taehoon Moon

Introduction

The divide between SQL and NoSQL databases has often presented challenges in database management. GlueSQL, a unique database maker library, aims to blur this boundary, providing a versatile tool for handling these two distinct types of databases.

In this article, we explore how GlueSQL navigates the features of SQL and NoSQL databases, offering an integrated solution that promotes flexibility and efficiency. With its ability to unify disparate database types, GlueSQL heralds a new age of adaptable database creation and management.

The Interface Perspective: SQL & AST Builder

When we talk about SQL databases, it's almost a given that they support SQL - the standard query language. Although there are slight variations between databases, the convenience of using a similar SQL language across multiple databases cannot be overstated. However, from a software engineer's perspective, there's room for improvement. In most software development scenarios, a specific programming language is used. SQL is a separate language, which can cause friction when integrating it into your software. As a result, rather than using raw SQL, many developers employ query builders or ORMs to manipulate SQL conveniently using their preferred programming language. Although it's not efficient to generate SQL using a query builder and then parse it again in the database, it's a practical and effective choice.

On the other hand, NoSQL databases offer different mechanisms. Some of them have their own language similar to SQL, but most provide an interface library developed specifically for each programming language. While SQL databases rely on external query builder libraries to provide an interface for each programming language, NoSQL databases mostly develop and offer these libraries themselves. If we discount the convenience of SQL language, this is one of the major factors that make NoSQL databases more comfortable to use. Since query builder libraries supporting SQL databases often cater to multiple SQL databases, they are limited in fully supporting unique features of each database. NoSQL databases, on the other hand, can freely manage their interface libraries without these restrictions.

Providing a query interface for each programming language is not a fundamental difference between SQL and NoSQL, but we generally accept it implicitly.

Let's see what happens if we break down this boundary, using GlueSQL as an example. As you can see from the SQL postfix, GlueSQL supports SQL and can be classified as an SQL database.

CREATE TABLE Glue (id INTEGER, name TEXT);

INSERT INTO Glue VALUES (1, "hello"), (2, "gluesql");

SELECT * FROM Glue WHERE id = 1;

However, GlueSQL also supports its own query builder, like a NoSQL database. (Currently, only Rust is supported, but we're working on adding support for other languages.)

table("Glue")
.create_table()
.add_column("id INTEGER")
.add_column("name TEXT")
.execute(glue)

table("Glue")
.insert()
.values(vec![
vec![num(1), text("hello")],
vec![num(2), text("gluesql")],
])
.execute(glue)
.await;

table("Glue")
.select()
.filter(col("id").eq(1))
.execute(glue)
.await;

Let's reconsider the implicit distinction between SQL and NoSQL. GlueSQL indeed supports SQL, but it also officially develops and offers its own query builder. This query builder is not a secondary tool for SQL. While most SQL query builder libraries ultimately generate SQL strings, GlueSQL's builder directly creates an AST (Abstract Structure Tree) that is used for execution within GlueSQL. Hence, we call it the AST Builder. This means SQL and the AST Builder are two equally supported interfaces in GlueSQL.

This also offers an additional advantage:

table("Glue")
.select()
// 1.
.filter(col("id").eq(1))
// 2.
.filter("id = 1")
.execute(glue)
.await;

Because GlueSQL already supports SQL, not only can you use the custom interface in the AST Builder, but you can also use familiar SQL syntax in part. Whether you use col("id").eq(1) or "id = 1", you can use it in the way you prefer. The AST Builder interface, although initially unfamiliar, allows a gradual migration similar to writing SQL for your convenience.

Thus, we've dismantled one of the implicit distinctions between SQL and NoSQL. However, it's more of an implicit differentiation than a fundamental one. There are more significant design differences that we'll explore next.

Structured & Unstructured Data

In this section, we'll discuss how SQL and NoSQL handle data. SQL generally deals with structured data, and recently, it's been made to support semi-structured data as well. On the other hand, NoSQL supports schemaless, unstructured data. Then, we'll explain in detail how GlueSQL handles these two types of data. The last part of this section will provide a segue into the next section where we'll discuss the decomposition of database functions.

When talking about SQL databases, one aspect is usually considered together: SQL databases have a defined schema.

CREATE TABLE Foo (
id INTEGER,
name TEXT,
rate FLOAT NULL
);

However, these days, SQL databases tend to support semi-structured data types, such as LIST or JSON. But, supporting completely schemaless, unstructured data is a different matter. SQL databases typically require a minimum schema.

What about NoSQL databases? As NoSQL databases vary significantly, we can't make definitive statements. But let's consider a typical document database like MongoDB. Unlike SQL databases, it doesn't enforce a schema. Essentially, you can insert any form of data directly. Often, NoSQL databases support schemaless data, but they lack features that enforce a schema like SQL. They generally support structure via validation methods, rather than structured access.

Is there no choice but to distinguish between structured data and unstructured, schemaless data so clearly? GlueSQL is being developed with the goal of being adaptable in various environments. Being forced to choose regarding this schema constraint was quite inconvenient. We started pondering if we couldn't benefit from both aspects - supporting both schema and schemaless data simultaneously, and we eventually found the answer. Let's look at how GlueSQL currently solves this issue through familiar SQL examples.

CREATE TABLE Names (id INTEGER, name TEXT);
INSERT INTO Names VALUES (1, 'glue'), (2, 'sql');

You can create a regular table with a schema like this. But GlueSQL's choice for creating a schemaless table is as follows:

CREATE TABLE Logs;
INSERT INTO Logs VALUES
('{ "id": 1, "value": 30 }'),
('{ "id": 2, "rate": 3.0, "list": [1, 2, 3] }'),
('{ "id": 3, "rate": 5.0, "value": 100 }');

It creates a table without column definitions! If you do this, GlueSQL recognizes the table as schemaless and processes it internally.

SELECT id, rate, list[0] FROM Logs WHERE id = 2;

Although the way to create the table was a bit special, using it isn't much different from the regular SQL SELECT statement. Not only can you differentiate between schema and schemaless when creating tables, but you can also use them interchangeably!

SELECT * FROM Names JOIN Logs ON Names.id = Logs.id;
/*
| id | list | name | rate | value |
|----|---------|------|------|-------|
| 1 | | glue | | 30 |
| 2 |[1, 2, 3]| sql | 3 | |
*/

Here's an example of querying data by INNER JOINing the Names table, which has a schema, and the Logs table, which is schemaless. GlueSQL has resolved this problem by allowing the internal execution layer to handle both vector-type data, for cases where each row has a defined schema, and map-type data for schemaless cases.

Thanks to this, the variety of storage that can be supported through GlueSQL has expanded significantly. If there were previously limitations to supporting NoSQL databases that support schemaless data, that is no longer the case. The reference storage where you can directly experience this schemaless data support is JSON Storage. It offers features that allow you to deal directly with unstructured data like JSON using GlueSQL.

If GlueSQL starts from the perspective of an SQL database and expands, by providing the AST Builder directly, it once blurs the boundary, and by supporting unstructured data simultaneously, it knocks down the boundary once more. How do you like it?

Decomposing Database Functionality: Breaking Down SQL and NoSQL Features

The distinction between SQL and NoSQL is not just about whether they support unstructured data. Of course, there are examples like unstructured data, which is mainly supported only in NoSQL, but in many cases, SQL databases tend to support more diverse and complex queries. NoSQL often gains other advantages in exchange for reducing the range of query support provided by SQL databases.

GlueSQL is ambitious. It has devised a rather interesting method to support all of this through SQL and the AST Builder, with the same interface. When we usually say SQL database, it implicitly assumes that a lot of features have been fully implemented. Create tables by specifying a schema, modify schemas with "alter table", support both clustered and non-clustered indexes, and support transactions. And there's so much more. But the functionality that is naturally supported in SQL databases may not be natural in other environments.

Let's think about JSON Storage. GlueSQL's JSON Storage allows you to handle JSON, JSONL files using SQL and the AST Builder. This JSON Storage does not support atomic operations or transactions. Of course, it would be great if it did, but implementing and executing them would be a significant performance burden. In most cases, when you want to simply browse and handle JSONL files, the overhead caused by transactions can be an unnecessary burden. In this case, you want to handle JSON, JSONL files using SQL, but you don't necessarily need transactions.

To meet the requirements of these diverse environments, GlueSQL has separated the functionality of what we usually call an SQL database into multiple independent interfaces. Store, StoreMut, AlterTable, Transaction, .. These are just a few of the various storage interfaces that GlueSQL currently supports. @@ -23,7 +23,7 @@ The Transaction interface works the same way. The interesting part is that, except for Store and StoreMut, all other storage interfaces can be implemented independently. GlueSQL allows you to choose and implement only the features you need. And it's not just about providing interfaces. It also provides integration tests suitable for each situation to verify what you have implemented. You just need to implement the interface and import the corresponding test case for verification.

In addition to supporting both structured and unstructured data simultaneously, GlueSQL provides the ability to divide the functionality of a database into multiple independent features and selectively implement them. This allows GlueSQL to be ported to a wide variety of environments without any burden.

Conclusion

GlueSQL, while serving as a database that provides its own reference storage, is fundamentally a library designed to simplify the creation of databases. One of the substantial challenges GlueSQL had to overcome in order to support a diverse array of environments was to address the distinctive features that separate conventional SQL databases from NoSQL databases. GlueSQL achieved this through several innovative approaches, managing to support both categories simultaneously despite their significantly different characteristics.

It offers support for SQL alongside an AST Builder, and accommodates both structured and unstructured data. Additionally, it decomposes database functionalities into multiple independent features, allowing each environment to selectively implement the functionalities it requires.

These unique attributes enable GlueSQL to live up to its 'Glue' prefix by facilitating effortless porting across various environments. While we have been developing it for several years, there is still much ground to cover. However, the fact that we are now able to introduce it publicly attests to our successful technological validation and completion of a demonstrable level of implementation.

Through GlueSQL, we hope to provide developers with a unified query interface that can be customized according to their needs, thereby enabling them to produce efficient products more effortlessly. There's a promising future ahead for GlueSQL, and we look forward to its contributions to the technology community.

- - + + \ No newline at end of file diff --git a/docs/dev/blog/index.html b/docs/dev/blog/index.html index 9e5ba0c2..cf5a69e6 100644 --- a/docs/dev/blog/index.html +++ b/docs/dev/blog/index.html @@ -1,17 +1,17 @@ - + - + Blog | GlueSQL - - - + + +
-

· 14 min read
Taehoon Moon

Introduction

GlueSQL is a versatile database project designed for exceptional portability across a broad range of environments, from embedded systems and servers to web and mobile platforms. The core goal is to support diverse storage environments and manage various data types with a standard SQL approach.

Imagine handling files like CSV, JSONL, and Parquet, or transforming key-value or NoSQL databases such as RocksDB, Redis, and MongoDB into SQL-supporting databases—all feasible with GlueSQL. It can also operate with storages supported in web browsers.

GlueSQL's essential feature is providing a management layer for these diverse storage scenarios without requiring data migration. The broader aim is to facilitate portability of GlueSQL to any environment supporting read or read-write operations. This extends to APIs like GitHub, or messengers like Discord or Slack.

GlueSQL supports both structured and unstructured data and is written in Rust for compatibility with various environments. While portability is its core value, the emphasis is on creating an intuitive, comfortable development environment for easy custom storage implementation.

Ultimately, GlueSQL aims to significantly reduce the cost, time, and complexity of developing new databases. By leveraging GlueSQL for the parser, planner, and execution layer, developers can focus on creating specific storage implementations, leading to a more convenient query interface like SQL for many environments.

The Problem: Why Reinvent the Database?

Despite the numerous database implementations that currently exist, the emergence of new databases continues. The primary reason behind this trend is our need for databases for a broad spectrum of distinct purposes. For instance, new databases are surfacing that are specifically optimized for Large Language Models (LLMs) like ChatGPT. The range is wide and diverse, encompassing embedded databases, OLAP for data analysis, OLTP databases optimized for online transactions, databases specialized for time-series data processing, and many more.

With such varied requirements, we find ourselves in constant need of fresh databases. However, constructing a database from scratch is a monumental task. It necessitates defining a query interface for handling the database and implementing a corresponding parser. Moreover, a separate execution layer for running operations must be built. Also, the planning layer, which is responsible for devising execution strategies, is a vital aspect of this process. Let's not forget about the critical storage layer that physically reads and stores the data. In a nutshell, there's a daunting amount of work involved in developing a new database.

Given these circumstances, it's understandable why numerous emerging databases resort to high pricing structures—they need immediate revenue to offset continuous development costs.

But the story doesn't end here. Query interfaces like SQL are indeed useful for serious tasks, but they also provide excellent utility for handling simple log files such as CSV, JSONL, Parquet, and even for utilizing REST APIs for various applications. The issue arises when a complex query interface needs to be provided even for these lighter storage requirements—it necessitates a development process almost identical to building a sophisticated database. Implementing an entire parser and execution layer just to add SQL support to an existing service can seem like an excessive burden.

Whether it's a simple storage environment or a serious task, the key lies in the storage layer, which involves the actual reading and storing of data. So, what if developers focused on implementing these storage mechanisms while the remaining parts could be handled using existing libraries? This is the role that GlueSQL aspires to play.

The Vision of GlueSQL

The GlueSQL project aims to offer a unified query interface for various environments. The goal is to allow anyone to port and use SQL and GlueSQL's proprietary query builder, the AST Builder, in any desired environment. This could range from key-value databases, serious NoSQL databases, log files, and even REST API services. Essentially, if a service supports reading or read-writing data, regardless of the data type, it can readily support a complex query interface via GlueSQL.

Presently, the GlueSQL project itself directly supports a few storage types as reference storages. These include in-memory storage for non-persistent data handling, sled storage, which is a key-value database written in Rust, JSON storage for handling JSON and JSONL files, and a storage that ports SQL to the web browser's IndexedDB. While the GlueSQL Team is primarily developing these, the aim is to allow anyone to create such custom storages for a wide array of purposes, thus enabling them to assemble the database of their choosing.

Imagine using GlueSQL's SQL and AST Builder everywhere, with the simple method of swapping out storages to operate in diverse settings. It could significantly reduce software development costs. Developers wouldn't need to learn the different usage methods for each database. Instead, they could focus solely on implementing business logic using the same interface.

Our vision is to reduce database development costs by 10 times, or even more than 20 times. We aim to gather diverse database creators under the GlueSQL banner, making it the go-to solution for cost-effective database development.

Benefits to Database Users: Unifying Query Interfaces, Streamlining Software Development, and Reducing Costs

From the perspective of the users who engage with databases, there has always been the burden of learning different interfaces to interact with each database. The approach required to work with Redis is different from that necessary for MongoDB. Likewise, handling SQL databases necessitates using SQL. Although SQL databases generally use a common SQL, the SQL they support can considerably vary when examined in detail.

Naturally, there are legitimate reasons for such differences. Each database focuses on different areas, and to cater to specialized functionalities, they incorporate dedicated interface mechanisms. However, not all application development needs to utilize these database-specific core special functionalities.

Let's look at a couple of examples:

Suppose you're developing a back-end application that uses MySQL as the database and Redis for caching. Due to the vast differences in handling SQL databases and Redis, you would have to develop using different methods when storing data.

Here's another scenario: -Imagine you're implementing a data migration pipeline between various databases and log files. Let's say you're transferring Parquet to Redis or MongoDB. In this case, you would need to convert data using different methods for each, all of which would be a cumbersome process.

In both of the above examples, GlueSQL can directly address and solve the issues. It offers the convenience of a uniform query interface to deal with these matters. In certain scenarios, even the construction of a data pipeline can potentially be solved with a single SQL query, thanks to GlueSQL.

Benefits to Database Developers: Drastically Lowering Development Costs and Simplifying the Creation of Purpose-Built Databases

If you want to support SQL in the desired environment, using GlueSQL essentially requires you to implement an interface for Storage. There's no need to support all functionalities from the beginning. You can start lightly, choosing and implementing storage features suitable for the environment you want to create. To facilitate this, GlueSQL also provides a library in the form of a test suite to easily validate the storage you've implemented.

Lowering development costs in this way will enable a broader range of developers to support the GlueSQL query interface. As more developers join, a significant synergy can be generated. Designing a query interface from scratch involves a great deal of work, including planning and supporting the interface for different target programming languages.

However, despite all this hard work, it is not easy to attract database users accustomed to different methods.

Consider that the SQL and AST Builder provided by GlueSQL are already securing numerous users. This eliminates the need for efforts to promote a newly planned query interface. Over the years, many new databases have emphasized compatibility with PostgreSQL or MySQL for similar reasons. As GlueSQL places a strong emphasis on portability in its query interface planning, it allows for more flexible configuration according to the desired situation. Through the AST Builder, it also eliminates the cost of porting to different languages.

For many database developers, using GlueSQL can be an optimal choice, as it can save costs and quickly secure users.

Let me mention one more thing: what's convenient for humans... could be applied to AI as well. Rather than making AI write automation code using different databases, providing a common query interface can be much more efficient.

The Future with GlueSQL

GlueSQL has been and will continue to improve and develop new features to enable portability in various environments. Thanks to the schemaless data support added last year, it is now possible to handle both structured data with schema and unstructured data like JSON simultaneously. This has significantly increased the range of storage environments that can be supported.

One of the key features added last year was the AST Builder. This feature allowed us to escape the confines of SQL and provide an interface for comfortably handling data in the programming languages used for development.

Of course, improving existing features is extremely important, and there are many new features to be added. As a major development plan this year, we aim to develop features to effectively attach GlueSQL to NoSQL databases with their own planners and execution layers. The GlueSQL query planner, currently at a basic level, will see significant changes this year. With the expansion of this planner, not only NoSQL databases but also other SQL databases could be supported without sacrificing performance using GlueSQL.

The synergy that arises from the combination of different databases is a significant bonus in this process.

The Journey of the GlueSQL Team

The GlueSQL project was first conceived in the fall of 2019, and since then we have been developing it continuously. Personally, I have created various products in a variety of environments, including game development, backend server, and frontend development over the past decade. The experience gained through this process was a major motivation to start the GlueSQL project.

To put it grandly, the inconveniences felt while using different databases in various environments were a major motivation, wouldn't you say?

The start was actually a bit simple. Around 2019, I was mainly doing web front-end development. However, the lack of a structured database for state management and internal data processing made it very uncomfortable, especially since I couldn't use SQL databases and the like. So I started to lightly create an SQL database that could run on a web browser. Also, I wanted to use Rust, but after failing to introduce it at the company I was working for at the time, I decided to use it in my own project.

But as I started developing, my dreams grew significantly. Beyond a SQL database that simply operates on a web browser, I started envisioning a database that fits the name "Glue", one that can easily be ported to various environments, and I continue that journey to this day.

Whether I took the database project too lightly, or because the features I wanted kept increasing, the content to be developed kept expanding. As a result, I ended up investing full time in the GlueSQL project development for over three years. For a year in between, I even juggled full-time software engineering work alongside GlueSQL development. Currently, I'm back to developing the GlueSQL project full time, alongside various part-time contributors.

Now, we're getting very close to the starting point of the picture I wanted to create through GlueSQL, and thankfully, with contributors joining me, I am not alone.

The Sustainability and Business Aspect of GlueSQL

I believe that what we create through GlueSQL will make a great contribution to the world and make many software engineers happy. This gives me immense strength to continue developing even in difficult situations. However, we cannot accomplish everything with pure passion alone. As much as the GlueSQL project can make a significant contribution, I also see it as holding great business value.

The business strategy of GlueSQL may be somewhat different from other databases. We distribute the project itself as open source under the Apache-2.0 license, so that anyone can use it fully, and we do not consider pricing methods such as restricting features to the storages we support. In fact, if there is any player who can do it better, there's no way to prevent them from taking the GlueSQL project and making it their own.

But we believe that GlueSQL has great potential in this regard. Anyone can participate and they are free to distribute their own storage in the way they want, whether it's open source, private, or commercial. This eliminates the need to create something to replace the GlueSQL project. We aim to prevent the need to recreate the wheel that we provide using GlueSQL.

Moreover, our GlueSQL team seeks to continually expand our group of developers and companies working with us. During this development process, while they can certainly implement everything on their own, there is also no reason not to collaborate with our GlueSQL Team, especially for databases like NoSQL that have their own planners and execution layers. If you have a REST API and want to enhance convenience through SQL support, you can do it yourself or you can collaborate with us.

In addition, for some storages, we can also participate as players in the same position as other custom storage developers. We plan to expand the GlueSQL ecosystem in various ways, such as technical support and storage development.

We are finally ready to provide GlueSQL to users at the production level. We are accelerating the development of GlueSQL. If you are a company interested in storage development like SQL support, or if you resonate with our vision and want to join us, please contact us at taehoon@gluesql.com.

Conclusion

The continued emergence of new databases is driven by the demand for diverse and specialized databases, such as those optimized for Large Language Models (LLMs) and databases catering to unique requirements, like embedded databases, OLAP, OLTP, and time-series data processing. However, developing a new database from scratch is a significant undertaking, requiring extensive work, which often results in high costs.

GlueSQL presents a solution to this challenge by providing a unified query interface that can be ported across various environments, from key-value databases, NoSQL databases, log files, to REST APIs. It allows anyone to create custom storages, reducing the need for developers to build entirely new databases and to learn different usage methods for each database. Instead, they can focus on implementing their business logic using the same interface.

From a user perspective, GlueSQL offers the convenience of a unified query interface, easing the burden of learning different interfaces for each database. This simplification of interface use can also extend to AI, potentially enhancing the efficiency of AI automation.

GlueSQL's development plan includes significant enhancements to its query planner and aims to enable effective attachment of GlueSQL to NoSQL databases. The synergy of combining different databases is a valuable bonus in this process.

Since its inception in the fall of 2019, the GlueSQL team has continuously developed the project, driven by the desire to mitigate the inconveniences encountered while using different databases in various environments. The journey has been a rewarding one, with the GlueSQL project now at a point where it closely resembles the envisioned product.

GlueSQL, distributed under the Apache-2.0 license, is free for anyone to use and adapt. While the GlueSQL team welcomes collaboration with other developers and companies, they also see significant potential for the project as a business venture. The team is working to expand the GlueSQL ecosystem through a variety of initiatives, including technical support and storage development.

With GlueSQL now sufficiently prepared for practical applications, the team invites companies interested in storage development or those who share their vision to join them in their journey of revolutionizing database development.

· 10 min read
Taehoon Moon

Introduction: GlueSQL and Test-Driven Documentation

Recently, the GlueSQL project reached a significant milestone with the release of version 0.14. This new version brings a host of fresh features to the table, yet one of the most notable changes is in the realm of documentation. For the first time, we're proud to announce the launch of our official documentation website. Interested readers can explore the full range of user manuals at https://gluesql.org/docs.

Prior to this update, the only way to navigate GlueSQL was by manually inspecting the test code within the test suite. With the recent release, however, a comprehensive user manual has been made public to facilitate a more user-friendly experience. We hope that this new addition will prove beneficial to a broad spectrum of users.

The task of compiling an entire database manual in one go was daunting due to the sheer volume of content required. Surprisingly, this process turned out to be smoother than initially anticipated, largely due to the invaluable aid of ChatGPT, which was instrumental in automating much of the document creation. Specifically, around 80% of the SQL Syntax section was generated using this tool.

This remarkable feat was only possible due to the solid foundation of test codes previously established in GlueSQL. In this article, we'll share how we managed to leverage ChatGPT in such a unique way. Based on our recent experience of crafting documents grounded in testing, we've begun to consider the possibility of entirely automating document creation, save for the initial stages.

Along with sharing our journey so far, we will also reveal our plans for future test-based automation of documentation within GlueSQL.

Test Codes and Documentation

The GlueSQL project has placed a significant emphasis on writing test codes. This might be a given for a database project; however, the thoroughness of our approach is evident from our line coverage of nearly 99% for core codes. While we devoted considerable effort to creating these test codes, our primary focus has always been on a different aspect: ensuring that anyone can quickly grasp the content of the tests and easily add new ones.

The intent here is to empower newcomers to GlueSQL to understand the functionality of the software solely by examining integration tests, even in the absence of a user manual.

The integration tests for GlueSQL can be found in the test-suite workspace. For example, here's an excerpt of the test code for the INSERT statement:

test_case!(insert, async move {
run!(
"
CREATE TABLE Test (
id INTEGER DEFAULT 1,
num INTEGER NULL,
name TEXT NOT NULL,
);"
);

test! {
name: "basic insert - single item",
sql: "INSERT INTO Test (id, num, name) VALUES (1, 2, 'Hi boo');",
expected: Ok(Payload::Insert(1))
};


test! {
sql: "INSERT INTO Test VALUES(17, 30, 'Sullivan');",
expected: Ok(Payload::Insert(1))
};

test! {
sql: "INSERT INTO Test (num, name) VALUES (28, 'Wazowski');",
expected: Ok(Payload::Insert(1))
};

test! {
sql: "SELECT * FROM Test;",
expected: Ok(select!(
id | num | name;
I64 | I64 | Str;
1 2 "Hi boo".to_owned();
3 9 "Kitty!".to_owned();
2 7 "Monsters".to_owned();
17 30 "Sullivan".to_owned();
1 28 "Wazowski".to_owned()
))
};

// ...
});

Despite being written in Rust, these test cases are designed to be comprehensible, even to those unfamiliar with the language. Each test is a complete scenario from start to finish, and the results of each operation are readily observable.

Given that identifying results from SELECT operations in the form of Rust enums and structs can be challenging, we actively utilized macros such as select! and select_with_null!. We've composed the test cases to demonstrate that the INSERT statement can handle a wide range of cases, including specifying all columns, omitting some, or omitting all.

test! {
sql: "INSERT INTO Test (id, num) VALUES (1, 10);",
expected: Err(InsertError::LackOfRequiredColumn("name".to_owned()).into())
};

The tests also include scenarios for expected faulty inputs, indicating the error returns in these situations.

By organizing the tests in this manner, we aim to make it easy for anyone to read and write tests. Our goal was for these tests to serve as "documentation" for GlueSQL contributors. At the time we were writing these tests, we didn't anticipate that they could actually become documentation themselves. But we've come to realize that they have extraordinary potential.

Leveraging ChatGPT

When we first embarked on writing the User Manual, we were overwhelmed by the sheer volume of content we had to generate. Around the same time, ChatGPT was gaining prominence, and we thought it might be worth trying out, if only to lighten our load slightly.

To our surprise, ChatGPT exceeded our expectations. If the test codes were well written, it was capable of automatically crafting an exceptional document based on them, capturing all essential details.

After several trials and errors, we settled on the following prompt for document generation. While it's still a challenge to use the same prompt for all documentation, we made minor modifications to suit different situations:

I'm creating an SQL database documentation website, and I'd like you to help me with one of the pages that introduces the SQL syntax for GlueSQL.

1. Please provide the response content in the "markdown" format, so I can copy and paste it directly. Keep this constraint in mind while writing.
2. Regardless of the language I use, I need the content written in English.
3. I will provide some test case code written in the Rust language, which contains SQL examples. Please write the documentation based on these examples, but feel free to change the table names, column names, and data types as needed. Don't include any Rust related content or text in the response. all the response code example should be in plain SQL.
4. GlueSQL does not have the VARCHAR type. If you want to use that, please use TEXT instead. You don't need to mention this in the response.
5. Wrap the entire response text using <pre> and </pre> tags so I can copy all the content easily.

Now, I'd like you to write the following request:
SQL Statement - "INSERT"

Here's an example test code you can refer to:

test_case!(insert, async move {
run!(...

Generally, we used the template above, and copied and pasted the test code from our existing test-suite. We leveraged this method to harness our many tests to assist in the creation of the user manual. In the next section, we'll showcase a sample of the documentation generated in this manner. It's quite impressive.

Success Case: Automated User Manual of GlueSQL

Thanks to ChatGPT, the resulting INSERT document page can be viewed at the following link. It's important to note that we used ChatGPT 4 for this task. Version 3.5 wasn't quite up to the task, and using version 4 was the minimum requirement.

https://gluesql.org/docs/dev/sql-syntax/statements/data-manipulation/insert

INSERT Statement

The results were quite impressive. ChatGPT neatly categorized the test cases, explained the syntax, outlined constraints, and provided appropriate examples. It didn't stop there; it also skillfully recognized error test cases and incorporated them into the documentation, as shown below.

INSERT Statement

Isn't it amazing?

Future Plans: Fully Automating Documentation Generation

While the current documentation is far from perfect and there are many aspects that can be improved, we see great potential in this approach. We believe it's entirely possible to automate the process of writing this kind of document, and writing in general.

In the past, documents like user manuals required a great deal of effort to maintain once they were written. If a document contained real code examples, verifying that the code still worked was often a tedious task. With the ability to automatically generate documentation as we have done here, these issues are no longer problematic.

Previously, you would have to write tests and then also document them separately. If you had to support multiple languages, that would be an additional task. With a tool like ChatGPT, you can automate all of this. All a developer has to do is write the tests. This alone can be sufficient. You can generate documents automatically based on the tests. Eventually, we can even support automatically translating these documents into multiple languages.

The GlueSQL project repository is currently hosted on GitHub and makes good use of various GitHub Actions. We envision a GitHub Action that automatically regenerates a document corresponding to a test when a user modifies the test and raises a Pull Request. Another GitHub Action could automatically translate updated documents into supported languages and create new Pull Requests. The possibilities are truly endless.

Not only will this help with document generation, but it will also provide clear guidelines for writing better test code. If we can automatically generate documents based on written tests, the quality of those documents can serve as an indicator of the quality of the tests themselves. This means that a document automation tool can play the role of a good reviewer for tests. It can greatly reduce the time and effort required for painstakingly reviewing the quality of each test. Developers can also write tests without pressure, evaluate their test code by looking at the generated document, and improve it.

Furthermore, multi-language support becomes a breeze. In my personal experience as a software engineer over the past decade, developing various products such as games, web services, and applications, I often needed to support multiple languages. Each time, there was no definite solution. The optimal approach varied depending on the situation, and there were many things to consider when entrusting translations, such as effectively communicating the context of the target service to the translator. Moreover, regularly updating content and having it retranslated into various languages was a very tedious process. While I tried to automate as much as possible by creating various tools, I was never fully satisfied. I believe ChatGPT can completely solve these issues. If there is a need to provide project-specific context, all you need to do is prepare a prompt in advance. Instead of having to rely on and wait for professional translators, we can now entrust this task to ChatGPT, and we only need a few people to review the translated content.

We are nearing a world where documentation is no longer a burden for developers.

Conclusion: The Value of Test-Driven Documentation

The use of ChatGPT to generate documentation has proven a significant step forward in the GlueSQL user manual creation process. Through test-driven documentation, we've managed to automate a substantial part of the manual creation process, saving time and effort, and increasing accuracy.

Moreover, this process has unveiled a new potential for documentation: the possibility of fully automating document generation. We've seen that quality tests can become quality documentation with the help of AI, leading to more efficient workflows and possibly better test code as a result.

The journey doesn't stop here. We envision leveraging this capability further to auto-translate our documents into multiple languages, making our product more accessible to a global audience.

As we progress, we hope that our experience can inspire other developers to explore and embrace the benefits of AI-generated, test-driven documentation. It's not just about saving time—it's about improving the way we work, communicate, and share knowledge.

· 11 min read
Taehoon Moon

Introduction

The divide between SQL and NoSQL databases has often presented challenges in database management. GlueSQL, a unique database maker library, aims to blur this boundary, providing a versatile tool for handling these two distinct types of databases.

In this article, we explore how GlueSQL navigates the features of SQL and NoSQL databases, offering an integrated solution that promotes flexibility and efficiency. With its ability to unify disparate database types, GlueSQL heralds a new age of adaptable database creation and management.

The Interface Perspective: SQL & AST Builder

When we talk about SQL databases, it's almost a given that they support SQL - the standard query language. Although there are slight variations between databases, the convenience of using a similar SQL language across multiple databases cannot be overstated. However, from a software engineer's perspective, there's room for improvement. In most software development scenarios, a specific programming language is used. SQL is a separate language, which can cause friction when integrating it into your software. As a result, rather than using raw SQL, many developers employ query builders or ORMs to manipulate SQL conveniently using their preferred programming language. Although it's not efficient to generate SQL using a query builder and then parse it again in the database, it's a practical and effective choice.

On the other hand, NoSQL databases offer different mechanisms. Some of them have their own language similar to SQL, but most provide an interface library developed specifically for each programming language. While SQL databases rely on external query builder libraries to provide an interface for each programming language, NoSQL databases mostly develop and offer these libraries themselves. If we discount the convenience of SQL language, this is one of the major factors that make NoSQL databases more comfortable to use. Since query builder libraries supporting SQL databases often cater to multiple SQL databases, they are limited in fully supporting unique features of each database. NoSQL databases, on the other hand, can freely manage their interface libraries without these restrictions.

Providing a query interface for each programming language is not a fundamental difference between SQL and NoSQL, but we generally accept it implicitly.

Let's see what happens if we break down this boundary, using GlueSQL as an example. As you can see from the SQL postfix, GlueSQL supports SQL and can be classified as an SQL database.

CREATE TABLE Glue (id INTEGER, name TEXT);

INSERT INTO Glue VALUES (1, "hello"), (2, "gluesql");

SELECT * FROM Glue WHERE id = 1;

However, GlueSQL also supports its own query builder, like a NoSQL database. +

· 14 min read
Taehoon Moon

Introduction

GlueSQL is a versatile database project designed for exceptional portability across a broad range of environments, from embedded systems and servers to web and mobile platforms. The core goal is to support diverse storage environments and manage various data types with a standard SQL approach.

Imagine handling files like CSV, JSONL, and Parquet, or transforming key-value or NoSQL databases such as RocksDB, Redis, and MongoDB into SQL-supporting databases—all feasible with GlueSQL. It can also operate with storages supported in web browsers.

GlueSQL's essential feature is providing a management layer for these diverse storage scenarios without requiring data migration. The broader aim is to facilitate portability of GlueSQL to any environment supporting read or read-write operations. This extends to APIs like GitHub, or messengers like Discord or Slack.

GlueSQL supports both structured and unstructured data and is written in Rust for compatibility with various environments. While portability is its core value, the emphasis is on creating an intuitive, comfortable development environment for easy custom storage implementation.

Ultimately, GlueSQL aims to significantly reduce the cost, time, and complexity of developing new databases. By leveraging GlueSQL for the parser, planner, and execution layer, developers can focus on creating specific storage implementations, leading to a more convenient query interface like SQL for many environments.

The Problem: Why Reinvent the Database?

Despite the numerous database implementations that currently exist, the emergence of new databases continues. The primary reason behind this trend is our need for databases for a broad spectrum of distinct purposes. For instance, new databases are surfacing that are specifically optimized for Large Language Models (LLMs) like ChatGPT. The range is wide and diverse, encompassing embedded databases, OLAP for data analysis, OLTP databases optimized for online transactions, databases specialized for time-series data processing, and many more.

With such varied requirements, we find ourselves in constant need of fresh databases. However, constructing a database from scratch is a monumental task. It necessitates defining a query interface for handling the database and implementing a corresponding parser. Moreover, a separate execution layer for running operations must be built. Also, the planning layer, which is responsible for devising execution strategies, is a vital aspect of this process. Let's not forget about the critical storage layer that physically reads and stores the data. In a nutshell, there's a daunting amount of work involved in developing a new database.

Given these circumstances, it's understandable why numerous emerging databases resort to high pricing structures—they need immediate revenue to offset continuous development costs.

But the story doesn't end here. Query interfaces like SQL are indeed useful for serious tasks, but they also provide excellent utility for handling simple log files such as CSV, JSONL, Parquet, and even for utilizing REST APIs for various applications. The issue arises when a complex query interface needs to be provided even for these lighter storage requirements—it necessitates a development process almost identical to building a sophisticated database. Implementing an entire parser and execution layer just to add SQL support to an existing service can seem like an excessive burden.

Whether it's a simple storage environment or a serious task, the key lies in the storage layer, which involves the actual reading and storing of data. So, what if developers focused on implementing these storage mechanisms while the remaining parts could be handled using existing libraries? This is the role that GlueSQL aspires to play.

The Vision of GlueSQL

The GlueSQL project aims to offer a unified query interface for various environments. The goal is to allow anyone to port and use SQL and GlueSQL's proprietary query builder, the AST Builder, in any desired environment. This could range from key-value databases, serious NoSQL databases, log files, and even REST API services. Essentially, if a service supports reading or read-writing data, regardless of the data type, it can readily support a complex query interface via GlueSQL.

Presently, the GlueSQL project itself directly supports a few storage types as reference storages. These include in-memory storage for non-persistent data handling, sled storage, which is a key-value database written in Rust, JSON storage for handling JSON and JSONL files, and a storage that ports SQL to the web browser's IndexedDB. While the GlueSQL Team is primarily developing these, the aim is to allow anyone to create such custom storages for a wide array of purposes, thus enabling them to assemble the database of their choosing.

Imagine using GlueSQL's SQL and AST Builder everywhere, with the simple method of swapping out storages to operate in diverse settings. It could significantly reduce software development costs. Developers wouldn't need to learn the different usage methods for each database. Instead, they could focus solely on implementing business logic using the same interface.

Our vision is to reduce database development costs by 10 times, or even more than 20 times. We aim to gather diverse database creators under the GlueSQL banner, making it the go-to solution for cost-effective database development.

Benefits to Database Users: Unifying Query Interfaces, Streamlining Software Development, and Reducing Costs

From the perspective of the users who engage with databases, there has always been the burden of learning different interfaces to interact with each database. The approach required to work with Redis is different from that necessary for MongoDB. Likewise, handling SQL databases necessitates using SQL. Although SQL databases generally use a common SQL, the SQL they support can considerably vary when examined in detail.

Naturally, there are legitimate reasons for such differences. Each database focuses on different areas, and to cater to specialized functionalities, they incorporate dedicated interface mechanisms. However, not all application development needs to utilize these database-specific core special functionalities.

Let's look at a couple of examples:

Suppose you're developing a back-end application that uses MySQL as the database and Redis for caching. Due to the vast differences in handling SQL databases and Redis, you would have to develop using different methods when storing data.

Here's another scenario: +Imagine you're implementing a data migration pipeline between various databases and log files. Let's say you're transferring Parquet to Redis or MongoDB. In this case, you would need to convert data using different methods for each, all of which would be a cumbersome process.

In both of the above examples, GlueSQL can directly address and solve the issues. It offers the convenience of a uniform query interface to deal with these matters. In certain scenarios, even the construction of a data pipeline can potentially be solved with a single SQL query, thanks to GlueSQL.

Benefits to Database Developers: Drastically Lowering Development Costs and Simplifying the Creation of Purpose-Built Databases

If you want to support SQL in the desired environment, using GlueSQL essentially requires you to implement an interface for Storage. There's no need to support all functionalities from the beginning. You can start lightly, choosing and implementing storage features suitable for the environment you want to create. To facilitate this, GlueSQL also provides a library in the form of a test suite to easily validate the storage you've implemented.

Lowering development costs in this way will enable a broader range of developers to support the GlueSQL query interface. As more developers join, a significant synergy can be generated. Designing a query interface from scratch involves a great deal of work, including planning and supporting the interface for different target programming languages.

However, despite all this hard work, it is not easy to attract database users accustomed to different methods.

Consider that the SQL and AST Builder provided by GlueSQL are already securing numerous users. This eliminates the need for efforts to promote a newly planned query interface. Over the years, many new databases have emphasized compatibility with PostgreSQL or MySQL for similar reasons. As GlueSQL places a strong emphasis on portability in its query interface planning, it allows for more flexible configuration according to the desired situation. Through the AST Builder, it also eliminates the cost of porting to different languages.

For many database developers, using GlueSQL can be an optimal choice, as it can save costs and quickly secure users.

Let me mention one more thing: what's convenient for humans... could be applied to AI as well. Rather than making AI write automation code using different databases, providing a common query interface can be much more efficient.

The Future with GlueSQL

GlueSQL has been and will continue to improve and develop new features to enable portability in various environments. Thanks to the schemaless data support added last year, it is now possible to handle both structured data with schema and unstructured data like JSON simultaneously. This has significantly increased the range of storage environments that can be supported.

One of the key features added last year was the AST Builder. This feature allowed us to escape the confines of SQL and provide an interface for comfortably handling data in the programming languages used for development.

Of course, improving existing features is extremely important, and there are many new features to be added. As a major development plan this year, we aim to develop features to effectively attach GlueSQL to NoSQL databases with their own planners and execution layers. The GlueSQL query planner, currently at a basic level, will see significant changes this year. With the expansion of this planner, not only NoSQL databases but also other SQL databases could be supported without sacrificing performance using GlueSQL.

The synergy that arises from the combination of different databases is a significant bonus in this process.

The Journey of the GlueSQL Team

The GlueSQL project was first conceived in the fall of 2019, and since then we have been developing it continuously. Personally, I have created various products in a variety of environments, including game development, backend server, and frontend development over the past decade. The experience gained through this process was a major motivation to start the GlueSQL project.

To put it grandly, the inconveniences felt while using different databases in various environments were a major motivation, wouldn't you say?

The start was actually a bit simple. Around 2019, I was mainly doing web front-end development. However, the lack of a structured database for state management and internal data processing made it very uncomfortable, especially since I couldn't use SQL databases and the like. So I started to lightly create an SQL database that could run on a web browser. Also, I wanted to use Rust, but after failing to introduce it at the company I was working for at the time, I decided to use it in my own project.

But as I started developing, my dreams grew significantly. Beyond a SQL database that simply operates on a web browser, I started envisioning a database that fits the name "Glue", one that can easily be ported to various environments, and I continue that journey to this day.

Whether I took the database project too lightly, or because the features I wanted kept increasing, the content to be developed kept expanding. As a result, I ended up investing full time in the GlueSQL project development for over three years. For a year in between, I even juggled full-time software engineering work alongside GlueSQL development. Currently, I'm back to developing the GlueSQL project full time, alongside various part-time contributors.

Now, we're getting very close to the starting point of the picture I wanted to create through GlueSQL, and thankfully, with contributors joining me, I am not alone.

The Sustainability and Business Aspect of GlueSQL

I believe that what we create through GlueSQL will make a great contribution to the world and make many software engineers happy. This gives me immense strength to continue developing even in difficult situations. However, we cannot accomplish everything with pure passion alone. As much as the GlueSQL project can make a significant contribution, I also see it as holding great business value.

The business strategy of GlueSQL may be somewhat different from other databases. We distribute the project itself as open source under the Apache-2.0 license, so that anyone can use it fully, and we do not consider pricing methods such as restricting features to the storages we support. In fact, if there is any player who can do it better, there's no way to prevent them from taking the GlueSQL project and making it their own.

But we believe that GlueSQL has great potential in this regard. Anyone can participate and they are free to distribute their own storage in the way they want, whether it's open source, private, or commercial. This eliminates the need to create something to replace the GlueSQL project. We aim to prevent the need to recreate the wheel that we provide using GlueSQL.

Moreover, our GlueSQL team seeks to continually expand our group of developers and companies working with us. During this development process, while they can certainly implement everything on their own, there is also no reason not to collaborate with our GlueSQL Team, especially for databases like NoSQL that have their own planners and execution layers. If you have a REST API and want to enhance convenience through SQL support, you can do it yourself or you can collaborate with us.

In addition, for some storages, we can also participate as players in the same position as other custom storage developers. We plan to expand the GlueSQL ecosystem in various ways, such as technical support and storage development.

We are finally ready to provide GlueSQL to users at the production level. We are accelerating the development of GlueSQL. If you are a company interested in storage development like SQL support, or if you resonate with our vision and want to join us, please contact us at taehoon@gluesql.com.

Conclusion

The continued emergence of new databases is driven by the demand for diverse and specialized databases, such as those optimized for Large Language Models (LLMs) and databases catering to unique requirements, like embedded databases, OLAP, OLTP, and time-series data processing. However, developing a new database from scratch is a significant undertaking, requiring extensive work, which often results in high costs.

GlueSQL presents a solution to this challenge by providing a unified query interface that can be ported across various environments, from key-value databases, NoSQL databases, log files, to REST APIs. It allows anyone to create custom storages, reducing the need for developers to build entirely new databases and to learn different usage methods for each database. Instead, they can focus on implementing their business logic using the same interface.

From a user perspective, GlueSQL offers the convenience of a unified query interface, easing the burden of learning different interfaces for each database. This simplification of interface use can also extend to AI, potentially enhancing the efficiency of AI automation.

GlueSQL's development plan includes significant enhancements to its query planner and aims to enable effective attachment of GlueSQL to NoSQL databases. The synergy of combining different databases is a valuable bonus in this process.

Since its inception in the fall of 2019, the GlueSQL team has continuously developed the project, driven by the desire to mitigate the inconveniences encountered while using different databases in various environments. The journey has been a rewarding one, with the GlueSQL project now at a point where it closely resembles the envisioned product.

GlueSQL, distributed under the Apache-2.0 license, is free for anyone to use and adapt. While the GlueSQL team welcomes collaboration with other developers and companies, they also see significant potential for the project as a business venture. The team is working to expand the GlueSQL ecosystem through a variety of initiatives, including technical support and storage development.

With GlueSQL now sufficiently prepared for practical applications, the team invites companies interested in storage development or those who share their vision to join them in their journey of revolutionizing database development.

· 10 min read
Taehoon Moon

Introduction: GlueSQL and Test-Driven Documentation

Recently, the GlueSQL project reached a significant milestone with the release of version 0.14. This new version brings a host of fresh features to the table, yet one of the most notable changes is in the realm of documentation. For the first time, we're proud to announce the launch of our official documentation website. Interested readers can explore the full range of user manuals at https://gluesql.org/docs.

Prior to this update, the only way to navigate GlueSQL was by manually inspecting the test code within the test suite. With the recent release, however, a comprehensive user manual has been made public to facilitate a more user-friendly experience. We hope that this new addition will prove beneficial to a broad spectrum of users.

The task of compiling an entire database manual in one go was daunting due to the sheer volume of content required. Surprisingly, this process turned out to be smoother than initially anticipated, largely due to the invaluable aid of ChatGPT, which was instrumental in automating much of the document creation. Specifically, around 80% of the SQL Syntax section was generated using this tool.

This remarkable feat was only possible due to the solid foundation of test codes previously established in GlueSQL. In this article, we'll share how we managed to leverage ChatGPT in such a unique way. Based on our recent experience of crafting documents grounded in testing, we've begun to consider the possibility of entirely automating document creation, save for the initial stages.

Along with sharing our journey so far, we will also reveal our plans for future test-based automation of documentation within GlueSQL.

Test Codes and Documentation

The GlueSQL project has placed a significant emphasis on writing test codes. This might be a given for a database project; however, the thoroughness of our approach is evident from our line coverage of nearly 99% for core codes. While we devoted considerable effort to creating these test codes, our primary focus has always been on a different aspect: ensuring that anyone can quickly grasp the content of the tests and easily add new ones.

The intent here is to empower newcomers to GlueSQL to understand the functionality of the software solely by examining integration tests, even in the absence of a user manual.

The integration tests for GlueSQL can be found in the test-suite workspace. For example, here's an excerpt of the test code for the INSERT statement:

test_case!(insert, async move {
run!(
"
CREATE TABLE Test (
id INTEGER DEFAULT 1,
num INTEGER NULL,
name TEXT NOT NULL,
);"
);

test! {
name: "basic insert - single item",
sql: "INSERT INTO Test (id, num, name) VALUES (1, 2, 'Hi boo');",
expected: Ok(Payload::Insert(1))
};


test! {
sql: "INSERT INTO Test VALUES(17, 30, 'Sullivan');",
expected: Ok(Payload::Insert(1))
};

test! {
sql: "INSERT INTO Test (num, name) VALUES (28, 'Wazowski');",
expected: Ok(Payload::Insert(1))
};

test! {
sql: "SELECT * FROM Test;",
expected: Ok(select!(
id | num | name;
I64 | I64 | Str;
1 2 "Hi boo".to_owned();
3 9 "Kitty!".to_owned();
2 7 "Monsters".to_owned();
17 30 "Sullivan".to_owned();
1 28 "Wazowski".to_owned()
))
};

// ...
});

Despite being written in Rust, these test cases are designed to be comprehensible, even to those unfamiliar with the language. Each test is a complete scenario from start to finish, and the results of each operation are readily observable.

Given that identifying results from SELECT operations in the form of Rust enums and structs can be challenging, we actively utilized macros such as select! and select_with_null!. We've composed the test cases to demonstrate that the INSERT statement can handle a wide range of cases, including specifying all columns, omitting some, or omitting all.

test! {
sql: "INSERT INTO Test (id, num) VALUES (1, 10);",
expected: Err(InsertError::LackOfRequiredColumn("name".to_owned()).into())
};

The tests also include scenarios for expected faulty inputs, indicating the error returns in these situations.

By organizing the tests in this manner, we aim to make it easy for anyone to read and write tests. Our goal was for these tests to serve as "documentation" for GlueSQL contributors. At the time we were writing these tests, we didn't anticipate that they could actually become documentation themselves. But we've come to realize that they have extraordinary potential.

Leveraging ChatGPT

When we first embarked on writing the User Manual, we were overwhelmed by the sheer volume of content we had to generate. Around the same time, ChatGPT was gaining prominence, and we thought it might be worth trying out, if only to lighten our load slightly.

To our surprise, ChatGPT exceeded our expectations. If the test codes were well written, it was capable of automatically crafting an exceptional document based on them, capturing all essential details.

After several trials and errors, we settled on the following prompt for document generation. While it's still a challenge to use the same prompt for all documentation, we made minor modifications to suit different situations:

I'm creating an SQL database documentation website, and I'd like you to help me with one of the pages that introduces the SQL syntax for GlueSQL.

1. Please provide the response content in the "markdown" format, so I can copy and paste it directly. Keep this constraint in mind while writing.
2. Regardless of the language I use, I need the content written in English.
3. I will provide some test case code written in the Rust language, which contains SQL examples. Please write the documentation based on these examples, but feel free to change the table names, column names, and data types as needed. Don't include any Rust related content or text in the response. all the response code example should be in plain SQL.
4. GlueSQL does not have the VARCHAR type. If you want to use that, please use TEXT instead. You don't need to mention this in the response.
5. Wrap the entire response text using <pre> and </pre> tags so I can copy all the content easily.

Now, I'd like you to write the following request:
SQL Statement - "INSERT"

Here's an example test code you can refer to:

test_case!(insert, async move {
run!(...

Generally, we used the template above, and copied and pasted the test code from our existing test-suite. We leveraged this method to harness our many tests to assist in the creation of the user manual. In the next section, we'll showcase a sample of the documentation generated in this manner. It's quite impressive.

Success Case: Automated User Manual of GlueSQL

Thanks to ChatGPT, the resulting INSERT document page can be viewed at the following link. It's important to note that we used ChatGPT 4 for this task. Version 3.5 wasn't quite up to the task, and using version 4 was the minimum requirement.

https://gluesql.org/docs/dev/sql-syntax/statements/data-manipulation/insert

INSERT Statement

The results were quite impressive. ChatGPT neatly categorized the test cases, explained the syntax, outlined constraints, and provided appropriate examples. It didn't stop there; it also skillfully recognized error test cases and incorporated them into the documentation, as shown below.

INSERT Statement

Isn't it amazing?

Future Plans: Fully Automating Documentation Generation

While the current documentation is far from perfect and there are many aspects that can be improved, we see great potential in this approach. We believe it's entirely possible to automate the process of writing this kind of document, and writing in general.

In the past, documents like user manuals required a great deal of effort to maintain once they were written. If a document contained real code examples, verifying that the code still worked was often a tedious task. With the ability to automatically generate documentation as we have done here, these issues are no longer problematic.

Previously, you would have to write tests and then also document them separately. If you had to support multiple languages, that would be an additional task. With a tool like ChatGPT, you can automate all of this. All a developer has to do is write the tests. This alone can be sufficient. You can generate documents automatically based on the tests. Eventually, we can even support automatically translating these documents into multiple languages.

The GlueSQL project repository is currently hosted on GitHub and makes good use of various GitHub Actions. We envision a GitHub Action that automatically regenerates a document corresponding to a test when a user modifies the test and raises a Pull Request. Another GitHub Action could automatically translate updated documents into supported languages and create new Pull Requests. The possibilities are truly endless.

Not only will this help with document generation, but it will also provide clear guidelines for writing better test code. If we can automatically generate documents based on written tests, the quality of those documents can serve as an indicator of the quality of the tests themselves. This means that a document automation tool can play the role of a good reviewer for tests. It can greatly reduce the time and effort required for painstakingly reviewing the quality of each test. Developers can also write tests without pressure, evaluate their test code by looking at the generated document, and improve it.

Furthermore, multi-language support becomes a breeze. In my personal experience as a software engineer over the past decade, developing various products such as games, web services, and applications, I often needed to support multiple languages. Each time, there was no definite solution. The optimal approach varied depending on the situation, and there were many things to consider when entrusting translations, such as effectively communicating the context of the target service to the translator. Moreover, regularly updating content and having it retranslated into various languages was a very tedious process. While I tried to automate as much as possible by creating various tools, I was never fully satisfied. I believe ChatGPT can completely solve these issues. If there is a need to provide project-specific context, all you need to do is prepare a prompt in advance. Instead of having to rely on and wait for professional translators, we can now entrust this task to ChatGPT, and we only need a few people to review the translated content.

We are nearing a world where documentation is no longer a burden for developers.

Conclusion: The Value of Test-Driven Documentation

The use of ChatGPT to generate documentation has proven a significant step forward in the GlueSQL user manual creation process. Through test-driven documentation, we've managed to automate a substantial part of the manual creation process, saving time and effort, and increasing accuracy.

Moreover, this process has unveiled a new potential for documentation: the possibility of fully automating document generation. We've seen that quality tests can become quality documentation with the help of AI, leading to more efficient workflows and possibly better test code as a result.

The journey doesn't stop here. We envision leveraging this capability further to auto-translate our documents into multiple languages, making our product more accessible to a global audience.

As we progress, we hope that our experience can inspire other developers to explore and embrace the benefits of AI-generated, test-driven documentation. It's not just about saving time—it's about improving the way we work, communicate, and share knowledge.

· 11 min read
Taehoon Moon

Introduction

The divide between SQL and NoSQL databases has often presented challenges in database management. GlueSQL, a unique database maker library, aims to blur this boundary, providing a versatile tool for handling these two distinct types of databases.

In this article, we explore how GlueSQL navigates the features of SQL and NoSQL databases, offering an integrated solution that promotes flexibility and efficiency. With its ability to unify disparate database types, GlueSQL heralds a new age of adaptable database creation and management.

The Interface Perspective: SQL & AST Builder

When we talk about SQL databases, it's almost a given that they support SQL - the standard query language. Although there are slight variations between databases, the convenience of using a similar SQL language across multiple databases cannot be overstated. However, from a software engineer's perspective, there's room for improvement. In most software development scenarios, a specific programming language is used. SQL is a separate language, which can cause friction when integrating it into your software. As a result, rather than using raw SQL, many developers employ query builders or ORMs to manipulate SQL conveniently using their preferred programming language. Although it's not efficient to generate SQL using a query builder and then parse it again in the database, it's a practical and effective choice.

On the other hand, NoSQL databases offer different mechanisms. Some of them have their own language similar to SQL, but most provide an interface library developed specifically for each programming language. While SQL databases rely on external query builder libraries to provide an interface for each programming language, NoSQL databases mostly develop and offer these libraries themselves. If we discount the convenience of SQL language, this is one of the major factors that make NoSQL databases more comfortable to use. Since query builder libraries supporting SQL databases often cater to multiple SQL databases, they are limited in fully supporting unique features of each database. NoSQL databases, on the other hand, can freely manage their interface libraries without these restrictions.

Providing a query interface for each programming language is not a fundamental difference between SQL and NoSQL, but we generally accept it implicitly.

Let's see what happens if we break down this boundary, using GlueSQL as an example. As you can see from the SQL postfix, GlueSQL supports SQL and can be classified as an SQL database.

CREATE TABLE Glue (id INTEGER, name TEXT);

INSERT INTO Glue VALUES (1, "hello"), (2, "gluesql");

SELECT * FROM Glue WHERE id = 1;

However, GlueSQL also supports its own query builder, like a NoSQL database. (Currently, only Rust is supported, but we're working on adding support for other languages.)

table("Glue")
.create_table()
.add_column("id INTEGER")
.add_column("name TEXT")
.execute(glue)

table("Glue")
.insert()
.values(vec![
vec![num(1), text("hello")],
vec![num(2), text("gluesql")],
])
.execute(glue)
.await;

table("Glue")
.select()
.filter(col("id").eq(1))
.execute(glue)
.await;

Let's reconsider the implicit distinction between SQL and NoSQL. GlueSQL indeed supports SQL, but it also officially develops and offers its own query builder. This query builder is not a secondary tool for SQL. While most SQL query builder libraries ultimately generate SQL strings, GlueSQL's builder directly creates an AST (Abstract Structure Tree) that is used for execution within GlueSQL. Hence, we call it the AST Builder. This means SQL and the AST Builder are two equally supported interfaces in GlueSQL.

This also offers an additional advantage:

table("Glue")
.select()
// 1.
.filter(col("id").eq(1))
// 2.
.filter("id = 1")
.execute(glue)
.await;

Because GlueSQL already supports SQL, not only can you use the custom interface in the AST Builder, but you can also use familiar SQL syntax in part. Whether you use col("id").eq(1) or "id = 1", you can use it in the way you prefer. The AST Builder interface, although initially unfamiliar, allows a gradual migration similar to writing SQL for your convenience.

Thus, we've dismantled one of the implicit distinctions between SQL and NoSQL. However, it's more of an implicit differentiation than a fundamental one. There are more significant design differences that we'll explore next.

Structured & Unstructured Data

In this section, we'll discuss how SQL and NoSQL handle data. SQL generally deals with structured data, and recently, it's been made to support semi-structured data as well. On the other hand, NoSQL supports schemaless, unstructured data. Then, we'll explain in detail how GlueSQL handles these two types of data. The last part of this section will provide a segue into the next section where we'll discuss the decomposition of database functions.

When talking about SQL databases, one aspect is usually considered together: SQL databases have a defined schema.

CREATE TABLE Foo (
id INTEGER,
name TEXT,
rate FLOAT NULL
);

However, these days, SQL databases tend to support semi-structured data types, such as LIST or JSON. But, supporting completely schemaless, unstructured data is a different matter. SQL databases typically require a minimum schema.

What about NoSQL databases? As NoSQL databases vary significantly, we can't make definitive statements. But let's consider a typical document database like MongoDB. Unlike SQL databases, it doesn't enforce a schema. Essentially, you can insert any form of data directly. Often, NoSQL databases support schemaless data, but they lack features that enforce a schema like SQL. They generally support structure via validation methods, rather than structured access.

Is there no choice but to distinguish between structured data and unstructured, schemaless data so clearly? GlueSQL is being developed with the goal of being adaptable in various environments. Being forced to choose regarding this schema constraint was quite inconvenient. We started pondering if we couldn't benefit from both aspects - supporting both schema and schemaless data simultaneously, and we eventually found the answer. Let's look at how GlueSQL currently solves this issue through familiar SQL examples.

CREATE TABLE Names (id INTEGER, name TEXT);
INSERT INTO Names VALUES (1, 'glue'), (2, 'sql');

You can create a regular table with a schema like this. But GlueSQL's choice for creating a schemaless table is as follows:

CREATE TABLE Logs;
INSERT INTO Logs VALUES
('{ "id": 1, "value": 30 }'),
('{ "id": 2, "rate": 3.0, "list": [1, 2, 3] }'),
('{ "id": 3, "rate": 5.0, "value": 100 }');

It creates a table without column definitions! If you do this, GlueSQL recognizes the table as schemaless and processes it internally.

SELECT id, rate, list[0] FROM Logs WHERE id = 2;

Although the way to create the table was a bit special, using it isn't much different from the regular SQL SELECT statement. Not only can you differentiate between schema and schemaless when creating tables, but you can also use them interchangeably!

SELECT * FROM Names JOIN Logs ON Names.id = Logs.id;
/*
| id | list | name | rate | value |
|----|---------|------|------|-------|
| 1 | | glue | | 30 |
| 2 |[1, 2, 3]| sql | 3 | |
*/

Here's an example of querying data by INNER JOINing the Names table, which has a schema, and the Logs table, which is schemaless. GlueSQL has resolved this problem by allowing the internal execution layer to handle both vector-type data, for cases where each row has a defined schema, and map-type data for schemaless cases.

Thanks to this, the variety of storage that can be supported through GlueSQL has expanded significantly. If there were previously limitations to supporting NoSQL databases that support schemaless data, that is no longer the case. The reference storage where you can directly experience this schemaless data support is JSON Storage. It offers features that allow you to deal directly with unstructured data like JSON using GlueSQL.

If GlueSQL starts from the perspective of an SQL database and expands, by providing the AST Builder directly, it once blurs the boundary, and by supporting unstructured data simultaneously, it knocks down the boundary once more. How do you like it?

Decomposing Database Functionality: Breaking Down SQL and NoSQL Features

The distinction between SQL and NoSQL is not just about whether they support unstructured data. Of course, there are examples like unstructured data, which is mainly supported only in NoSQL, but in many cases, SQL databases tend to support more diverse and complex queries. NoSQL often gains other advantages in exchange for reducing the range of query support provided by SQL databases.

GlueSQL is ambitious. It has devised a rather interesting method to support all of this through SQL and the AST Builder, with the same interface. When we usually say SQL database, it implicitly assumes that a lot of features have been fully implemented. Create tables by specifying a schema, modify schemas with "alter table", support both clustered and non-clustered indexes, and support transactions. And there's so much more. But the functionality that is naturally supported in SQL databases may not be natural in other environments.

Let's think about JSON Storage. GlueSQL's JSON Storage allows you to handle JSON, JSONL files using SQL and the AST Builder. This JSON Storage does not support atomic operations or transactions. Of course, it would be great if it did, but implementing and executing them would be a significant performance burden. In most cases, when you want to simply browse and handle JSONL files, the overhead caused by transactions can be an unnecessary burden. In this case, you want to handle JSON, JSONL files using SQL, but you don't necessarily need transactions.

To meet the requirements of these diverse environments, GlueSQL has separated the functionality of what we usually call an SQL database into multiple independent interfaces. Store, StoreMut, AlterTable, Transaction, .. These are just a few of the various storage interfaces that GlueSQL currently supports. @@ -23,10 +23,10 @@ If you want to support the ALTER TABLE statement, you can additionally implement the AlterTable interface. The Transaction interface works the same way. The interesting part is that, except for Store and StoreMut, all other storage interfaces can be implemented independently. GlueSQL allows you to choose and implement only the features you need. -And it's not just about providing interfaces. It also provides integration tests suitable for each situation to verify what you have implemented. You just need to implement the interface and import the corresponding test case for verification.

In addition to supporting both structured and unstructured data simultaneously, GlueSQL provides the ability to divide the functionality of a database into multiple independent features and selectively implement them. This allows GlueSQL to be ported to a wide variety of environments without any burden.

Conclusion

GlueSQL, while serving as a database that provides its own reference storage, is fundamentally a library designed to simplify the creation of databases. One of the substantial challenges GlueSQL had to overcome in order to support a diverse array of environments was to address the distinctive features that separate conventional SQL databases from NoSQL databases. GlueSQL achieved this through several innovative approaches, managing to support both categories simultaneously despite their significantly different characteristics.

It offers support for SQL alongside an AST Builder, and accommodates both structured and unstructured data. Additionally, it decomposes database functionalities into multiple independent features, allowing each environment to selectively implement the functionalities it requires.

These unique attributes enable GlueSQL to live up to its 'Glue' prefix by facilitating effortless porting across various environments. While we have been developing it for several years, there is still much ground to cover. However, the fact that we are now able to introduce it publicly attests to our successful technological validation and completion of a demonstrable level of implementation.

Through GlueSQL, we hope to provide developers with a unified query interface that can be customized according to their needs, thereby enabling them to produce efficient products more effortlessly. There's a promising future ahead for GlueSQL, and we look forward to its contributions to the technology community.

· 11 min read
Taehoon Moon

We now provide an official documentation website at https://gluesql.org/docs

🚀 Features

🍀 Schemaless data support

GlueSQL now supports creating tables without a schema, allowing for both structured and unstructured data to be stored in the same table. +And it's not just about providing interfaces. It also provides integration tests suitable for each situation to verify what you have implemented. You just need to implement the interface and import the corresponding test case for verification.

In addition to supporting both structured and unstructured data simultaneously, GlueSQL provides the ability to divide the functionality of a database into multiple independent features and selectively implement them. This allows GlueSQL to be ported to a wide variety of environments without any burden.

Conclusion

GlueSQL, while serving as a database that provides its own reference storage, is fundamentally a library designed to simplify the creation of databases. One of the substantial challenges GlueSQL had to overcome in order to support a diverse array of environments was to address the distinctive features that separate conventional SQL databases from NoSQL databases. GlueSQL achieved this through several innovative approaches, managing to support both categories simultaneously despite their significantly different characteristics.

It offers support for SQL alongside an AST Builder, and accommodates both structured and unstructured data. Additionally, it decomposes database functionalities into multiple independent features, allowing each environment to selectively implement the functionalities it requires.

These unique attributes enable GlueSQL to live up to its 'Glue' prefix by facilitating effortless porting across various environments. While we have been developing it for several years, there is still much ground to cover. However, the fact that we are now able to introduce it publicly attests to our successful technological validation and completion of a demonstrable level of implementation.

Through GlueSQL, we hope to provide developers with a unified query interface that can be customized according to their needs, thereby enabling them to produce efficient products more effortlessly. There's a promising future ahead for GlueSQL, and we look forward to its contributions to the technology community.

· 11 min read
Taehoon Moon

We now provide an official documentation website at https://gluesql.org/docs

🚀 Features

🍀 Schemaless data support

GlueSQL now supports creating tables without a schema, allowing for both structured and unstructured data to be stored in the same table. To create a schemaless table, simply run CREATE TABLE without specifying any columns. For more information on querying schemaless data, please refer to the following link: querying schemaless data

CREATE TABLE Bar;

To insert values,

INSERT INTO Bar VALUES
('{ "name": "ast", "value": 30 }'),
('{ "name": "glue", "rate": 3.0, "list": [1, 2, 3] }'),

Then, selecting values from schemaless table is simple.

SELECT name, rate, list[0] FROM Bar WHERE name = 'glue';

e.g.

CREATE TABLE Names (id INTEGER, name TEXT);
INSERT INTO Names VALUES (1, 'glue'), (2, 'sql');

CREATE TABLE Logs;
INSERT INTO Logs VALUES
('{ "id": 1, "value": 30 }'),
('{ "id": 2, "rate": 3.0, "list": [1, 2, 3] }'),
('{ "id": 3, "rate": 5.0, "value": 100 }');

SELECT * FROM Names JOIN Logs ON Names.id = Logs.id;
/*
| id | list | name | rate | value |
|----|---------|------|------|-------|
| 1 | | glue | | 30 |
| 2 |[1, 2, 3]| sql | 3 | |
*/

🍀 IndexedDB & WebStorage supports in JavaScript package

GlueSQL supports handling in-memory, localStorage, sessionStorage, and even IndexedDB using the same SQL syntax. All you need to know is how to specify the ENGINE when creating a table.

e.g.

CREATE TABLE Mem (mid INTEGER) ENGINE = memory;
CREATE TABLE Loc (lid INTEGER) ENGINE = localStorage;
CREATE TABLE Ses (sid INTEGER) ENGINE = sessionStorage;
CREATE TABLE Idb (iid INTEGER) ENGINE = indexedDB;

SELECT
mid, lid, sid, iid
FROM Mem
JOIN Loc
JOIN Ses
JOIN Idb;

🍀 Data Types - UINT32, UINT64, UINT128, POINT and FLOAT32

🍀 Functions - APPEND, PREPEND, RAND, FIND_IDX, INITCAP and CALC_DISTANCE

🍀 Store traits

User-level custom function

By implementing both the CustomFunction and CustomFunctionMut traits, users can create, use, and delete user-level custom functions. Although GlueSQL plans to continuously add various functions, users may still find them insufficient. In such cases, users can create their own user-level custom functions to supplement the built-in functions. Additionally, if there are repetitive business logic codes, they can be stored as custom functions. e.g.

CREATE FUNCTION ADD_ONE (n INT, x INT DEFAULT 1) RETURN n + x;

SELECT ADD_ONE(10) AS test;

DROP FUNCTION ADD_ONE;

Metadata

The Metadata trait is an optional implementation for providing additional metadata support in GlueSQL. GlueSQL does not enforce any specific metadata implementation, allowing custom storage developers to decide which type of metadata, such as create time, modify time, etc., they want to provide.

🍀 Storages

JSON Storage

Composite Storage

  • Add CompositeStorage which bundles multiple storages @panarch (#1068)

IndexedDB Storage

Web Storage

  • Add WebStorage - support localStorage \& sessionStorage for web browsers @panarch (#1050)

🍀 Other new features

🌊 Interface Changes

  • Remove Store trait related cfg features, @panarch (#1091)
  • Refactor CreateTable.columns from Vec<ColumnDef> to Option<Vec<ColumnDef>> @devgony (#1086)
  • Remove MutResult @panarch (#1073)
  • Update all store mut trait methods to take \&mut self @panarch (#1072)
  • Change StoreMut interface to use \&mut self, not to take ownership @panarch (#1071)
  • Modify default ColumnOption from NOT NULL to NULL @devgony (#997)

🌟 Improvements

🌳 Documentation

We now provide an official documentation website at https://gluesql.org/docs

Docs - setup

📋 Tests

🐛 Bug Fixes

  • Fix docusaurus pages/index broken link @panarch (#1214)
  • Fix docs/ Discord GlueSQL channel invite link address @panarch (#1213)
  • Fix InvalidJsonString error message replacing payload to fileName @devgony (#1185)
  • Fix TryFrom Value::Str to u128 not to use parse_uuid @ChobobDev (#1134)
  • Fix column alias with identifer for TableFactor::Derived @ding-young (#1119)
  • Pass data even when deleted_by is not present @ever0de (#1117)
  • Fix MemoryStorage \& WebStorage primary key support @panarch (#1115)
  • Fix plan::validate to handle CTAS and ITAS adding unit test @devgony (#1074)
  • Fix test-suite tester functions to show (found, expected) shape @panarch (#1028)
- - + + \ No newline at end of file diff --git a/docs/dev/blog/release-v0.14/index.html b/docs/dev/blog/release-v0.14/index.html index 3547bfa1..c5c7bb67 100644 --- a/docs/dev/blog/release-v0.14/index.html +++ b/docs/dev/blog/release-v0.14/index.html @@ -1,19 +1,19 @@ - + - + Release v0.14 | GlueSQL - - - + + +
-

Release v0.14

· 11 min read
Taehoon Moon

We now provide an official documentation website at https://gluesql.org/docs

🚀 Features

🍀 Schemaless data support

GlueSQL now supports creating tables without a schema, allowing for both structured and unstructured data to be stored in the same table. +

Release v0.14

· 11 min read
Taehoon Moon

We now provide an official documentation website at https://gluesql.org/docs

🚀 Features

🍀 Schemaless data support

GlueSQL now supports creating tables without a schema, allowing for both structured and unstructured data to be stored in the same table. To create a schemaless table, simply run CREATE TABLE without specifying any columns. For more information on querying schemaless data, please refer to the following link: querying schemaless data

CREATE TABLE Bar;

To insert values,

INSERT INTO Bar VALUES
('{ "name": "ast", "value": 30 }'),
('{ "name": "glue", "rate": 3.0, "list": [1, 2, 3] }'),

Then, selecting values from schemaless table is simple.

SELECT name, rate, list[0] FROM Bar WHERE name = 'glue';

e.g.

CREATE TABLE Names (id INTEGER, name TEXT);
INSERT INTO Names VALUES (1, 'glue'), (2, 'sql');

CREATE TABLE Logs;
INSERT INTO Logs VALUES
('{ "id": 1, "value": 30 }'),
('{ "id": 2, "rate": 3.0, "list": [1, 2, 3] }'),
('{ "id": 3, "rate": 5.0, "value": 100 }');

SELECT * FROM Names JOIN Logs ON Names.id = Logs.id;
/*
| id | list | name | rate | value |
|----|---------|------|------|-------|
| 1 | | glue | | 30 |
| 2 |[1, 2, 3]| sql | 3 | |
*/

🍀 IndexedDB & WebStorage supports in JavaScript package

GlueSQL supports handling in-memory, localStorage, sessionStorage, and even IndexedDB using the same SQL syntax. All you need to know is how to specify the ENGINE when creating a table.

e.g.

CREATE TABLE Mem (mid INTEGER) ENGINE = memory;
CREATE TABLE Loc (lid INTEGER) ENGINE = localStorage;
CREATE TABLE Ses (sid INTEGER) ENGINE = sessionStorage;
CREATE TABLE Idb (iid INTEGER) ENGINE = indexedDB;

SELECT
mid, lid, sid, iid
FROM Mem
JOIN Loc
JOIN Ses
JOIN Idb;

🍀 Data Types - UINT32, UINT64, UINT128, POINT and FLOAT32

🍀 Functions - APPEND, PREPEND, RAND, FIND_IDX, INITCAP and CALC_DISTANCE

🍀 Store traits

User-level custom function

By implementing both the CustomFunction and CustomFunctionMut traits, users can create, use, and delete user-level custom functions. Although GlueSQL plans to continuously add various functions, users may still find them insufficient. In such cases, users can create their own user-level custom functions to supplement the built-in functions. Additionally, if there are repetitive business logic codes, they can be stored as custom functions. e.g.

CREATE FUNCTION ADD_ONE (n INT, x INT DEFAULT 1) RETURN n + x;

SELECT ADD_ONE(10) AS test;

DROP FUNCTION ADD_ONE;

Metadata

The Metadata trait is an optional implementation for providing additional metadata support in GlueSQL. GlueSQL does not enforce any specific metadata implementation, allowing custom storage developers to decide which type of metadata, such as create time, modify time, etc., they want to provide.

🍀 Storages

JSON Storage

Composite Storage

  • Add CompositeStorage which bundles multiple storages @panarch (#1068)

IndexedDB Storage

Web Storage

  • Add WebStorage - support localStorage \& sessionStorage for web browsers @panarch (#1050)

🍀 Other new features

🌊 Interface Changes

  • Remove Store trait related cfg features, @panarch (#1091)
  • Refactor CreateTable.columns from Vec<ColumnDef> to Option<Vec<ColumnDef>> @devgony (#1086)
  • Remove MutResult @panarch (#1073)
  • Update all store mut trait methods to take \&mut self @panarch (#1072)
  • Change StoreMut interface to use \&mut self, not to take ownership @panarch (#1071)
  • Modify default ColumnOption from NOT NULL to NULL @devgony (#997)

🌟 Improvements

🌳 Documentation

We now provide an official documentation website at https://gluesql.org/docs

Docs - setup

📋 Tests

🐛 Bug Fixes

  • Fix docusaurus pages/index broken link @panarch (#1214)
  • Fix docs/ Discord GlueSQL channel invite link address @panarch (#1213)
  • Fix InvalidJsonString error message replacing payload to fileName @devgony (#1185)
  • Fix TryFrom Value::Str to u128 not to use parse_uuid @ChobobDev (#1134)
  • Fix column alias with identifer for TableFactor::Derived @ding-young (#1119)
  • Pass data even when deleted_by is not present @ever0de (#1117)
  • Fix MemoryStorage \& WebStorage primary key support @panarch (#1115)
  • Fix plan::validate to handle CTAS and ITAS adding unit test @devgony (#1074)
  • Fix test-suite tester functions to show (found, expected) shape @panarch (#1028)
- - + + \ No newline at end of file diff --git a/docs/dev/blog/revolutionizing-databases-by-unifying-query-interfaces/index.html b/docs/dev/blog/revolutionizing-databases-by-unifying-query-interfaces/index.html index 820f8c5f..39b58deb 100644 --- a/docs/dev/blog/revolutionizing-databases-by-unifying-query-interfaces/index.html +++ b/docs/dev/blog/revolutionizing-databases-by-unifying-query-interfaces/index.html @@ -1,18 +1,18 @@ - + - + GlueSQL - Revolutionizing Databases by Unifying Query Interfaces | GlueSQL - - - + + +
-

GlueSQL - Revolutionizing Databases by Unifying Query Interfaces

· 14 min read
Taehoon Moon

Introduction

GlueSQL is a versatile database project designed for exceptional portability across a broad range of environments, from embedded systems and servers to web and mobile platforms. The core goal is to support diverse storage environments and manage various data types with a standard SQL approach.

Imagine handling files like CSV, JSONL, and Parquet, or transforming key-value or NoSQL databases such as RocksDB, Redis, and MongoDB into SQL-supporting databases—all feasible with GlueSQL. It can also operate with storages supported in web browsers.

GlueSQL's essential feature is providing a management layer for these diverse storage scenarios without requiring data migration. The broader aim is to facilitate portability of GlueSQL to any environment supporting read or read-write operations. This extends to APIs like GitHub, or messengers like Discord or Slack.

GlueSQL supports both structured and unstructured data and is written in Rust for compatibility with various environments. While portability is its core value, the emphasis is on creating an intuitive, comfortable development environment for easy custom storage implementation.

Ultimately, GlueSQL aims to significantly reduce the cost, time, and complexity of developing new databases. By leveraging GlueSQL for the parser, planner, and execution layer, developers can focus on creating specific storage implementations, leading to a more convenient query interface like SQL for many environments.

The Problem: Why Reinvent the Database?

Despite the numerous database implementations that currently exist, the emergence of new databases continues. The primary reason behind this trend is our need for databases for a broad spectrum of distinct purposes. For instance, new databases are surfacing that are specifically optimized for Large Language Models (LLMs) like ChatGPT. The range is wide and diverse, encompassing embedded databases, OLAP for data analysis, OLTP databases optimized for online transactions, databases specialized for time-series data processing, and many more.

With such varied requirements, we find ourselves in constant need of fresh databases. However, constructing a database from scratch is a monumental task. It necessitates defining a query interface for handling the database and implementing a corresponding parser. Moreover, a separate execution layer for running operations must be built. Also, the planning layer, which is responsible for devising execution strategies, is a vital aspect of this process. Let's not forget about the critical storage layer that physically reads and stores the data. In a nutshell, there's a daunting amount of work involved in developing a new database.

Given these circumstances, it's understandable why numerous emerging databases resort to high pricing structures—they need immediate revenue to offset continuous development costs.

But the story doesn't end here. Query interfaces like SQL are indeed useful for serious tasks, but they also provide excellent utility for handling simple log files such as CSV, JSONL, Parquet, and even for utilizing REST APIs for various applications. The issue arises when a complex query interface needs to be provided even for these lighter storage requirements—it necessitates a development process almost identical to building a sophisticated database. Implementing an entire parser and execution layer just to add SQL support to an existing service can seem like an excessive burden.

Whether it's a simple storage environment or a serious task, the key lies in the storage layer, which involves the actual reading and storing of data. So, what if developers focused on implementing these storage mechanisms while the remaining parts could be handled using existing libraries? This is the role that GlueSQL aspires to play.

The Vision of GlueSQL

The GlueSQL project aims to offer a unified query interface for various environments. The goal is to allow anyone to port and use SQL and GlueSQL's proprietary query builder, the AST Builder, in any desired environment. This could range from key-value databases, serious NoSQL databases, log files, and even REST API services. Essentially, if a service supports reading or read-writing data, regardless of the data type, it can readily support a complex query interface via GlueSQL.

Presently, the GlueSQL project itself directly supports a few storage types as reference storages. These include in-memory storage for non-persistent data handling, sled storage, which is a key-value database written in Rust, JSON storage for handling JSON and JSONL files, and a storage that ports SQL to the web browser's IndexedDB. While the GlueSQL Team is primarily developing these, the aim is to allow anyone to create such custom storages for a wide array of purposes, thus enabling them to assemble the database of their choosing.

Imagine using GlueSQL's SQL and AST Builder everywhere, with the simple method of swapping out storages to operate in diverse settings. It could significantly reduce software development costs. Developers wouldn't need to learn the different usage methods for each database. Instead, they could focus solely on implementing business logic using the same interface.

Our vision is to reduce database development costs by 10 times, or even more than 20 times. We aim to gather diverse database creators under the GlueSQL banner, making it the go-to solution for cost-effective database development.

Benefits to Database Users: Unifying Query Interfaces, Streamlining Software Development, and Reducing Costs

From the perspective of the users who engage with databases, there has always been the burden of learning different interfaces to interact with each database. The approach required to work with Redis is different from that necessary for MongoDB. Likewise, handling SQL databases necessitates using SQL. Although SQL databases generally use a common SQL, the SQL they support can considerably vary when examined in detail.

Naturally, there are legitimate reasons for such differences. Each database focuses on different areas, and to cater to specialized functionalities, they incorporate dedicated interface mechanisms. However, not all application development needs to utilize these database-specific core special functionalities.

Let's look at a couple of examples:

Suppose you're developing a back-end application that uses MySQL as the database and Redis for caching. Due to the vast differences in handling SQL databases and Redis, you would have to develop using different methods when storing data.

Here's another scenario: +

GlueSQL - Revolutionizing Databases by Unifying Query Interfaces

· 14 min read
Taehoon Moon

Introduction

GlueSQL is a versatile database project designed for exceptional portability across a broad range of environments, from embedded systems and servers to web and mobile platforms. The core goal is to support diverse storage environments and manage various data types with a standard SQL approach.

Imagine handling files like CSV, JSONL, and Parquet, or transforming key-value or NoSQL databases such as RocksDB, Redis, and MongoDB into SQL-supporting databases—all feasible with GlueSQL. It can also operate with storages supported in web browsers.

GlueSQL's essential feature is providing a management layer for these diverse storage scenarios without requiring data migration. The broader aim is to facilitate portability of GlueSQL to any environment supporting read or read-write operations. This extends to APIs like GitHub, or messengers like Discord or Slack.

GlueSQL supports both structured and unstructured data and is written in Rust for compatibility with various environments. While portability is its core value, the emphasis is on creating an intuitive, comfortable development environment for easy custom storage implementation.

Ultimately, GlueSQL aims to significantly reduce the cost, time, and complexity of developing new databases. By leveraging GlueSQL for the parser, planner, and execution layer, developers can focus on creating specific storage implementations, leading to a more convenient query interface like SQL for many environments.

The Problem: Why Reinvent the Database?

Despite the numerous database implementations that currently exist, the emergence of new databases continues. The primary reason behind this trend is our need for databases for a broad spectrum of distinct purposes. For instance, new databases are surfacing that are specifically optimized for Large Language Models (LLMs) like ChatGPT. The range is wide and diverse, encompassing embedded databases, OLAP for data analysis, OLTP databases optimized for online transactions, databases specialized for time-series data processing, and many more.

With such varied requirements, we find ourselves in constant need of fresh databases. However, constructing a database from scratch is a monumental task. It necessitates defining a query interface for handling the database and implementing a corresponding parser. Moreover, a separate execution layer for running operations must be built. Also, the planning layer, which is responsible for devising execution strategies, is a vital aspect of this process. Let's not forget about the critical storage layer that physically reads and stores the data. In a nutshell, there's a daunting amount of work involved in developing a new database.

Given these circumstances, it's understandable why numerous emerging databases resort to high pricing structures—they need immediate revenue to offset continuous development costs.

But the story doesn't end here. Query interfaces like SQL are indeed useful for serious tasks, but they also provide excellent utility for handling simple log files such as CSV, JSONL, Parquet, and even for utilizing REST APIs for various applications. The issue arises when a complex query interface needs to be provided even for these lighter storage requirements—it necessitates a development process almost identical to building a sophisticated database. Implementing an entire parser and execution layer just to add SQL support to an existing service can seem like an excessive burden.

Whether it's a simple storage environment or a serious task, the key lies in the storage layer, which involves the actual reading and storing of data. So, what if developers focused on implementing these storage mechanisms while the remaining parts could be handled using existing libraries? This is the role that GlueSQL aspires to play.

The Vision of GlueSQL

The GlueSQL project aims to offer a unified query interface for various environments. The goal is to allow anyone to port and use SQL and GlueSQL's proprietary query builder, the AST Builder, in any desired environment. This could range from key-value databases, serious NoSQL databases, log files, and even REST API services. Essentially, if a service supports reading or read-writing data, regardless of the data type, it can readily support a complex query interface via GlueSQL.

Presently, the GlueSQL project itself directly supports a few storage types as reference storages. These include in-memory storage for non-persistent data handling, sled storage, which is a key-value database written in Rust, JSON storage for handling JSON and JSONL files, and a storage that ports SQL to the web browser's IndexedDB. While the GlueSQL Team is primarily developing these, the aim is to allow anyone to create such custom storages for a wide array of purposes, thus enabling them to assemble the database of their choosing.

Imagine using GlueSQL's SQL and AST Builder everywhere, with the simple method of swapping out storages to operate in diverse settings. It could significantly reduce software development costs. Developers wouldn't need to learn the different usage methods for each database. Instead, they could focus solely on implementing business logic using the same interface.

Our vision is to reduce database development costs by 10 times, or even more than 20 times. We aim to gather diverse database creators under the GlueSQL banner, making it the go-to solution for cost-effective database development.

Benefits to Database Users: Unifying Query Interfaces, Streamlining Software Development, and Reducing Costs

From the perspective of the users who engage with databases, there has always been the burden of learning different interfaces to interact with each database. The approach required to work with Redis is different from that necessary for MongoDB. Likewise, handling SQL databases necessitates using SQL. Although SQL databases generally use a common SQL, the SQL they support can considerably vary when examined in detail.

Naturally, there are legitimate reasons for such differences. Each database focuses on different areas, and to cater to specialized functionalities, they incorporate dedicated interface mechanisms. However, not all application development needs to utilize these database-specific core special functionalities.

Let's look at a couple of examples:

Suppose you're developing a back-end application that uses MySQL as the database and Redis for caching. Due to the vast differences in handling SQL databases and Redis, you would have to develop using different methods when storing data.

Here's another scenario: Imagine you're implementing a data migration pipeline between various databases and log files. Let's say you're transferring Parquet to Redis or MongoDB. In this case, you would need to convert data using different methods for each, all of which would be a cumbersome process.

In both of the above examples, GlueSQL can directly address and solve the issues. It offers the convenience of a uniform query interface to deal with these matters. In certain scenarios, even the construction of a data pipeline can potentially be solved with a single SQL query, thanks to GlueSQL.

Benefits to Database Developers: Drastically Lowering Development Costs and Simplifying the Creation of Purpose-Built Databases

If you want to support SQL in the desired environment, using GlueSQL essentially requires you to implement an interface for Storage. There's no need to support all functionalities from the beginning. You can start lightly, choosing and implementing storage features suitable for the environment you want to create. To facilitate this, GlueSQL also provides a library in the form of a test suite to easily validate the storage you've implemented.

Lowering development costs in this way will enable a broader range of developers to support the GlueSQL query interface. As more developers join, a significant synergy can be generated. Designing a query interface from scratch involves a great deal of work, including planning and supporting the interface for different target programming languages.

However, despite all this hard work, it is not easy to attract database users accustomed to different methods.

Consider that the SQL and AST Builder provided by GlueSQL are already securing numerous users. This eliminates the need for efforts to promote a newly planned query interface. Over the years, many new databases have emphasized compatibility with PostgreSQL or MySQL for similar reasons. As GlueSQL places a strong emphasis on portability in its query interface planning, it allows for more flexible configuration according to the desired situation. Through the AST Builder, it also eliminates the cost of porting to different languages.

For many database developers, using GlueSQL can be an optimal choice, as it can save costs and quickly secure users.

Let me mention one more thing: what's convenient for humans... could be applied to AI as well. Rather than making AI write automation code using different databases, providing a common query interface can be much more efficient.

The Future with GlueSQL

GlueSQL has been and will continue to improve and develop new features to enable portability in various environments. Thanks to the schemaless data support added last year, it is now possible to handle both structured data with schema and unstructured data like JSON simultaneously. This has significantly increased the range of storage environments that can be supported.

One of the key features added last year was the AST Builder. This feature allowed us to escape the confines of SQL and provide an interface for comfortably handling data in the programming languages used for development.

Of course, improving existing features is extremely important, and there are many new features to be added. As a major development plan this year, we aim to develop features to effectively attach GlueSQL to NoSQL databases with their own planners and execution layers. The GlueSQL query planner, currently at a basic level, will see significant changes this year. With the expansion of this planner, not only NoSQL databases but also other SQL databases could be supported without sacrificing performance using GlueSQL.

The synergy that arises from the combination of different databases is a significant bonus in this process.

The Journey of the GlueSQL Team

The GlueSQL project was first conceived in the fall of 2019, and since then we have been developing it continuously. Personally, I have created various products in a variety of environments, including game development, backend server, and frontend development over the past decade. The experience gained through this process was a major motivation to start the GlueSQL project.

To put it grandly, the inconveniences felt while using different databases in various environments were a major motivation, wouldn't you say?

The start was actually a bit simple. Around 2019, I was mainly doing web front-end development. However, the lack of a structured database for state management and internal data processing made it very uncomfortable, especially since I couldn't use SQL databases and the like. So I started to lightly create an SQL database that could run on a web browser. Also, I wanted to use Rust, but after failing to introduce it at the company I was working for at the time, I decided to use it in my own project.

But as I started developing, my dreams grew significantly. Beyond a SQL database that simply operates on a web browser, I started envisioning a database that fits the name "Glue", one that can easily be ported to various environments, and I continue that journey to this day.

Whether I took the database project too lightly, or because the features I wanted kept increasing, the content to be developed kept expanding. As a result, I ended up investing full time in the GlueSQL project development for over three years. For a year in between, I even juggled full-time software engineering work alongside GlueSQL development. Currently, I'm back to developing the GlueSQL project full time, alongside various part-time contributors.

Now, we're getting very close to the starting point of the picture I wanted to create through GlueSQL, and thankfully, with contributors joining me, I am not alone.

The Sustainability and Business Aspect of GlueSQL

I believe that what we create through GlueSQL will make a great contribution to the world and make many software engineers happy. This gives me immense strength to continue developing even in difficult situations. However, we cannot accomplish everything with pure passion alone. As much as the GlueSQL project can make a significant contribution, I also see it as holding great business value.

The business strategy of GlueSQL may be somewhat different from other databases. We distribute the project itself as open source under the Apache-2.0 license, so that anyone can use it fully, and we do not consider pricing methods such as restricting features to the storages we support. In fact, if there is any player who can do it better, there's no way to prevent them from taking the GlueSQL project and making it their own.

But we believe that GlueSQL has great potential in this regard. Anyone can participate and they are free to distribute their own storage in the way they want, whether it's open source, private, or commercial. This eliminates the need to create something to replace the GlueSQL project. We aim to prevent the need to recreate the wheel that we provide using GlueSQL.

Moreover, our GlueSQL team seeks to continually expand our group of developers and companies working with us. During this development process, while they can certainly implement everything on their own, there is also no reason not to collaborate with our GlueSQL Team, especially for databases like NoSQL that have their own planners and execution layers. If you have a REST API and want to enhance convenience through SQL support, you can do it yourself or you can collaborate with us.

In addition, for some storages, we can also participate as players in the same position as other custom storage developers. We plan to expand the GlueSQL ecosystem in various ways, such as technical support and storage development.

We are finally ready to provide GlueSQL to users at the production level. We are accelerating the development of GlueSQL. If you are a company interested in storage development like SQL support, or if you resonate with our vision and want to join us, please contact us at taehoon@gluesql.com.

Conclusion

The continued emergence of new databases is driven by the demand for diverse and specialized databases, such as those optimized for Large Language Models (LLMs) and databases catering to unique requirements, like embedded databases, OLAP, OLTP, and time-series data processing. However, developing a new database from scratch is a significant undertaking, requiring extensive work, which often results in high costs.

GlueSQL presents a solution to this challenge by providing a unified query interface that can be ported across various environments, from key-value databases, NoSQL databases, log files, to REST APIs. It allows anyone to create custom storages, reducing the need for developers to build entirely new databases and to learn different usage methods for each database. Instead, they can focus on implementing their business logic using the same interface.

From a user perspective, GlueSQL offers the convenience of a unified query interface, easing the burden of learning different interfaces for each database. This simplification of interface use can also extend to AI, potentially enhancing the efficiency of AI automation.

GlueSQL's development plan includes significant enhancements to its query planner and aims to enable effective attachment of GlueSQL to NoSQL databases. The synergy of combining different databases is a valuable bonus in this process.

Since its inception in the fall of 2019, the GlueSQL team has continuously developed the project, driven by the desire to mitigate the inconveniences encountered while using different databases in various environments. The journey has been a rewarding one, with the GlueSQL project now at a point where it closely resembles the envisioned product.

GlueSQL, distributed under the Apache-2.0 license, is free for anyone to use and adapt. While the GlueSQL team welcomes collaboration with other developers and companies, they also see significant potential for the project as a business venture. The team is working to expand the GlueSQL ecosystem through a variety of initiatives, including technical support and storage development.

With GlueSQL now sufficiently prepared for practical applications, the team invites companies interested in storage development or those who share their vision to join them in their journey of revolutionizing database development.

- - + + \ No newline at end of file diff --git a/docs/dev/blog/tags/automation/index.html b/docs/dev/blog/tags/automation/index.html index 23c4af07..32160c1f 100644 --- a/docs/dev/blog/tags/automation/index.html +++ b/docs/dev/blog/tags/automation/index.html @@ -1,17 +1,17 @@ - + - + One post tagged with "Automation" | GlueSQL - - - + + +
-

One post tagged with "Automation"

View All Tags

· 10 min read
Taehoon Moon

Introduction: GlueSQL and Test-Driven Documentation

Recently, the GlueSQL project reached a significant milestone with the release of version 0.14. This new version brings a host of fresh features to the table, yet one of the most notable changes is in the realm of documentation. For the first time, we're proud to announce the launch of our official documentation website. Interested readers can explore the full range of user manuals at https://gluesql.org/docs.

Prior to this update, the only way to navigate GlueSQL was by manually inspecting the test code within the test suite. With the recent release, however, a comprehensive user manual has been made public to facilitate a more user-friendly experience. We hope that this new addition will prove beneficial to a broad spectrum of users.

The task of compiling an entire database manual in one go was daunting due to the sheer volume of content required. Surprisingly, this process turned out to be smoother than initially anticipated, largely due to the invaluable aid of ChatGPT, which was instrumental in automating much of the document creation. Specifically, around 80% of the SQL Syntax section was generated using this tool.

This remarkable feat was only possible due to the solid foundation of test codes previously established in GlueSQL. In this article, we'll share how we managed to leverage ChatGPT in such a unique way. Based on our recent experience of crafting documents grounded in testing, we've begun to consider the possibility of entirely automating document creation, save for the initial stages.

Along with sharing our journey so far, we will also reveal our plans for future test-based automation of documentation within GlueSQL.

Test Codes and Documentation

The GlueSQL project has placed a significant emphasis on writing test codes. This might be a given for a database project; however, the thoroughness of our approach is evident from our line coverage of nearly 99% for core codes. While we devoted considerable effort to creating these test codes, our primary focus has always been on a different aspect: ensuring that anyone can quickly grasp the content of the tests and easily add new ones.

The intent here is to empower newcomers to GlueSQL to understand the functionality of the software solely by examining integration tests, even in the absence of a user manual.

The integration tests for GlueSQL can be found in the test-suite workspace. For example, here's an excerpt of the test code for the INSERT statement:

test_case!(insert, async move {
run!(
"
CREATE TABLE Test (
id INTEGER DEFAULT 1,
num INTEGER NULL,
name TEXT NOT NULL,
);"
);

test! {
name: "basic insert - single item",
sql: "INSERT INTO Test (id, num, name) VALUES (1, 2, 'Hi boo');",
expected: Ok(Payload::Insert(1))
};


test! {
sql: "INSERT INTO Test VALUES(17, 30, 'Sullivan');",
expected: Ok(Payload::Insert(1))
};

test! {
sql: "INSERT INTO Test (num, name) VALUES (28, 'Wazowski');",
expected: Ok(Payload::Insert(1))
};

test! {
sql: "SELECT * FROM Test;",
expected: Ok(select!(
id | num | name;
I64 | I64 | Str;
1 2 "Hi boo".to_owned();
3 9 "Kitty!".to_owned();
2 7 "Monsters".to_owned();
17 30 "Sullivan".to_owned();
1 28 "Wazowski".to_owned()
))
};

// ...
});

Despite being written in Rust, these test cases are designed to be comprehensible, even to those unfamiliar with the language. Each test is a complete scenario from start to finish, and the results of each operation are readily observable.

Given that identifying results from SELECT operations in the form of Rust enums and structs can be challenging, we actively utilized macros such as select! and select_with_null!. We've composed the test cases to demonstrate that the INSERT statement can handle a wide range of cases, including specifying all columns, omitting some, or omitting all.

test! {
sql: "INSERT INTO Test (id, num) VALUES (1, 10);",
expected: Err(InsertError::LackOfRequiredColumn("name".to_owned()).into())
};

The tests also include scenarios for expected faulty inputs, indicating the error returns in these situations.

By organizing the tests in this manner, we aim to make it easy for anyone to read and write tests. Our goal was for these tests to serve as "documentation" for GlueSQL contributors. At the time we were writing these tests, we didn't anticipate that they could actually become documentation themselves. But we've come to realize that they have extraordinary potential.

Leveraging ChatGPT

When we first embarked on writing the User Manual, we were overwhelmed by the sheer volume of content we had to generate. Around the same time, ChatGPT was gaining prominence, and we thought it might be worth trying out, if only to lighten our load slightly.

To our surprise, ChatGPT exceeded our expectations. If the test codes were well written, it was capable of automatically crafting an exceptional document based on them, capturing all essential details.

After several trials and errors, we settled on the following prompt for document generation. While it's still a challenge to use the same prompt for all documentation, we made minor modifications to suit different situations:

I'm creating an SQL database documentation website, and I'd like you to help me with one of the pages that introduces the SQL syntax for GlueSQL.

1. Please provide the response content in the "markdown" format, so I can copy and paste it directly. Keep this constraint in mind while writing.
2. Regardless of the language I use, I need the content written in English.
3. I will provide some test case code written in the Rust language, which contains SQL examples. Please write the documentation based on these examples, but feel free to change the table names, column names, and data types as needed. Don't include any Rust related content or text in the response. all the response code example should be in plain SQL.
4. GlueSQL does not have the VARCHAR type. If you want to use that, please use TEXT instead. You don't need to mention this in the response.
5. Wrap the entire response text using <pre> and </pre> tags so I can copy all the content easily.

Now, I'd like you to write the following request:
SQL Statement - "INSERT"

Here's an example test code you can refer to:

test_case!(insert, async move {
run!(...

Generally, we used the template above, and copied and pasted the test code from our existing test-suite. We leveraged this method to harness our many tests to assist in the creation of the user manual. In the next section, we'll showcase a sample of the documentation generated in this manner. It's quite impressive.

Success Case: Automated User Manual of GlueSQL

Thanks to ChatGPT, the resulting INSERT document page can be viewed at the following link. It's important to note that we used ChatGPT 4 for this task. Version 3.5 wasn't quite up to the task, and using version 4 was the minimum requirement.

https://gluesql.org/docs/dev/sql-syntax/statements/data-manipulation/insert

INSERT Statement

The results were quite impressive. ChatGPT neatly categorized the test cases, explained the syntax, outlined constraints, and provided appropriate examples. It didn't stop there; it also skillfully recognized error test cases and incorporated them into the documentation, as shown below.

INSERT Statement

Isn't it amazing?

Future Plans: Fully Automating Documentation Generation

While the current documentation is far from perfect and there are many aspects that can be improved, we see great potential in this approach. We believe it's entirely possible to automate the process of writing this kind of document, and writing in general.

In the past, documents like user manuals required a great deal of effort to maintain once they were written. If a document contained real code examples, verifying that the code still worked was often a tedious task. With the ability to automatically generate documentation as we have done here, these issues are no longer problematic.

Previously, you would have to write tests and then also document them separately. If you had to support multiple languages, that would be an additional task. With a tool like ChatGPT, you can automate all of this. All a developer has to do is write the tests. This alone can be sufficient. You can generate documents automatically based on the tests. Eventually, we can even support automatically translating these documents into multiple languages.

The GlueSQL project repository is currently hosted on GitHub and makes good use of various GitHub Actions. We envision a GitHub Action that automatically regenerates a document corresponding to a test when a user modifies the test and raises a Pull Request. Another GitHub Action could automatically translate updated documents into supported languages and create new Pull Requests. The possibilities are truly endless.

Not only will this help with document generation, but it will also provide clear guidelines for writing better test code. If we can automatically generate documents based on written tests, the quality of those documents can serve as an indicator of the quality of the tests themselves. This means that a document automation tool can play the role of a good reviewer for tests. It can greatly reduce the time and effort required for painstakingly reviewing the quality of each test. Developers can also write tests without pressure, evaluate their test code by looking at the generated document, and improve it.

Furthermore, multi-language support becomes a breeze. In my personal experience as a software engineer over the past decade, developing various products such as games, web services, and applications, I often needed to support multiple languages. Each time, there was no definite solution. The optimal approach varied depending on the situation, and there were many things to consider when entrusting translations, such as effectively communicating the context of the target service to the translator. Moreover, regularly updating content and having it retranslated into various languages was a very tedious process. While I tried to automate as much as possible by creating various tools, I was never fully satisfied. I believe ChatGPT can completely solve these issues. If there is a need to provide project-specific context, all you need to do is prepare a prompt in advance. Instead of having to rely on and wait for professional translators, we can now entrust this task to ChatGPT, and we only need a few people to review the translated content.

We are nearing a world where documentation is no longer a burden for developers.

Conclusion: The Value of Test-Driven Documentation

The use of ChatGPT to generate documentation has proven a significant step forward in the GlueSQL user manual creation process. Through test-driven documentation, we've managed to automate a substantial part of the manual creation process, saving time and effort, and increasing accuracy.

Moreover, this process has unveiled a new potential for documentation: the possibility of fully automating document generation. We've seen that quality tests can become quality documentation with the help of AI, leading to more efficient workflows and possibly better test code as a result.

The journey doesn't stop here. We envision leveraging this capability further to auto-translate our documents into multiple languages, making our product more accessible to a global audience.

As we progress, we hope that our experience can inspire other developers to explore and embrace the benefits of AI-generated, test-driven documentation. It's not just about saving time—it's about improving the way we work, communicate, and share knowledge.

- - +

One post tagged with "Automation"

View All Tags

· 10 min read
Taehoon Moon

Introduction: GlueSQL and Test-Driven Documentation

Recently, the GlueSQL project reached a significant milestone with the release of version 0.14. This new version brings a host of fresh features to the table, yet one of the most notable changes is in the realm of documentation. For the first time, we're proud to announce the launch of our official documentation website. Interested readers can explore the full range of user manuals at https://gluesql.org/docs.

Prior to this update, the only way to navigate GlueSQL was by manually inspecting the test code within the test suite. With the recent release, however, a comprehensive user manual has been made public to facilitate a more user-friendly experience. We hope that this new addition will prove beneficial to a broad spectrum of users.

The task of compiling an entire database manual in one go was daunting due to the sheer volume of content required. Surprisingly, this process turned out to be smoother than initially anticipated, largely due to the invaluable aid of ChatGPT, which was instrumental in automating much of the document creation. Specifically, around 80% of the SQL Syntax section was generated using this tool.

This remarkable feat was only possible due to the solid foundation of test codes previously established in GlueSQL. In this article, we'll share how we managed to leverage ChatGPT in such a unique way. Based on our recent experience of crafting documents grounded in testing, we've begun to consider the possibility of entirely automating document creation, save for the initial stages.

Along with sharing our journey so far, we will also reveal our plans for future test-based automation of documentation within GlueSQL.

Test Codes and Documentation

The GlueSQL project has placed a significant emphasis on writing test codes. This might be a given for a database project; however, the thoroughness of our approach is evident from our line coverage of nearly 99% for core codes. While we devoted considerable effort to creating these test codes, our primary focus has always been on a different aspect: ensuring that anyone can quickly grasp the content of the tests and easily add new ones.

The intent here is to empower newcomers to GlueSQL to understand the functionality of the software solely by examining integration tests, even in the absence of a user manual.

The integration tests for GlueSQL can be found in the test-suite workspace. For example, here's an excerpt of the test code for the INSERT statement:

test_case!(insert, async move {
run!(
"
CREATE TABLE Test (
id INTEGER DEFAULT 1,
num INTEGER NULL,
name TEXT NOT NULL,
);"
);

test! {
name: "basic insert - single item",
sql: "INSERT INTO Test (id, num, name) VALUES (1, 2, 'Hi boo');",
expected: Ok(Payload::Insert(1))
};


test! {
sql: "INSERT INTO Test VALUES(17, 30, 'Sullivan');",
expected: Ok(Payload::Insert(1))
};

test! {
sql: "INSERT INTO Test (num, name) VALUES (28, 'Wazowski');",
expected: Ok(Payload::Insert(1))
};

test! {
sql: "SELECT * FROM Test;",
expected: Ok(select!(
id | num | name;
I64 | I64 | Str;
1 2 "Hi boo".to_owned();
3 9 "Kitty!".to_owned();
2 7 "Monsters".to_owned();
17 30 "Sullivan".to_owned();
1 28 "Wazowski".to_owned()
))
};

// ...
});

Despite being written in Rust, these test cases are designed to be comprehensible, even to those unfamiliar with the language. Each test is a complete scenario from start to finish, and the results of each operation are readily observable.

Given that identifying results from SELECT operations in the form of Rust enums and structs can be challenging, we actively utilized macros such as select! and select_with_null!. We've composed the test cases to demonstrate that the INSERT statement can handle a wide range of cases, including specifying all columns, omitting some, or omitting all.

test! {
sql: "INSERT INTO Test (id, num) VALUES (1, 10);",
expected: Err(InsertError::LackOfRequiredColumn("name".to_owned()).into())
};

The tests also include scenarios for expected faulty inputs, indicating the error returns in these situations.

By organizing the tests in this manner, we aim to make it easy for anyone to read and write tests. Our goal was for these tests to serve as "documentation" for GlueSQL contributors. At the time we were writing these tests, we didn't anticipate that they could actually become documentation themselves. But we've come to realize that they have extraordinary potential.

Leveraging ChatGPT

When we first embarked on writing the User Manual, we were overwhelmed by the sheer volume of content we had to generate. Around the same time, ChatGPT was gaining prominence, and we thought it might be worth trying out, if only to lighten our load slightly.

To our surprise, ChatGPT exceeded our expectations. If the test codes were well written, it was capable of automatically crafting an exceptional document based on them, capturing all essential details.

After several trials and errors, we settled on the following prompt for document generation. While it's still a challenge to use the same prompt for all documentation, we made minor modifications to suit different situations:

I'm creating an SQL database documentation website, and I'd like you to help me with one of the pages that introduces the SQL syntax for GlueSQL.

1. Please provide the response content in the "markdown" format, so I can copy and paste it directly. Keep this constraint in mind while writing.
2. Regardless of the language I use, I need the content written in English.
3. I will provide some test case code written in the Rust language, which contains SQL examples. Please write the documentation based on these examples, but feel free to change the table names, column names, and data types as needed. Don't include any Rust related content or text in the response. all the response code example should be in plain SQL.
4. GlueSQL does not have the VARCHAR type. If you want to use that, please use TEXT instead. You don't need to mention this in the response.
5. Wrap the entire response text using <pre> and </pre> tags so I can copy all the content easily.

Now, I'd like you to write the following request:
SQL Statement - "INSERT"

Here's an example test code you can refer to:

test_case!(insert, async move {
run!(...

Generally, we used the template above, and copied and pasted the test code from our existing test-suite. We leveraged this method to harness our many tests to assist in the creation of the user manual. In the next section, we'll showcase a sample of the documentation generated in this manner. It's quite impressive.

Success Case: Automated User Manual of GlueSQL

Thanks to ChatGPT, the resulting INSERT document page can be viewed at the following link. It's important to note that we used ChatGPT 4 for this task. Version 3.5 wasn't quite up to the task, and using version 4 was the minimum requirement.

https://gluesql.org/docs/dev/sql-syntax/statements/data-manipulation/insert

INSERT Statement

The results were quite impressive. ChatGPT neatly categorized the test cases, explained the syntax, outlined constraints, and provided appropriate examples. It didn't stop there; it also skillfully recognized error test cases and incorporated them into the documentation, as shown below.

INSERT Statement

Isn't it amazing?

Future Plans: Fully Automating Documentation Generation

While the current documentation is far from perfect and there are many aspects that can be improved, we see great potential in this approach. We believe it's entirely possible to automate the process of writing this kind of document, and writing in general.

In the past, documents like user manuals required a great deal of effort to maintain once they were written. If a document contained real code examples, verifying that the code still worked was often a tedious task. With the ability to automatically generate documentation as we have done here, these issues are no longer problematic.

Previously, you would have to write tests and then also document them separately. If you had to support multiple languages, that would be an additional task. With a tool like ChatGPT, you can automate all of this. All a developer has to do is write the tests. This alone can be sufficient. You can generate documents automatically based on the tests. Eventually, we can even support automatically translating these documents into multiple languages.

The GlueSQL project repository is currently hosted on GitHub and makes good use of various GitHub Actions. We envision a GitHub Action that automatically regenerates a document corresponding to a test when a user modifies the test and raises a Pull Request. Another GitHub Action could automatically translate updated documents into supported languages and create new Pull Requests. The possibilities are truly endless.

Not only will this help with document generation, but it will also provide clear guidelines for writing better test code. If we can automatically generate documents based on written tests, the quality of those documents can serve as an indicator of the quality of the tests themselves. This means that a document automation tool can play the role of a good reviewer for tests. It can greatly reduce the time and effort required for painstakingly reviewing the quality of each test. Developers can also write tests without pressure, evaluate their test code by looking at the generated document, and improve it.

Furthermore, multi-language support becomes a breeze. In my personal experience as a software engineer over the past decade, developing various products such as games, web services, and applications, I often needed to support multiple languages. Each time, there was no definite solution. The optimal approach varied depending on the situation, and there were many things to consider when entrusting translations, such as effectively communicating the context of the target service to the translator. Moreover, regularly updating content and having it retranslated into various languages was a very tedious process. While I tried to automate as much as possible by creating various tools, I was never fully satisfied. I believe ChatGPT can completely solve these issues. If there is a need to provide project-specific context, all you need to do is prepare a prompt in advance. Instead of having to rely on and wait for professional translators, we can now entrust this task to ChatGPT, and we only need a few people to review the translated content.

We are nearing a world where documentation is no longer a burden for developers.

Conclusion: The Value of Test-Driven Documentation

The use of ChatGPT to generate documentation has proven a significant step forward in the GlueSQL user manual creation process. Through test-driven documentation, we've managed to automate a substantial part of the manual creation process, saving time and effort, and increasing accuracy.

Moreover, this process has unveiled a new potential for documentation: the possibility of fully automating document generation. We've seen that quality tests can become quality documentation with the help of AI, leading to more efficient workflows and possibly better test code as a result.

The journey doesn't stop here. We envision leveraging this capability further to auto-translate our documents into multiple languages, making our product more accessible to a global audience.

As we progress, we hope that our experience can inspire other developers to explore and embrace the benefits of AI-generated, test-driven documentation. It's not just about saving time—it's about improving the way we work, communicate, and share knowledge.

+ + \ No newline at end of file diff --git a/docs/dev/blog/tags/chat-gpt/index.html b/docs/dev/blog/tags/chat-gpt/index.html index 01a3935e..4e2af6a5 100644 --- a/docs/dev/blog/tags/chat-gpt/index.html +++ b/docs/dev/blog/tags/chat-gpt/index.html @@ -1,17 +1,17 @@ - + - + One post tagged with "ChatGPT" | GlueSQL - - - + + +
-

One post tagged with "ChatGPT"

View All Tags

· 10 min read
Taehoon Moon

Introduction: GlueSQL and Test-Driven Documentation

Recently, the GlueSQL project reached a significant milestone with the release of version 0.14. This new version brings a host of fresh features to the table, yet one of the most notable changes is in the realm of documentation. For the first time, we're proud to announce the launch of our official documentation website. Interested readers can explore the full range of user manuals at https://gluesql.org/docs.

Prior to this update, the only way to navigate GlueSQL was by manually inspecting the test code within the test suite. With the recent release, however, a comprehensive user manual has been made public to facilitate a more user-friendly experience. We hope that this new addition will prove beneficial to a broad spectrum of users.

The task of compiling an entire database manual in one go was daunting due to the sheer volume of content required. Surprisingly, this process turned out to be smoother than initially anticipated, largely due to the invaluable aid of ChatGPT, which was instrumental in automating much of the document creation. Specifically, around 80% of the SQL Syntax section was generated using this tool.

This remarkable feat was only possible due to the solid foundation of test codes previously established in GlueSQL. In this article, we'll share how we managed to leverage ChatGPT in such a unique way. Based on our recent experience of crafting documents grounded in testing, we've begun to consider the possibility of entirely automating document creation, save for the initial stages.

Along with sharing our journey so far, we will also reveal our plans for future test-based automation of documentation within GlueSQL.

Test Codes and Documentation

The GlueSQL project has placed a significant emphasis on writing test codes. This might be a given for a database project; however, the thoroughness of our approach is evident from our line coverage of nearly 99% for core codes. While we devoted considerable effort to creating these test codes, our primary focus has always been on a different aspect: ensuring that anyone can quickly grasp the content of the tests and easily add new ones.

The intent here is to empower newcomers to GlueSQL to understand the functionality of the software solely by examining integration tests, even in the absence of a user manual.

The integration tests for GlueSQL can be found in the test-suite workspace. For example, here's an excerpt of the test code for the INSERT statement:

test_case!(insert, async move {
run!(
"
CREATE TABLE Test (
id INTEGER DEFAULT 1,
num INTEGER NULL,
name TEXT NOT NULL,
);"
);

test! {
name: "basic insert - single item",
sql: "INSERT INTO Test (id, num, name) VALUES (1, 2, 'Hi boo');",
expected: Ok(Payload::Insert(1))
};


test! {
sql: "INSERT INTO Test VALUES(17, 30, 'Sullivan');",
expected: Ok(Payload::Insert(1))
};

test! {
sql: "INSERT INTO Test (num, name) VALUES (28, 'Wazowski');",
expected: Ok(Payload::Insert(1))
};

test! {
sql: "SELECT * FROM Test;",
expected: Ok(select!(
id | num | name;
I64 | I64 | Str;
1 2 "Hi boo".to_owned();
3 9 "Kitty!".to_owned();
2 7 "Monsters".to_owned();
17 30 "Sullivan".to_owned();
1 28 "Wazowski".to_owned()
))
};

// ...
});

Despite being written in Rust, these test cases are designed to be comprehensible, even to those unfamiliar with the language. Each test is a complete scenario from start to finish, and the results of each operation are readily observable.

Given that identifying results from SELECT operations in the form of Rust enums and structs can be challenging, we actively utilized macros such as select! and select_with_null!. We've composed the test cases to demonstrate that the INSERT statement can handle a wide range of cases, including specifying all columns, omitting some, or omitting all.

test! {
sql: "INSERT INTO Test (id, num) VALUES (1, 10);",
expected: Err(InsertError::LackOfRequiredColumn("name".to_owned()).into())
};

The tests also include scenarios for expected faulty inputs, indicating the error returns in these situations.

By organizing the tests in this manner, we aim to make it easy for anyone to read and write tests. Our goal was for these tests to serve as "documentation" for GlueSQL contributors. At the time we were writing these tests, we didn't anticipate that they could actually become documentation themselves. But we've come to realize that they have extraordinary potential.

Leveraging ChatGPT

When we first embarked on writing the User Manual, we were overwhelmed by the sheer volume of content we had to generate. Around the same time, ChatGPT was gaining prominence, and we thought it might be worth trying out, if only to lighten our load slightly.

To our surprise, ChatGPT exceeded our expectations. If the test codes were well written, it was capable of automatically crafting an exceptional document based on them, capturing all essential details.

After several trials and errors, we settled on the following prompt for document generation. While it's still a challenge to use the same prompt for all documentation, we made minor modifications to suit different situations:

I'm creating an SQL database documentation website, and I'd like you to help me with one of the pages that introduces the SQL syntax for GlueSQL.

1. Please provide the response content in the "markdown" format, so I can copy and paste it directly. Keep this constraint in mind while writing.
2. Regardless of the language I use, I need the content written in English.
3. I will provide some test case code written in the Rust language, which contains SQL examples. Please write the documentation based on these examples, but feel free to change the table names, column names, and data types as needed. Don't include any Rust related content or text in the response. all the response code example should be in plain SQL.
4. GlueSQL does not have the VARCHAR type. If you want to use that, please use TEXT instead. You don't need to mention this in the response.
5. Wrap the entire response text using <pre> and </pre> tags so I can copy all the content easily.

Now, I'd like you to write the following request:
SQL Statement - "INSERT"

Here's an example test code you can refer to:

test_case!(insert, async move {
run!(...

Generally, we used the template above, and copied and pasted the test code from our existing test-suite. We leveraged this method to harness our many tests to assist in the creation of the user manual. In the next section, we'll showcase a sample of the documentation generated in this manner. It's quite impressive.

Success Case: Automated User Manual of GlueSQL

Thanks to ChatGPT, the resulting INSERT document page can be viewed at the following link. It's important to note that we used ChatGPT 4 for this task. Version 3.5 wasn't quite up to the task, and using version 4 was the minimum requirement.

https://gluesql.org/docs/dev/sql-syntax/statements/data-manipulation/insert

INSERT Statement

The results were quite impressive. ChatGPT neatly categorized the test cases, explained the syntax, outlined constraints, and provided appropriate examples. It didn't stop there; it also skillfully recognized error test cases and incorporated them into the documentation, as shown below.

INSERT Statement

Isn't it amazing?

Future Plans: Fully Automating Documentation Generation

While the current documentation is far from perfect and there are many aspects that can be improved, we see great potential in this approach. We believe it's entirely possible to automate the process of writing this kind of document, and writing in general.

In the past, documents like user manuals required a great deal of effort to maintain once they were written. If a document contained real code examples, verifying that the code still worked was often a tedious task. With the ability to automatically generate documentation as we have done here, these issues are no longer problematic.

Previously, you would have to write tests and then also document them separately. If you had to support multiple languages, that would be an additional task. With a tool like ChatGPT, you can automate all of this. All a developer has to do is write the tests. This alone can be sufficient. You can generate documents automatically based on the tests. Eventually, we can even support automatically translating these documents into multiple languages.

The GlueSQL project repository is currently hosted on GitHub and makes good use of various GitHub Actions. We envision a GitHub Action that automatically regenerates a document corresponding to a test when a user modifies the test and raises a Pull Request. Another GitHub Action could automatically translate updated documents into supported languages and create new Pull Requests. The possibilities are truly endless.

Not only will this help with document generation, but it will also provide clear guidelines for writing better test code. If we can automatically generate documents based on written tests, the quality of those documents can serve as an indicator of the quality of the tests themselves. This means that a document automation tool can play the role of a good reviewer for tests. It can greatly reduce the time and effort required for painstakingly reviewing the quality of each test. Developers can also write tests without pressure, evaluate their test code by looking at the generated document, and improve it.

Furthermore, multi-language support becomes a breeze. In my personal experience as a software engineer over the past decade, developing various products such as games, web services, and applications, I often needed to support multiple languages. Each time, there was no definite solution. The optimal approach varied depending on the situation, and there were many things to consider when entrusting translations, such as effectively communicating the context of the target service to the translator. Moreover, regularly updating content and having it retranslated into various languages was a very tedious process. While I tried to automate as much as possible by creating various tools, I was never fully satisfied. I believe ChatGPT can completely solve these issues. If there is a need to provide project-specific context, all you need to do is prepare a prompt in advance. Instead of having to rely on and wait for professional translators, we can now entrust this task to ChatGPT, and we only need a few people to review the translated content.

We are nearing a world where documentation is no longer a burden for developers.

Conclusion: The Value of Test-Driven Documentation

The use of ChatGPT to generate documentation has proven a significant step forward in the GlueSQL user manual creation process. Through test-driven documentation, we've managed to automate a substantial part of the manual creation process, saving time and effort, and increasing accuracy.

Moreover, this process has unveiled a new potential for documentation: the possibility of fully automating document generation. We've seen that quality tests can become quality documentation with the help of AI, leading to more efficient workflows and possibly better test code as a result.

The journey doesn't stop here. We envision leveraging this capability further to auto-translate our documents into multiple languages, making our product more accessible to a global audience.

As we progress, we hope that our experience can inspire other developers to explore and embrace the benefits of AI-generated, test-driven documentation. It's not just about saving time—it's about improving the way we work, communicate, and share knowledge.

- - +

One post tagged with "ChatGPT"

View All Tags

· 10 min read
Taehoon Moon

Introduction: GlueSQL and Test-Driven Documentation

Recently, the GlueSQL project reached a significant milestone with the release of version 0.14. This new version brings a host of fresh features to the table, yet one of the most notable changes is in the realm of documentation. For the first time, we're proud to announce the launch of our official documentation website. Interested readers can explore the full range of user manuals at https://gluesql.org/docs.

Prior to this update, the only way to navigate GlueSQL was by manually inspecting the test code within the test suite. With the recent release, however, a comprehensive user manual has been made public to facilitate a more user-friendly experience. We hope that this new addition will prove beneficial to a broad spectrum of users.

The task of compiling an entire database manual in one go was daunting due to the sheer volume of content required. Surprisingly, this process turned out to be smoother than initially anticipated, largely due to the invaluable aid of ChatGPT, which was instrumental in automating much of the document creation. Specifically, around 80% of the SQL Syntax section was generated using this tool.

This remarkable feat was only possible due to the solid foundation of test codes previously established in GlueSQL. In this article, we'll share how we managed to leverage ChatGPT in such a unique way. Based on our recent experience of crafting documents grounded in testing, we've begun to consider the possibility of entirely automating document creation, save for the initial stages.

Along with sharing our journey so far, we will also reveal our plans for future test-based automation of documentation within GlueSQL.

Test Codes and Documentation

The GlueSQL project has placed a significant emphasis on writing test codes. This might be a given for a database project; however, the thoroughness of our approach is evident from our line coverage of nearly 99% for core codes. While we devoted considerable effort to creating these test codes, our primary focus has always been on a different aspect: ensuring that anyone can quickly grasp the content of the tests and easily add new ones.

The intent here is to empower newcomers to GlueSQL to understand the functionality of the software solely by examining integration tests, even in the absence of a user manual.

The integration tests for GlueSQL can be found in the test-suite workspace. For example, here's an excerpt of the test code for the INSERT statement:

test_case!(insert, async move {
run!(
"
CREATE TABLE Test (
id INTEGER DEFAULT 1,
num INTEGER NULL,
name TEXT NOT NULL,
);"
);

test! {
name: "basic insert - single item",
sql: "INSERT INTO Test (id, num, name) VALUES (1, 2, 'Hi boo');",
expected: Ok(Payload::Insert(1))
};


test! {
sql: "INSERT INTO Test VALUES(17, 30, 'Sullivan');",
expected: Ok(Payload::Insert(1))
};

test! {
sql: "INSERT INTO Test (num, name) VALUES (28, 'Wazowski');",
expected: Ok(Payload::Insert(1))
};

test! {
sql: "SELECT * FROM Test;",
expected: Ok(select!(
id | num | name;
I64 | I64 | Str;
1 2 "Hi boo".to_owned();
3 9 "Kitty!".to_owned();
2 7 "Monsters".to_owned();
17 30 "Sullivan".to_owned();
1 28 "Wazowski".to_owned()
))
};

// ...
});

Despite being written in Rust, these test cases are designed to be comprehensible, even to those unfamiliar with the language. Each test is a complete scenario from start to finish, and the results of each operation are readily observable.

Given that identifying results from SELECT operations in the form of Rust enums and structs can be challenging, we actively utilized macros such as select! and select_with_null!. We've composed the test cases to demonstrate that the INSERT statement can handle a wide range of cases, including specifying all columns, omitting some, or omitting all.

test! {
sql: "INSERT INTO Test (id, num) VALUES (1, 10);",
expected: Err(InsertError::LackOfRequiredColumn("name".to_owned()).into())
};

The tests also include scenarios for expected faulty inputs, indicating the error returns in these situations.

By organizing the tests in this manner, we aim to make it easy for anyone to read and write tests. Our goal was for these tests to serve as "documentation" for GlueSQL contributors. At the time we were writing these tests, we didn't anticipate that they could actually become documentation themselves. But we've come to realize that they have extraordinary potential.

Leveraging ChatGPT

When we first embarked on writing the User Manual, we were overwhelmed by the sheer volume of content we had to generate. Around the same time, ChatGPT was gaining prominence, and we thought it might be worth trying out, if only to lighten our load slightly.

To our surprise, ChatGPT exceeded our expectations. If the test codes were well written, it was capable of automatically crafting an exceptional document based on them, capturing all essential details.

After several trials and errors, we settled on the following prompt for document generation. While it's still a challenge to use the same prompt for all documentation, we made minor modifications to suit different situations:

I'm creating an SQL database documentation website, and I'd like you to help me with one of the pages that introduces the SQL syntax for GlueSQL.

1. Please provide the response content in the "markdown" format, so I can copy and paste it directly. Keep this constraint in mind while writing.
2. Regardless of the language I use, I need the content written in English.
3. I will provide some test case code written in the Rust language, which contains SQL examples. Please write the documentation based on these examples, but feel free to change the table names, column names, and data types as needed. Don't include any Rust related content or text in the response. all the response code example should be in plain SQL.
4. GlueSQL does not have the VARCHAR type. If you want to use that, please use TEXT instead. You don't need to mention this in the response.
5. Wrap the entire response text using <pre> and </pre> tags so I can copy all the content easily.

Now, I'd like you to write the following request:
SQL Statement - "INSERT"

Here's an example test code you can refer to:

test_case!(insert, async move {
run!(...

Generally, we used the template above, and copied and pasted the test code from our existing test-suite. We leveraged this method to harness our many tests to assist in the creation of the user manual. In the next section, we'll showcase a sample of the documentation generated in this manner. It's quite impressive.

Success Case: Automated User Manual of GlueSQL

Thanks to ChatGPT, the resulting INSERT document page can be viewed at the following link. It's important to note that we used ChatGPT 4 for this task. Version 3.5 wasn't quite up to the task, and using version 4 was the minimum requirement.

https://gluesql.org/docs/dev/sql-syntax/statements/data-manipulation/insert

INSERT Statement

The results were quite impressive. ChatGPT neatly categorized the test cases, explained the syntax, outlined constraints, and provided appropriate examples. It didn't stop there; it also skillfully recognized error test cases and incorporated them into the documentation, as shown below.

INSERT Statement

Isn't it amazing?

Future Plans: Fully Automating Documentation Generation

While the current documentation is far from perfect and there are many aspects that can be improved, we see great potential in this approach. We believe it's entirely possible to automate the process of writing this kind of document, and writing in general.

In the past, documents like user manuals required a great deal of effort to maintain once they were written. If a document contained real code examples, verifying that the code still worked was often a tedious task. With the ability to automatically generate documentation as we have done here, these issues are no longer problematic.

Previously, you would have to write tests and then also document them separately. If you had to support multiple languages, that would be an additional task. With a tool like ChatGPT, you can automate all of this. All a developer has to do is write the tests. This alone can be sufficient. You can generate documents automatically based on the tests. Eventually, we can even support automatically translating these documents into multiple languages.

The GlueSQL project repository is currently hosted on GitHub and makes good use of various GitHub Actions. We envision a GitHub Action that automatically regenerates a document corresponding to a test when a user modifies the test and raises a Pull Request. Another GitHub Action could automatically translate updated documents into supported languages and create new Pull Requests. The possibilities are truly endless.

Not only will this help with document generation, but it will also provide clear guidelines for writing better test code. If we can automatically generate documents based on written tests, the quality of those documents can serve as an indicator of the quality of the tests themselves. This means that a document automation tool can play the role of a good reviewer for tests. It can greatly reduce the time and effort required for painstakingly reviewing the quality of each test. Developers can also write tests without pressure, evaluate their test code by looking at the generated document, and improve it.

Furthermore, multi-language support becomes a breeze. In my personal experience as a software engineer over the past decade, developing various products such as games, web services, and applications, I often needed to support multiple languages. Each time, there was no definite solution. The optimal approach varied depending on the situation, and there were many things to consider when entrusting translations, such as effectively communicating the context of the target service to the translator. Moreover, regularly updating content and having it retranslated into various languages was a very tedious process. While I tried to automate as much as possible by creating various tools, I was never fully satisfied. I believe ChatGPT can completely solve these issues. If there is a need to provide project-specific context, all you need to do is prepare a prompt in advance. Instead of having to rely on and wait for professional translators, we can now entrust this task to ChatGPT, and we only need a few people to review the translated content.

We are nearing a world where documentation is no longer a burden for developers.

Conclusion: The Value of Test-Driven Documentation

The use of ChatGPT to generate documentation has proven a significant step forward in the GlueSQL user manual creation process. Through test-driven documentation, we've managed to automate a substantial part of the manual creation process, saving time and effort, and increasing accuracy.

Moreover, this process has unveiled a new potential for documentation: the possibility of fully automating document generation. We've seen that quality tests can become quality documentation with the help of AI, leading to more efficient workflows and possibly better test code as a result.

The journey doesn't stop here. We envision leveraging this capability further to auto-translate our documents into multiple languages, making our product more accessible to a global audience.

As we progress, we hope that our experience can inspire other developers to explore and embrace the benefits of AI-generated, test-driven documentation. It's not just about saving time—it's about improving the way we work, communicate, and share knowledge.

+ + \ No newline at end of file diff --git a/docs/dev/blog/tags/database/index.html b/docs/dev/blog/tags/database/index.html index 22b3f152..5c56a86e 100644 --- a/docs/dev/blog/tags/database/index.html +++ b/docs/dev/blog/tags/database/index.html @@ -1,17 +1,17 @@ - + - + 3 posts tagged with "database" | GlueSQL - - - + + +
-

3 posts tagged with "database"

View All Tags

· 14 min read
Taehoon Moon

Introduction

GlueSQL is a versatile database project designed for exceptional portability across a broad range of environments, from embedded systems and servers to web and mobile platforms. The core goal is to support diverse storage environments and manage various data types with a standard SQL approach.

Imagine handling files like CSV, JSONL, and Parquet, or transforming key-value or NoSQL databases such as RocksDB, Redis, and MongoDB into SQL-supporting databases—all feasible with GlueSQL. It can also operate with storages supported in web browsers.

GlueSQL's essential feature is providing a management layer for these diverse storage scenarios without requiring data migration. The broader aim is to facilitate portability of GlueSQL to any environment supporting read or read-write operations. This extends to APIs like GitHub, or messengers like Discord or Slack.

GlueSQL supports both structured and unstructured data and is written in Rust for compatibility with various environments. While portability is its core value, the emphasis is on creating an intuitive, comfortable development environment for easy custom storage implementation.

Ultimately, GlueSQL aims to significantly reduce the cost, time, and complexity of developing new databases. By leveraging GlueSQL for the parser, planner, and execution layer, developers can focus on creating specific storage implementations, leading to a more convenient query interface like SQL for many environments.

The Problem: Why Reinvent the Database?

Despite the numerous database implementations that currently exist, the emergence of new databases continues. The primary reason behind this trend is our need for databases for a broad spectrum of distinct purposes. For instance, new databases are surfacing that are specifically optimized for Large Language Models (LLMs) like ChatGPT. The range is wide and diverse, encompassing embedded databases, OLAP for data analysis, OLTP databases optimized for online transactions, databases specialized for time-series data processing, and many more.

With such varied requirements, we find ourselves in constant need of fresh databases. However, constructing a database from scratch is a monumental task. It necessitates defining a query interface for handling the database and implementing a corresponding parser. Moreover, a separate execution layer for running operations must be built. Also, the planning layer, which is responsible for devising execution strategies, is a vital aspect of this process. Let's not forget about the critical storage layer that physically reads and stores the data. In a nutshell, there's a daunting amount of work involved in developing a new database.

Given these circumstances, it's understandable why numerous emerging databases resort to high pricing structures—they need immediate revenue to offset continuous development costs.

But the story doesn't end here. Query interfaces like SQL are indeed useful for serious tasks, but they also provide excellent utility for handling simple log files such as CSV, JSONL, Parquet, and even for utilizing REST APIs for various applications. The issue arises when a complex query interface needs to be provided even for these lighter storage requirements—it necessitates a development process almost identical to building a sophisticated database. Implementing an entire parser and execution layer just to add SQL support to an existing service can seem like an excessive burden.

Whether it's a simple storage environment or a serious task, the key lies in the storage layer, which involves the actual reading and storing of data. So, what if developers focused on implementing these storage mechanisms while the remaining parts could be handled using existing libraries? This is the role that GlueSQL aspires to play.

The Vision of GlueSQL

The GlueSQL project aims to offer a unified query interface for various environments. The goal is to allow anyone to port and use SQL and GlueSQL's proprietary query builder, the AST Builder, in any desired environment. This could range from key-value databases, serious NoSQL databases, log files, and even REST API services. Essentially, if a service supports reading or read-writing data, regardless of the data type, it can readily support a complex query interface via GlueSQL.

Presently, the GlueSQL project itself directly supports a few storage types as reference storages. These include in-memory storage for non-persistent data handling, sled storage, which is a key-value database written in Rust, JSON storage for handling JSON and JSONL files, and a storage that ports SQL to the web browser's IndexedDB. While the GlueSQL Team is primarily developing these, the aim is to allow anyone to create such custom storages for a wide array of purposes, thus enabling them to assemble the database of their choosing.

Imagine using GlueSQL's SQL and AST Builder everywhere, with the simple method of swapping out storages to operate in diverse settings. It could significantly reduce software development costs. Developers wouldn't need to learn the different usage methods for each database. Instead, they could focus solely on implementing business logic using the same interface.

Our vision is to reduce database development costs by 10 times, or even more than 20 times. We aim to gather diverse database creators under the GlueSQL banner, making it the go-to solution for cost-effective database development.

Benefits to Database Users: Unifying Query Interfaces, Streamlining Software Development, and Reducing Costs

From the perspective of the users who engage with databases, there has always been the burden of learning different interfaces to interact with each database. The approach required to work with Redis is different from that necessary for MongoDB. Likewise, handling SQL databases necessitates using SQL. Although SQL databases generally use a common SQL, the SQL they support can considerably vary when examined in detail.

Naturally, there are legitimate reasons for such differences. Each database focuses on different areas, and to cater to specialized functionalities, they incorporate dedicated interface mechanisms. However, not all application development needs to utilize these database-specific core special functionalities.

Let's look at a couple of examples:

Suppose you're developing a back-end application that uses MySQL as the database and Redis for caching. Due to the vast differences in handling SQL databases and Redis, you would have to develop using different methods when storing data.

Here's another scenario: -Imagine you're implementing a data migration pipeline between various databases and log files. Let's say you're transferring Parquet to Redis or MongoDB. In this case, you would need to convert data using different methods for each, all of which would be a cumbersome process.

In both of the above examples, GlueSQL can directly address and solve the issues. It offers the convenience of a uniform query interface to deal with these matters. In certain scenarios, even the construction of a data pipeline can potentially be solved with a single SQL query, thanks to GlueSQL.

Benefits to Database Developers: Drastically Lowering Development Costs and Simplifying the Creation of Purpose-Built Databases

If you want to support SQL in the desired environment, using GlueSQL essentially requires you to implement an interface for Storage. There's no need to support all functionalities from the beginning. You can start lightly, choosing and implementing storage features suitable for the environment you want to create. To facilitate this, GlueSQL also provides a library in the form of a test suite to easily validate the storage you've implemented.

Lowering development costs in this way will enable a broader range of developers to support the GlueSQL query interface. As more developers join, a significant synergy can be generated. Designing a query interface from scratch involves a great deal of work, including planning and supporting the interface for different target programming languages.

However, despite all this hard work, it is not easy to attract database users accustomed to different methods.

Consider that the SQL and AST Builder provided by GlueSQL are already securing numerous users. This eliminates the need for efforts to promote a newly planned query interface. Over the years, many new databases have emphasized compatibility with PostgreSQL or MySQL for similar reasons. As GlueSQL places a strong emphasis on portability in its query interface planning, it allows for more flexible configuration according to the desired situation. Through the AST Builder, it also eliminates the cost of porting to different languages.

For many database developers, using GlueSQL can be an optimal choice, as it can save costs and quickly secure users.

Let me mention one more thing: what's convenient for humans... could be applied to AI as well. Rather than making AI write automation code using different databases, providing a common query interface can be much more efficient.

The Future with GlueSQL

GlueSQL has been and will continue to improve and develop new features to enable portability in various environments. Thanks to the schemaless data support added last year, it is now possible to handle both structured data with schema and unstructured data like JSON simultaneously. This has significantly increased the range of storage environments that can be supported.

One of the key features added last year was the AST Builder. This feature allowed us to escape the confines of SQL and provide an interface for comfortably handling data in the programming languages used for development.

Of course, improving existing features is extremely important, and there are many new features to be added. As a major development plan this year, we aim to develop features to effectively attach GlueSQL to NoSQL databases with their own planners and execution layers. The GlueSQL query planner, currently at a basic level, will see significant changes this year. With the expansion of this planner, not only NoSQL databases but also other SQL databases could be supported without sacrificing performance using GlueSQL.

The synergy that arises from the combination of different databases is a significant bonus in this process.

The Journey of the GlueSQL Team

The GlueSQL project was first conceived in the fall of 2019, and since then we have been developing it continuously. Personally, I have created various products in a variety of environments, including game development, backend server, and frontend development over the past decade. The experience gained through this process was a major motivation to start the GlueSQL project.

To put it grandly, the inconveniences felt while using different databases in various environments were a major motivation, wouldn't you say?

The start was actually a bit simple. Around 2019, I was mainly doing web front-end development. However, the lack of a structured database for state management and internal data processing made it very uncomfortable, especially since I couldn't use SQL databases and the like. So I started to lightly create an SQL database that could run on a web browser. Also, I wanted to use Rust, but after failing to introduce it at the company I was working for at the time, I decided to use it in my own project.

But as I started developing, my dreams grew significantly. Beyond a SQL database that simply operates on a web browser, I started envisioning a database that fits the name "Glue", one that can easily be ported to various environments, and I continue that journey to this day.

Whether I took the database project too lightly, or because the features I wanted kept increasing, the content to be developed kept expanding. As a result, I ended up investing full time in the GlueSQL project development for over three years. For a year in between, I even juggled full-time software engineering work alongside GlueSQL development. Currently, I'm back to developing the GlueSQL project full time, alongside various part-time contributors.

Now, we're getting very close to the starting point of the picture I wanted to create through GlueSQL, and thankfully, with contributors joining me, I am not alone.

The Sustainability and Business Aspect of GlueSQL

I believe that what we create through GlueSQL will make a great contribution to the world and make many software engineers happy. This gives me immense strength to continue developing even in difficult situations. However, we cannot accomplish everything with pure passion alone. As much as the GlueSQL project can make a significant contribution, I also see it as holding great business value.

The business strategy of GlueSQL may be somewhat different from other databases. We distribute the project itself as open source under the Apache-2.0 license, so that anyone can use it fully, and we do not consider pricing methods such as restricting features to the storages we support. In fact, if there is any player who can do it better, there's no way to prevent them from taking the GlueSQL project and making it their own.

But we believe that GlueSQL has great potential in this regard. Anyone can participate and they are free to distribute their own storage in the way they want, whether it's open source, private, or commercial. This eliminates the need to create something to replace the GlueSQL project. We aim to prevent the need to recreate the wheel that we provide using GlueSQL.

Moreover, our GlueSQL team seeks to continually expand our group of developers and companies working with us. During this development process, while they can certainly implement everything on their own, there is also no reason not to collaborate with our GlueSQL Team, especially for databases like NoSQL that have their own planners and execution layers. If you have a REST API and want to enhance convenience through SQL support, you can do it yourself or you can collaborate with us.

In addition, for some storages, we can also participate as players in the same position as other custom storage developers. We plan to expand the GlueSQL ecosystem in various ways, such as technical support and storage development.

We are finally ready to provide GlueSQL to users at the production level. We are accelerating the development of GlueSQL. If you are a company interested in storage development like SQL support, or if you resonate with our vision and want to join us, please contact us at taehoon@gluesql.com.

Conclusion

The continued emergence of new databases is driven by the demand for diverse and specialized databases, such as those optimized for Large Language Models (LLMs) and databases catering to unique requirements, like embedded databases, OLAP, OLTP, and time-series data processing. However, developing a new database from scratch is a significant undertaking, requiring extensive work, which often results in high costs.

GlueSQL presents a solution to this challenge by providing a unified query interface that can be ported across various environments, from key-value databases, NoSQL databases, log files, to REST APIs. It allows anyone to create custom storages, reducing the need for developers to build entirely new databases and to learn different usage methods for each database. Instead, they can focus on implementing their business logic using the same interface.

From a user perspective, GlueSQL offers the convenience of a unified query interface, easing the burden of learning different interfaces for each database. This simplification of interface use can also extend to AI, potentially enhancing the efficiency of AI automation.

GlueSQL's development plan includes significant enhancements to its query planner and aims to enable effective attachment of GlueSQL to NoSQL databases. The synergy of combining different databases is a valuable bonus in this process.

Since its inception in the fall of 2019, the GlueSQL team has continuously developed the project, driven by the desire to mitigate the inconveniences encountered while using different databases in various environments. The journey has been a rewarding one, with the GlueSQL project now at a point where it closely resembles the envisioned product.

GlueSQL, distributed under the Apache-2.0 license, is free for anyone to use and adapt. While the GlueSQL team welcomes collaboration with other developers and companies, they also see significant potential for the project as a business venture. The team is working to expand the GlueSQL ecosystem through a variety of initiatives, including technical support and storage development.

With GlueSQL now sufficiently prepared for practical applications, the team invites companies interested in storage development or those who share their vision to join them in their journey of revolutionizing database development.

· 10 min read
Taehoon Moon

Introduction: GlueSQL and Test-Driven Documentation

Recently, the GlueSQL project reached a significant milestone with the release of version 0.14. This new version brings a host of fresh features to the table, yet one of the most notable changes is in the realm of documentation. For the first time, we're proud to announce the launch of our official documentation website. Interested readers can explore the full range of user manuals at https://gluesql.org/docs.

Prior to this update, the only way to navigate GlueSQL was by manually inspecting the test code within the test suite. With the recent release, however, a comprehensive user manual has been made public to facilitate a more user-friendly experience. We hope that this new addition will prove beneficial to a broad spectrum of users.

The task of compiling an entire database manual in one go was daunting due to the sheer volume of content required. Surprisingly, this process turned out to be smoother than initially anticipated, largely due to the invaluable aid of ChatGPT, which was instrumental in automating much of the document creation. Specifically, around 80% of the SQL Syntax section was generated using this tool.

This remarkable feat was only possible due to the solid foundation of test codes previously established in GlueSQL. In this article, we'll share how we managed to leverage ChatGPT in such a unique way. Based on our recent experience of crafting documents grounded in testing, we've begun to consider the possibility of entirely automating document creation, save for the initial stages.

Along with sharing our journey so far, we will also reveal our plans for future test-based automation of documentation within GlueSQL.

Test Codes and Documentation

The GlueSQL project has placed a significant emphasis on writing test codes. This might be a given for a database project; however, the thoroughness of our approach is evident from our line coverage of nearly 99% for core codes. While we devoted considerable effort to creating these test codes, our primary focus has always been on a different aspect: ensuring that anyone can quickly grasp the content of the tests and easily add new ones.

The intent here is to empower newcomers to GlueSQL to understand the functionality of the software solely by examining integration tests, even in the absence of a user manual.

The integration tests for GlueSQL can be found in the test-suite workspace. For example, here's an excerpt of the test code for the INSERT statement:

test_case!(insert, async move {
run!(
"
CREATE TABLE Test (
id INTEGER DEFAULT 1,
num INTEGER NULL,
name TEXT NOT NULL,
);"
);

test! {
name: "basic insert - single item",
sql: "INSERT INTO Test (id, num, name) VALUES (1, 2, 'Hi boo');",
expected: Ok(Payload::Insert(1))
};


test! {
sql: "INSERT INTO Test VALUES(17, 30, 'Sullivan');",
expected: Ok(Payload::Insert(1))
};

test! {
sql: "INSERT INTO Test (num, name) VALUES (28, 'Wazowski');",
expected: Ok(Payload::Insert(1))
};

test! {
sql: "SELECT * FROM Test;",
expected: Ok(select!(
id | num | name;
I64 | I64 | Str;
1 2 "Hi boo".to_owned();
3 9 "Kitty!".to_owned();
2 7 "Monsters".to_owned();
17 30 "Sullivan".to_owned();
1 28 "Wazowski".to_owned()
))
};

// ...
});

Despite being written in Rust, these test cases are designed to be comprehensible, even to those unfamiliar with the language. Each test is a complete scenario from start to finish, and the results of each operation are readily observable.

Given that identifying results from SELECT operations in the form of Rust enums and structs can be challenging, we actively utilized macros such as select! and select_with_null!. We've composed the test cases to demonstrate that the INSERT statement can handle a wide range of cases, including specifying all columns, omitting some, or omitting all.

test! {
sql: "INSERT INTO Test (id, num) VALUES (1, 10);",
expected: Err(InsertError::LackOfRequiredColumn("name".to_owned()).into())
};

The tests also include scenarios for expected faulty inputs, indicating the error returns in these situations.

By organizing the tests in this manner, we aim to make it easy for anyone to read and write tests. Our goal was for these tests to serve as "documentation" for GlueSQL contributors. At the time we were writing these tests, we didn't anticipate that they could actually become documentation themselves. But we've come to realize that they have extraordinary potential.

Leveraging ChatGPT

When we first embarked on writing the User Manual, we were overwhelmed by the sheer volume of content we had to generate. Around the same time, ChatGPT was gaining prominence, and we thought it might be worth trying out, if only to lighten our load slightly.

To our surprise, ChatGPT exceeded our expectations. If the test codes were well written, it was capable of automatically crafting an exceptional document based on them, capturing all essential details.

After several trials and errors, we settled on the following prompt for document generation. While it's still a challenge to use the same prompt for all documentation, we made minor modifications to suit different situations:

I'm creating an SQL database documentation website, and I'd like you to help me with one of the pages that introduces the SQL syntax for GlueSQL.

1. Please provide the response content in the "markdown" format, so I can copy and paste it directly. Keep this constraint in mind while writing.
2. Regardless of the language I use, I need the content written in English.
3. I will provide some test case code written in the Rust language, which contains SQL examples. Please write the documentation based on these examples, but feel free to change the table names, column names, and data types as needed. Don't include any Rust related content or text in the response. all the response code example should be in plain SQL.
4. GlueSQL does not have the VARCHAR type. If you want to use that, please use TEXT instead. You don't need to mention this in the response.
5. Wrap the entire response text using <pre> and </pre> tags so I can copy all the content easily.

Now, I'd like you to write the following request:
SQL Statement - "INSERT"

Here's an example test code you can refer to:

test_case!(insert, async move {
run!(...

Generally, we used the template above, and copied and pasted the test code from our existing test-suite. We leveraged this method to harness our many tests to assist in the creation of the user manual. In the next section, we'll showcase a sample of the documentation generated in this manner. It's quite impressive.

Success Case: Automated User Manual of GlueSQL

Thanks to ChatGPT, the resulting INSERT document page can be viewed at the following link. It's important to note that we used ChatGPT 4 for this task. Version 3.5 wasn't quite up to the task, and using version 4 was the minimum requirement.

https://gluesql.org/docs/dev/sql-syntax/statements/data-manipulation/insert

INSERT Statement

The results were quite impressive. ChatGPT neatly categorized the test cases, explained the syntax, outlined constraints, and provided appropriate examples. It didn't stop there; it also skillfully recognized error test cases and incorporated them into the documentation, as shown below.

INSERT Statement

Isn't it amazing?

Future Plans: Fully Automating Documentation Generation

While the current documentation is far from perfect and there are many aspects that can be improved, we see great potential in this approach. We believe it's entirely possible to automate the process of writing this kind of document, and writing in general.

In the past, documents like user manuals required a great deal of effort to maintain once they were written. If a document contained real code examples, verifying that the code still worked was often a tedious task. With the ability to automatically generate documentation as we have done here, these issues are no longer problematic.

Previously, you would have to write tests and then also document them separately. If you had to support multiple languages, that would be an additional task. With a tool like ChatGPT, you can automate all of this. All a developer has to do is write the tests. This alone can be sufficient. You can generate documents automatically based on the tests. Eventually, we can even support automatically translating these documents into multiple languages.

The GlueSQL project repository is currently hosted on GitHub and makes good use of various GitHub Actions. We envision a GitHub Action that automatically regenerates a document corresponding to a test when a user modifies the test and raises a Pull Request. Another GitHub Action could automatically translate updated documents into supported languages and create new Pull Requests. The possibilities are truly endless.

Not only will this help with document generation, but it will also provide clear guidelines for writing better test code. If we can automatically generate documents based on written tests, the quality of those documents can serve as an indicator of the quality of the tests themselves. This means that a document automation tool can play the role of a good reviewer for tests. It can greatly reduce the time and effort required for painstakingly reviewing the quality of each test. Developers can also write tests without pressure, evaluate their test code by looking at the generated document, and improve it.

Furthermore, multi-language support becomes a breeze. In my personal experience as a software engineer over the past decade, developing various products such as games, web services, and applications, I often needed to support multiple languages. Each time, there was no definite solution. The optimal approach varied depending on the situation, and there were many things to consider when entrusting translations, such as effectively communicating the context of the target service to the translator. Moreover, regularly updating content and having it retranslated into various languages was a very tedious process. While I tried to automate as much as possible by creating various tools, I was never fully satisfied. I believe ChatGPT can completely solve these issues. If there is a need to provide project-specific context, all you need to do is prepare a prompt in advance. Instead of having to rely on and wait for professional translators, we can now entrust this task to ChatGPT, and we only need a few people to review the translated content.

We are nearing a world where documentation is no longer a burden for developers.

Conclusion: The Value of Test-Driven Documentation

The use of ChatGPT to generate documentation has proven a significant step forward in the GlueSQL user manual creation process. Through test-driven documentation, we've managed to automate a substantial part of the manual creation process, saving time and effort, and increasing accuracy.

Moreover, this process has unveiled a new potential for documentation: the possibility of fully automating document generation. We've seen that quality tests can become quality documentation with the help of AI, leading to more efficient workflows and possibly better test code as a result.

The journey doesn't stop here. We envision leveraging this capability further to auto-translate our documents into multiple languages, making our product more accessible to a global audience.

As we progress, we hope that our experience can inspire other developers to explore and embrace the benefits of AI-generated, test-driven documentation. It's not just about saving time—it's about improving the way we work, communicate, and share knowledge.

· 11 min read
Taehoon Moon

Introduction

The divide between SQL and NoSQL databases has often presented challenges in database management. GlueSQL, a unique database maker library, aims to blur this boundary, providing a versatile tool for handling these two distinct types of databases.

In this article, we explore how GlueSQL navigates the features of SQL and NoSQL databases, offering an integrated solution that promotes flexibility and efficiency. With its ability to unify disparate database types, GlueSQL heralds a new age of adaptable database creation and management.

The Interface Perspective: SQL & AST Builder

When we talk about SQL databases, it's almost a given that they support SQL - the standard query language. Although there are slight variations between databases, the convenience of using a similar SQL language across multiple databases cannot be overstated. However, from a software engineer's perspective, there's room for improvement. In most software development scenarios, a specific programming language is used. SQL is a separate language, which can cause friction when integrating it into your software. As a result, rather than using raw SQL, many developers employ query builders or ORMs to manipulate SQL conveniently using their preferred programming language. Although it's not efficient to generate SQL using a query builder and then parse it again in the database, it's a practical and effective choice.

On the other hand, NoSQL databases offer different mechanisms. Some of them have their own language similar to SQL, but most provide an interface library developed specifically for each programming language. While SQL databases rely on external query builder libraries to provide an interface for each programming language, NoSQL databases mostly develop and offer these libraries themselves. If we discount the convenience of SQL language, this is one of the major factors that make NoSQL databases more comfortable to use. Since query builder libraries supporting SQL databases often cater to multiple SQL databases, they are limited in fully supporting unique features of each database. NoSQL databases, on the other hand, can freely manage their interface libraries without these restrictions.

Providing a query interface for each programming language is not a fundamental difference between SQL and NoSQL, but we generally accept it implicitly.

Let's see what happens if we break down this boundary, using GlueSQL as an example. As you can see from the SQL postfix, GlueSQL supports SQL and can be classified as an SQL database.

CREATE TABLE Glue (id INTEGER, name TEXT);

INSERT INTO Glue VALUES (1, "hello"), (2, "gluesql");

SELECT * FROM Glue WHERE id = 1;

However, GlueSQL also supports its own query builder, like a NoSQL database. +

3 posts tagged with "database"

View All Tags

· 14 min read
Taehoon Moon

Introduction

GlueSQL is a versatile database project designed for exceptional portability across a broad range of environments, from embedded systems and servers to web and mobile platforms. The core goal is to support diverse storage environments and manage various data types with a standard SQL approach.

Imagine handling files like CSV, JSONL, and Parquet, or transforming key-value or NoSQL databases such as RocksDB, Redis, and MongoDB into SQL-supporting databases—all feasible with GlueSQL. It can also operate with storages supported in web browsers.

GlueSQL's essential feature is providing a management layer for these diverse storage scenarios without requiring data migration. The broader aim is to facilitate portability of GlueSQL to any environment supporting read or read-write operations. This extends to APIs like GitHub, or messengers like Discord or Slack.

GlueSQL supports both structured and unstructured data and is written in Rust for compatibility with various environments. While portability is its core value, the emphasis is on creating an intuitive, comfortable development environment for easy custom storage implementation.

Ultimately, GlueSQL aims to significantly reduce the cost, time, and complexity of developing new databases. By leveraging GlueSQL for the parser, planner, and execution layer, developers can focus on creating specific storage implementations, leading to a more convenient query interface like SQL for many environments.

The Problem: Why Reinvent the Database?

Despite the numerous database implementations that currently exist, the emergence of new databases continues. The primary reason behind this trend is our need for databases for a broad spectrum of distinct purposes. For instance, new databases are surfacing that are specifically optimized for Large Language Models (LLMs) like ChatGPT. The range is wide and diverse, encompassing embedded databases, OLAP for data analysis, OLTP databases optimized for online transactions, databases specialized for time-series data processing, and many more.

With such varied requirements, we find ourselves in constant need of fresh databases. However, constructing a database from scratch is a monumental task. It necessitates defining a query interface for handling the database and implementing a corresponding parser. Moreover, a separate execution layer for running operations must be built. Also, the planning layer, which is responsible for devising execution strategies, is a vital aspect of this process. Let's not forget about the critical storage layer that physically reads and stores the data. In a nutshell, there's a daunting amount of work involved in developing a new database.

Given these circumstances, it's understandable why numerous emerging databases resort to high pricing structures—they need immediate revenue to offset continuous development costs.

But the story doesn't end here. Query interfaces like SQL are indeed useful for serious tasks, but they also provide excellent utility for handling simple log files such as CSV, JSONL, Parquet, and even for utilizing REST APIs for various applications. The issue arises when a complex query interface needs to be provided even for these lighter storage requirements—it necessitates a development process almost identical to building a sophisticated database. Implementing an entire parser and execution layer just to add SQL support to an existing service can seem like an excessive burden.

Whether it's a simple storage environment or a serious task, the key lies in the storage layer, which involves the actual reading and storing of data. So, what if developers focused on implementing these storage mechanisms while the remaining parts could be handled using existing libraries? This is the role that GlueSQL aspires to play.

The Vision of GlueSQL

The GlueSQL project aims to offer a unified query interface for various environments. The goal is to allow anyone to port and use SQL and GlueSQL's proprietary query builder, the AST Builder, in any desired environment. This could range from key-value databases, serious NoSQL databases, log files, and even REST API services. Essentially, if a service supports reading or read-writing data, regardless of the data type, it can readily support a complex query interface via GlueSQL.

Presently, the GlueSQL project itself directly supports a few storage types as reference storages. These include in-memory storage for non-persistent data handling, sled storage, which is a key-value database written in Rust, JSON storage for handling JSON and JSONL files, and a storage that ports SQL to the web browser's IndexedDB. While the GlueSQL Team is primarily developing these, the aim is to allow anyone to create such custom storages for a wide array of purposes, thus enabling them to assemble the database of their choosing.

Imagine using GlueSQL's SQL and AST Builder everywhere, with the simple method of swapping out storages to operate in diverse settings. It could significantly reduce software development costs. Developers wouldn't need to learn the different usage methods for each database. Instead, they could focus solely on implementing business logic using the same interface.

Our vision is to reduce database development costs by 10 times, or even more than 20 times. We aim to gather diverse database creators under the GlueSQL banner, making it the go-to solution for cost-effective database development.

Benefits to Database Users: Unifying Query Interfaces, Streamlining Software Development, and Reducing Costs

From the perspective of the users who engage with databases, there has always been the burden of learning different interfaces to interact with each database. The approach required to work with Redis is different from that necessary for MongoDB. Likewise, handling SQL databases necessitates using SQL. Although SQL databases generally use a common SQL, the SQL they support can considerably vary when examined in detail.

Naturally, there are legitimate reasons for such differences. Each database focuses on different areas, and to cater to specialized functionalities, they incorporate dedicated interface mechanisms. However, not all application development needs to utilize these database-specific core special functionalities.

Let's look at a couple of examples:

Suppose you're developing a back-end application that uses MySQL as the database and Redis for caching. Due to the vast differences in handling SQL databases and Redis, you would have to develop using different methods when storing data.

Here's another scenario: +Imagine you're implementing a data migration pipeline between various databases and log files. Let's say you're transferring Parquet to Redis or MongoDB. In this case, you would need to convert data using different methods for each, all of which would be a cumbersome process.

In both of the above examples, GlueSQL can directly address and solve the issues. It offers the convenience of a uniform query interface to deal with these matters. In certain scenarios, even the construction of a data pipeline can potentially be solved with a single SQL query, thanks to GlueSQL.

Benefits to Database Developers: Drastically Lowering Development Costs and Simplifying the Creation of Purpose-Built Databases

If you want to support SQL in the desired environment, using GlueSQL essentially requires you to implement an interface for Storage. There's no need to support all functionalities from the beginning. You can start lightly, choosing and implementing storage features suitable for the environment you want to create. To facilitate this, GlueSQL also provides a library in the form of a test suite to easily validate the storage you've implemented.

Lowering development costs in this way will enable a broader range of developers to support the GlueSQL query interface. As more developers join, a significant synergy can be generated. Designing a query interface from scratch involves a great deal of work, including planning and supporting the interface for different target programming languages.

However, despite all this hard work, it is not easy to attract database users accustomed to different methods.

Consider that the SQL and AST Builder provided by GlueSQL are already securing numerous users. This eliminates the need for efforts to promote a newly planned query interface. Over the years, many new databases have emphasized compatibility with PostgreSQL or MySQL for similar reasons. As GlueSQL places a strong emphasis on portability in its query interface planning, it allows for more flexible configuration according to the desired situation. Through the AST Builder, it also eliminates the cost of porting to different languages.

For many database developers, using GlueSQL can be an optimal choice, as it can save costs and quickly secure users.

Let me mention one more thing: what's convenient for humans... could be applied to AI as well. Rather than making AI write automation code using different databases, providing a common query interface can be much more efficient.

The Future with GlueSQL

GlueSQL has been and will continue to improve and develop new features to enable portability in various environments. Thanks to the schemaless data support added last year, it is now possible to handle both structured data with schema and unstructured data like JSON simultaneously. This has significantly increased the range of storage environments that can be supported.

One of the key features added last year was the AST Builder. This feature allowed us to escape the confines of SQL and provide an interface for comfortably handling data in the programming languages used for development.

Of course, improving existing features is extremely important, and there are many new features to be added. As a major development plan this year, we aim to develop features to effectively attach GlueSQL to NoSQL databases with their own planners and execution layers. The GlueSQL query planner, currently at a basic level, will see significant changes this year. With the expansion of this planner, not only NoSQL databases but also other SQL databases could be supported without sacrificing performance using GlueSQL.

The synergy that arises from the combination of different databases is a significant bonus in this process.

The Journey of the GlueSQL Team

The GlueSQL project was first conceived in the fall of 2019, and since then we have been developing it continuously. Personally, I have created various products in a variety of environments, including game development, backend server, and frontend development over the past decade. The experience gained through this process was a major motivation to start the GlueSQL project.

To put it grandly, the inconveniences felt while using different databases in various environments were a major motivation, wouldn't you say?

The start was actually a bit simple. Around 2019, I was mainly doing web front-end development. However, the lack of a structured database for state management and internal data processing made it very uncomfortable, especially since I couldn't use SQL databases and the like. So I started to lightly create an SQL database that could run on a web browser. Also, I wanted to use Rust, but after failing to introduce it at the company I was working for at the time, I decided to use it in my own project.

But as I started developing, my dreams grew significantly. Beyond a SQL database that simply operates on a web browser, I started envisioning a database that fits the name "Glue", one that can easily be ported to various environments, and I continue that journey to this day.

Whether I took the database project too lightly, or because the features I wanted kept increasing, the content to be developed kept expanding. As a result, I ended up investing full time in the GlueSQL project development for over three years. For a year in between, I even juggled full-time software engineering work alongside GlueSQL development. Currently, I'm back to developing the GlueSQL project full time, alongside various part-time contributors.

Now, we're getting very close to the starting point of the picture I wanted to create through GlueSQL, and thankfully, with contributors joining me, I am not alone.

The Sustainability and Business Aspect of GlueSQL

I believe that what we create through GlueSQL will make a great contribution to the world and make many software engineers happy. This gives me immense strength to continue developing even in difficult situations. However, we cannot accomplish everything with pure passion alone. As much as the GlueSQL project can make a significant contribution, I also see it as holding great business value.

The business strategy of GlueSQL may be somewhat different from other databases. We distribute the project itself as open source under the Apache-2.0 license, so that anyone can use it fully, and we do not consider pricing methods such as restricting features to the storages we support. In fact, if there is any player who can do it better, there's no way to prevent them from taking the GlueSQL project and making it their own.

But we believe that GlueSQL has great potential in this regard. Anyone can participate and they are free to distribute their own storage in the way they want, whether it's open source, private, or commercial. This eliminates the need to create something to replace the GlueSQL project. We aim to prevent the need to recreate the wheel that we provide using GlueSQL.

Moreover, our GlueSQL team seeks to continually expand our group of developers and companies working with us. During this development process, while they can certainly implement everything on their own, there is also no reason not to collaborate with our GlueSQL Team, especially for databases like NoSQL that have their own planners and execution layers. If you have a REST API and want to enhance convenience through SQL support, you can do it yourself or you can collaborate with us.

In addition, for some storages, we can also participate as players in the same position as other custom storage developers. We plan to expand the GlueSQL ecosystem in various ways, such as technical support and storage development.

We are finally ready to provide GlueSQL to users at the production level. We are accelerating the development of GlueSQL. If you are a company interested in storage development like SQL support, or if you resonate with our vision and want to join us, please contact us at taehoon@gluesql.com.

Conclusion

The continued emergence of new databases is driven by the demand for diverse and specialized databases, such as those optimized for Large Language Models (LLMs) and databases catering to unique requirements, like embedded databases, OLAP, OLTP, and time-series data processing. However, developing a new database from scratch is a significant undertaking, requiring extensive work, which often results in high costs.

GlueSQL presents a solution to this challenge by providing a unified query interface that can be ported across various environments, from key-value databases, NoSQL databases, log files, to REST APIs. It allows anyone to create custom storages, reducing the need for developers to build entirely new databases and to learn different usage methods for each database. Instead, they can focus on implementing their business logic using the same interface.

From a user perspective, GlueSQL offers the convenience of a unified query interface, easing the burden of learning different interfaces for each database. This simplification of interface use can also extend to AI, potentially enhancing the efficiency of AI automation.

GlueSQL's development plan includes significant enhancements to its query planner and aims to enable effective attachment of GlueSQL to NoSQL databases. The synergy of combining different databases is a valuable bonus in this process.

Since its inception in the fall of 2019, the GlueSQL team has continuously developed the project, driven by the desire to mitigate the inconveniences encountered while using different databases in various environments. The journey has been a rewarding one, with the GlueSQL project now at a point where it closely resembles the envisioned product.

GlueSQL, distributed under the Apache-2.0 license, is free for anyone to use and adapt. While the GlueSQL team welcomes collaboration with other developers and companies, they also see significant potential for the project as a business venture. The team is working to expand the GlueSQL ecosystem through a variety of initiatives, including technical support and storage development.

With GlueSQL now sufficiently prepared for practical applications, the team invites companies interested in storage development or those who share their vision to join them in their journey of revolutionizing database development.

· 10 min read
Taehoon Moon

Introduction: GlueSQL and Test-Driven Documentation

Recently, the GlueSQL project reached a significant milestone with the release of version 0.14. This new version brings a host of fresh features to the table, yet one of the most notable changes is in the realm of documentation. For the first time, we're proud to announce the launch of our official documentation website. Interested readers can explore the full range of user manuals at https://gluesql.org/docs.

Prior to this update, the only way to navigate GlueSQL was by manually inspecting the test code within the test suite. With the recent release, however, a comprehensive user manual has been made public to facilitate a more user-friendly experience. We hope that this new addition will prove beneficial to a broad spectrum of users.

The task of compiling an entire database manual in one go was daunting due to the sheer volume of content required. Surprisingly, this process turned out to be smoother than initially anticipated, largely due to the invaluable aid of ChatGPT, which was instrumental in automating much of the document creation. Specifically, around 80% of the SQL Syntax section was generated using this tool.

This remarkable feat was only possible due to the solid foundation of test codes previously established in GlueSQL. In this article, we'll share how we managed to leverage ChatGPT in such a unique way. Based on our recent experience of crafting documents grounded in testing, we've begun to consider the possibility of entirely automating document creation, save for the initial stages.

Along with sharing our journey so far, we will also reveal our plans for future test-based automation of documentation within GlueSQL.

Test Codes and Documentation

The GlueSQL project has placed a significant emphasis on writing test codes. This might be a given for a database project; however, the thoroughness of our approach is evident from our line coverage of nearly 99% for core codes. While we devoted considerable effort to creating these test codes, our primary focus has always been on a different aspect: ensuring that anyone can quickly grasp the content of the tests and easily add new ones.

The intent here is to empower newcomers to GlueSQL to understand the functionality of the software solely by examining integration tests, even in the absence of a user manual.

The integration tests for GlueSQL can be found in the test-suite workspace. For example, here's an excerpt of the test code for the INSERT statement:

test_case!(insert, async move {
run!(
"
CREATE TABLE Test (
id INTEGER DEFAULT 1,
num INTEGER NULL,
name TEXT NOT NULL,
);"
);

test! {
name: "basic insert - single item",
sql: "INSERT INTO Test (id, num, name) VALUES (1, 2, 'Hi boo');",
expected: Ok(Payload::Insert(1))
};


test! {
sql: "INSERT INTO Test VALUES(17, 30, 'Sullivan');",
expected: Ok(Payload::Insert(1))
};

test! {
sql: "INSERT INTO Test (num, name) VALUES (28, 'Wazowski');",
expected: Ok(Payload::Insert(1))
};

test! {
sql: "SELECT * FROM Test;",
expected: Ok(select!(
id | num | name;
I64 | I64 | Str;
1 2 "Hi boo".to_owned();
3 9 "Kitty!".to_owned();
2 7 "Monsters".to_owned();
17 30 "Sullivan".to_owned();
1 28 "Wazowski".to_owned()
))
};

// ...
});

Despite being written in Rust, these test cases are designed to be comprehensible, even to those unfamiliar with the language. Each test is a complete scenario from start to finish, and the results of each operation are readily observable.

Given that identifying results from SELECT operations in the form of Rust enums and structs can be challenging, we actively utilized macros such as select! and select_with_null!. We've composed the test cases to demonstrate that the INSERT statement can handle a wide range of cases, including specifying all columns, omitting some, or omitting all.

test! {
sql: "INSERT INTO Test (id, num) VALUES (1, 10);",
expected: Err(InsertError::LackOfRequiredColumn("name".to_owned()).into())
};

The tests also include scenarios for expected faulty inputs, indicating the error returns in these situations.

By organizing the tests in this manner, we aim to make it easy for anyone to read and write tests. Our goal was for these tests to serve as "documentation" for GlueSQL contributors. At the time we were writing these tests, we didn't anticipate that they could actually become documentation themselves. But we've come to realize that they have extraordinary potential.

Leveraging ChatGPT

When we first embarked on writing the User Manual, we were overwhelmed by the sheer volume of content we had to generate. Around the same time, ChatGPT was gaining prominence, and we thought it might be worth trying out, if only to lighten our load slightly.

To our surprise, ChatGPT exceeded our expectations. If the test codes were well written, it was capable of automatically crafting an exceptional document based on them, capturing all essential details.

After several trials and errors, we settled on the following prompt for document generation. While it's still a challenge to use the same prompt for all documentation, we made minor modifications to suit different situations:

I'm creating an SQL database documentation website, and I'd like you to help me with one of the pages that introduces the SQL syntax for GlueSQL.

1. Please provide the response content in the "markdown" format, so I can copy and paste it directly. Keep this constraint in mind while writing.
2. Regardless of the language I use, I need the content written in English.
3. I will provide some test case code written in the Rust language, which contains SQL examples. Please write the documentation based on these examples, but feel free to change the table names, column names, and data types as needed. Don't include any Rust related content or text in the response. all the response code example should be in plain SQL.
4. GlueSQL does not have the VARCHAR type. If you want to use that, please use TEXT instead. You don't need to mention this in the response.
5. Wrap the entire response text using <pre> and </pre> tags so I can copy all the content easily.

Now, I'd like you to write the following request:
SQL Statement - "INSERT"

Here's an example test code you can refer to:

test_case!(insert, async move {
run!(...

Generally, we used the template above, and copied and pasted the test code from our existing test-suite. We leveraged this method to harness our many tests to assist in the creation of the user manual. In the next section, we'll showcase a sample of the documentation generated in this manner. It's quite impressive.

Success Case: Automated User Manual of GlueSQL

Thanks to ChatGPT, the resulting INSERT document page can be viewed at the following link. It's important to note that we used ChatGPT 4 for this task. Version 3.5 wasn't quite up to the task, and using version 4 was the minimum requirement.

https://gluesql.org/docs/dev/sql-syntax/statements/data-manipulation/insert

INSERT Statement

The results were quite impressive. ChatGPT neatly categorized the test cases, explained the syntax, outlined constraints, and provided appropriate examples. It didn't stop there; it also skillfully recognized error test cases and incorporated them into the documentation, as shown below.

INSERT Statement

Isn't it amazing?

Future Plans: Fully Automating Documentation Generation

While the current documentation is far from perfect and there are many aspects that can be improved, we see great potential in this approach. We believe it's entirely possible to automate the process of writing this kind of document, and writing in general.

In the past, documents like user manuals required a great deal of effort to maintain once they were written. If a document contained real code examples, verifying that the code still worked was often a tedious task. With the ability to automatically generate documentation as we have done here, these issues are no longer problematic.

Previously, you would have to write tests and then also document them separately. If you had to support multiple languages, that would be an additional task. With a tool like ChatGPT, you can automate all of this. All a developer has to do is write the tests. This alone can be sufficient. You can generate documents automatically based on the tests. Eventually, we can even support automatically translating these documents into multiple languages.

The GlueSQL project repository is currently hosted on GitHub and makes good use of various GitHub Actions. We envision a GitHub Action that automatically regenerates a document corresponding to a test when a user modifies the test and raises a Pull Request. Another GitHub Action could automatically translate updated documents into supported languages and create new Pull Requests. The possibilities are truly endless.

Not only will this help with document generation, but it will also provide clear guidelines for writing better test code. If we can automatically generate documents based on written tests, the quality of those documents can serve as an indicator of the quality of the tests themselves. This means that a document automation tool can play the role of a good reviewer for tests. It can greatly reduce the time and effort required for painstakingly reviewing the quality of each test. Developers can also write tests without pressure, evaluate their test code by looking at the generated document, and improve it.

Furthermore, multi-language support becomes a breeze. In my personal experience as a software engineer over the past decade, developing various products such as games, web services, and applications, I often needed to support multiple languages. Each time, there was no definite solution. The optimal approach varied depending on the situation, and there were many things to consider when entrusting translations, such as effectively communicating the context of the target service to the translator. Moreover, regularly updating content and having it retranslated into various languages was a very tedious process. While I tried to automate as much as possible by creating various tools, I was never fully satisfied. I believe ChatGPT can completely solve these issues. If there is a need to provide project-specific context, all you need to do is prepare a prompt in advance. Instead of having to rely on and wait for professional translators, we can now entrust this task to ChatGPT, and we only need a few people to review the translated content.

We are nearing a world where documentation is no longer a burden for developers.

Conclusion: The Value of Test-Driven Documentation

The use of ChatGPT to generate documentation has proven a significant step forward in the GlueSQL user manual creation process. Through test-driven documentation, we've managed to automate a substantial part of the manual creation process, saving time and effort, and increasing accuracy.

Moreover, this process has unveiled a new potential for documentation: the possibility of fully automating document generation. We've seen that quality tests can become quality documentation with the help of AI, leading to more efficient workflows and possibly better test code as a result.

The journey doesn't stop here. We envision leveraging this capability further to auto-translate our documents into multiple languages, making our product more accessible to a global audience.

As we progress, we hope that our experience can inspire other developers to explore and embrace the benefits of AI-generated, test-driven documentation. It's not just about saving time—it's about improving the way we work, communicate, and share knowledge.

· 11 min read
Taehoon Moon

Introduction

The divide between SQL and NoSQL databases has often presented challenges in database management. GlueSQL, a unique database maker library, aims to blur this boundary, providing a versatile tool for handling these two distinct types of databases.

In this article, we explore how GlueSQL navigates the features of SQL and NoSQL databases, offering an integrated solution that promotes flexibility and efficiency. With its ability to unify disparate database types, GlueSQL heralds a new age of adaptable database creation and management.

The Interface Perspective: SQL & AST Builder

When we talk about SQL databases, it's almost a given that they support SQL - the standard query language. Although there are slight variations between databases, the convenience of using a similar SQL language across multiple databases cannot be overstated. However, from a software engineer's perspective, there's room for improvement. In most software development scenarios, a specific programming language is used. SQL is a separate language, which can cause friction when integrating it into your software. As a result, rather than using raw SQL, many developers employ query builders or ORMs to manipulate SQL conveniently using their preferred programming language. Although it's not efficient to generate SQL using a query builder and then parse it again in the database, it's a practical and effective choice.

On the other hand, NoSQL databases offer different mechanisms. Some of them have their own language similar to SQL, but most provide an interface library developed specifically for each programming language. While SQL databases rely on external query builder libraries to provide an interface for each programming language, NoSQL databases mostly develop and offer these libraries themselves. If we discount the convenience of SQL language, this is one of the major factors that make NoSQL databases more comfortable to use. Since query builder libraries supporting SQL databases often cater to multiple SQL databases, they are limited in fully supporting unique features of each database. NoSQL databases, on the other hand, can freely manage their interface libraries without these restrictions.

Providing a query interface for each programming language is not a fundamental difference between SQL and NoSQL, but we generally accept it implicitly.

Let's see what happens if we break down this boundary, using GlueSQL as an example. As you can see from the SQL postfix, GlueSQL supports SQL and can be classified as an SQL database.

CREATE TABLE Glue (id INTEGER, name TEXT);

INSERT INTO Glue VALUES (1, "hello"), (2, "gluesql");

SELECT * FROM Glue WHERE id = 1;

However, GlueSQL also supports its own query builder, like a NoSQL database. (Currently, only Rust is supported, but we're working on adding support for other languages.)

table("Glue")
.create_table()
.add_column("id INTEGER")
.add_column("name TEXT")
.execute(glue)

table("Glue")
.insert()
.values(vec![
vec![num(1), text("hello")],
vec![num(2), text("gluesql")],
])
.execute(glue)
.await;

table("Glue")
.select()
.filter(col("id").eq(1))
.execute(glue)
.await;

Let's reconsider the implicit distinction between SQL and NoSQL. GlueSQL indeed supports SQL, but it also officially develops and offers its own query builder. This query builder is not a secondary tool for SQL. While most SQL query builder libraries ultimately generate SQL strings, GlueSQL's builder directly creates an AST (Abstract Structure Tree) that is used for execution within GlueSQL. Hence, we call it the AST Builder. This means SQL and the AST Builder are two equally supported interfaces in GlueSQL.

This also offers an additional advantage:

table("Glue")
.select()
// 1.
.filter(col("id").eq(1))
// 2.
.filter("id = 1")
.execute(glue)
.await;

Because GlueSQL already supports SQL, not only can you use the custom interface in the AST Builder, but you can also use familiar SQL syntax in part. Whether you use col("id").eq(1) or "id = 1", you can use it in the way you prefer. The AST Builder interface, although initially unfamiliar, allows a gradual migration similar to writing SQL for your convenience.

Thus, we've dismantled one of the implicit distinctions between SQL and NoSQL. However, it's more of an implicit differentiation than a fundamental one. There are more significant design differences that we'll explore next.

Structured & Unstructured Data

In this section, we'll discuss how SQL and NoSQL handle data. SQL generally deals with structured data, and recently, it's been made to support semi-structured data as well. On the other hand, NoSQL supports schemaless, unstructured data. Then, we'll explain in detail how GlueSQL handles these two types of data. The last part of this section will provide a segue into the next section where we'll discuss the decomposition of database functions.

When talking about SQL databases, one aspect is usually considered together: SQL databases have a defined schema.

CREATE TABLE Foo (
id INTEGER,
name TEXT,
rate FLOAT NULL
);

However, these days, SQL databases tend to support semi-structured data types, such as LIST or JSON. But, supporting completely schemaless, unstructured data is a different matter. SQL databases typically require a minimum schema.

What about NoSQL databases? As NoSQL databases vary significantly, we can't make definitive statements. But let's consider a typical document database like MongoDB. Unlike SQL databases, it doesn't enforce a schema. Essentially, you can insert any form of data directly. Often, NoSQL databases support schemaless data, but they lack features that enforce a schema like SQL. They generally support structure via validation methods, rather than structured access.

Is there no choice but to distinguish between structured data and unstructured, schemaless data so clearly? GlueSQL is being developed with the goal of being adaptable in various environments. Being forced to choose regarding this schema constraint was quite inconvenient. We started pondering if we couldn't benefit from both aspects - supporting both schema and schemaless data simultaneously, and we eventually found the answer. Let's look at how GlueSQL currently solves this issue through familiar SQL examples.

CREATE TABLE Names (id INTEGER, name TEXT);
INSERT INTO Names VALUES (1, 'glue'), (2, 'sql');

You can create a regular table with a schema like this. But GlueSQL's choice for creating a schemaless table is as follows:

CREATE TABLE Logs;
INSERT INTO Logs VALUES
('{ "id": 1, "value": 30 }'),
('{ "id": 2, "rate": 3.0, "list": [1, 2, 3] }'),
('{ "id": 3, "rate": 5.0, "value": 100 }');

It creates a table without column definitions! If you do this, GlueSQL recognizes the table as schemaless and processes it internally.

SELECT id, rate, list[0] FROM Logs WHERE id = 2;

Although the way to create the table was a bit special, using it isn't much different from the regular SQL SELECT statement. Not only can you differentiate between schema and schemaless when creating tables, but you can also use them interchangeably!

SELECT * FROM Names JOIN Logs ON Names.id = Logs.id;
/*
| id | list | name | rate | value |
|----|---------|------|------|-------|
| 1 | | glue | | 30 |
| 2 |[1, 2, 3]| sql | 3 | |
*/

Here's an example of querying data by INNER JOINing the Names table, which has a schema, and the Logs table, which is schemaless. GlueSQL has resolved this problem by allowing the internal execution layer to handle both vector-type data, for cases where each row has a defined schema, and map-type data for schemaless cases.

Thanks to this, the variety of storage that can be supported through GlueSQL has expanded significantly. If there were previously limitations to supporting NoSQL databases that support schemaless data, that is no longer the case. The reference storage where you can directly experience this schemaless data support is JSON Storage. It offers features that allow you to deal directly with unstructured data like JSON using GlueSQL.

If GlueSQL starts from the perspective of an SQL database and expands, by providing the AST Builder directly, it once blurs the boundary, and by supporting unstructured data simultaneously, it knocks down the boundary once more. How do you like it?

Decomposing Database Functionality: Breaking Down SQL and NoSQL Features

The distinction between SQL and NoSQL is not just about whether they support unstructured data. Of course, there are examples like unstructured data, which is mainly supported only in NoSQL, but in many cases, SQL databases tend to support more diverse and complex queries. NoSQL often gains other advantages in exchange for reducing the range of query support provided by SQL databases.

GlueSQL is ambitious. It has devised a rather interesting method to support all of this through SQL and the AST Builder, with the same interface. When we usually say SQL database, it implicitly assumes that a lot of features have been fully implemented. Create tables by specifying a schema, modify schemas with "alter table", support both clustered and non-clustered indexes, and support transactions. And there's so much more. But the functionality that is naturally supported in SQL databases may not be natural in other environments.

Let's think about JSON Storage. GlueSQL's JSON Storage allows you to handle JSON, JSONL files using SQL and the AST Builder. This JSON Storage does not support atomic operations or transactions. Of course, it would be great if it did, but implementing and executing them would be a significant performance burden. In most cases, when you want to simply browse and handle JSONL files, the overhead caused by transactions can be an unnecessary burden. In this case, you want to handle JSON, JSONL files using SQL, but you don't necessarily need transactions.

To meet the requirements of these diverse environments, GlueSQL has separated the functionality of what we usually call an SQL database into multiple independent interfaces. Store, StoreMut, AlterTable, Transaction, .. These are just a few of the various storage interfaces that GlueSQL currently supports. @@ -24,7 +24,7 @@ The Transaction interface works the same way. The interesting part is that, except for Store and StoreMut, all other storage interfaces can be implemented independently. GlueSQL allows you to choose and implement only the features you need. And it's not just about providing interfaces. It also provides integration tests suitable for each situation to verify what you have implemented. You just need to implement the interface and import the corresponding test case for verification.

In addition to supporting both structured and unstructured data simultaneously, GlueSQL provides the ability to divide the functionality of a database into multiple independent features and selectively implement them. This allows GlueSQL to be ported to a wide variety of environments without any burden.

Conclusion

GlueSQL, while serving as a database that provides its own reference storage, is fundamentally a library designed to simplify the creation of databases. One of the substantial challenges GlueSQL had to overcome in order to support a diverse array of environments was to address the distinctive features that separate conventional SQL databases from NoSQL databases. GlueSQL achieved this through several innovative approaches, managing to support both categories simultaneously despite their significantly different characteristics.

It offers support for SQL alongside an AST Builder, and accommodates both structured and unstructured data. Additionally, it decomposes database functionalities into multiple independent features, allowing each environment to selectively implement the functionalities it requires.

These unique attributes enable GlueSQL to live up to its 'Glue' prefix by facilitating effortless porting across various environments. While we have been developing it for several years, there is still much ground to cover. However, the fact that we are now able to introduce it publicly attests to our successful technological validation and completion of a demonstrable level of implementation.

Through GlueSQL, we hope to provide developers with a unified query interface that can be customized according to their needs, thereby enabling them to produce efficient products more effortlessly. There's a promising future ahead for GlueSQL, and we look forward to its contributions to the technology community.

- - + + \ No newline at end of file diff --git a/docs/dev/blog/tags/documentation/index.html b/docs/dev/blog/tags/documentation/index.html index f37f29c0..3cb605a7 100644 --- a/docs/dev/blog/tags/documentation/index.html +++ b/docs/dev/blog/tags/documentation/index.html @@ -1,17 +1,17 @@ - + - + One post tagged with "Documentation" | GlueSQL - - - + + +
-

One post tagged with "Documentation"

View All Tags

· 10 min read
Taehoon Moon

Introduction: GlueSQL and Test-Driven Documentation

Recently, the GlueSQL project reached a significant milestone with the release of version 0.14. This new version brings a host of fresh features to the table, yet one of the most notable changes is in the realm of documentation. For the first time, we're proud to announce the launch of our official documentation website. Interested readers can explore the full range of user manuals at https://gluesql.org/docs.

Prior to this update, the only way to navigate GlueSQL was by manually inspecting the test code within the test suite. With the recent release, however, a comprehensive user manual has been made public to facilitate a more user-friendly experience. We hope that this new addition will prove beneficial to a broad spectrum of users.

The task of compiling an entire database manual in one go was daunting due to the sheer volume of content required. Surprisingly, this process turned out to be smoother than initially anticipated, largely due to the invaluable aid of ChatGPT, which was instrumental in automating much of the document creation. Specifically, around 80% of the SQL Syntax section was generated using this tool.

This remarkable feat was only possible due to the solid foundation of test codes previously established in GlueSQL. In this article, we'll share how we managed to leverage ChatGPT in such a unique way. Based on our recent experience of crafting documents grounded in testing, we've begun to consider the possibility of entirely automating document creation, save for the initial stages.

Along with sharing our journey so far, we will also reveal our plans for future test-based automation of documentation within GlueSQL.

Test Codes and Documentation

The GlueSQL project has placed a significant emphasis on writing test codes. This might be a given for a database project; however, the thoroughness of our approach is evident from our line coverage of nearly 99% for core codes. While we devoted considerable effort to creating these test codes, our primary focus has always been on a different aspect: ensuring that anyone can quickly grasp the content of the tests and easily add new ones.

The intent here is to empower newcomers to GlueSQL to understand the functionality of the software solely by examining integration tests, even in the absence of a user manual.

The integration tests for GlueSQL can be found in the test-suite workspace. For example, here's an excerpt of the test code for the INSERT statement:

test_case!(insert, async move {
run!(
"
CREATE TABLE Test (
id INTEGER DEFAULT 1,
num INTEGER NULL,
name TEXT NOT NULL,
);"
);

test! {
name: "basic insert - single item",
sql: "INSERT INTO Test (id, num, name) VALUES (1, 2, 'Hi boo');",
expected: Ok(Payload::Insert(1))
};


test! {
sql: "INSERT INTO Test VALUES(17, 30, 'Sullivan');",
expected: Ok(Payload::Insert(1))
};

test! {
sql: "INSERT INTO Test (num, name) VALUES (28, 'Wazowski');",
expected: Ok(Payload::Insert(1))
};

test! {
sql: "SELECT * FROM Test;",
expected: Ok(select!(
id | num | name;
I64 | I64 | Str;
1 2 "Hi boo".to_owned();
3 9 "Kitty!".to_owned();
2 7 "Monsters".to_owned();
17 30 "Sullivan".to_owned();
1 28 "Wazowski".to_owned()
))
};

// ...
});

Despite being written in Rust, these test cases are designed to be comprehensible, even to those unfamiliar with the language. Each test is a complete scenario from start to finish, and the results of each operation are readily observable.

Given that identifying results from SELECT operations in the form of Rust enums and structs can be challenging, we actively utilized macros such as select! and select_with_null!. We've composed the test cases to demonstrate that the INSERT statement can handle a wide range of cases, including specifying all columns, omitting some, or omitting all.

test! {
sql: "INSERT INTO Test (id, num) VALUES (1, 10);",
expected: Err(InsertError::LackOfRequiredColumn("name".to_owned()).into())
};

The tests also include scenarios for expected faulty inputs, indicating the error returns in these situations.

By organizing the tests in this manner, we aim to make it easy for anyone to read and write tests. Our goal was for these tests to serve as "documentation" for GlueSQL contributors. At the time we were writing these tests, we didn't anticipate that they could actually become documentation themselves. But we've come to realize that they have extraordinary potential.

Leveraging ChatGPT

When we first embarked on writing the User Manual, we were overwhelmed by the sheer volume of content we had to generate. Around the same time, ChatGPT was gaining prominence, and we thought it might be worth trying out, if only to lighten our load slightly.

To our surprise, ChatGPT exceeded our expectations. If the test codes were well written, it was capable of automatically crafting an exceptional document based on them, capturing all essential details.

After several trials and errors, we settled on the following prompt for document generation. While it's still a challenge to use the same prompt for all documentation, we made minor modifications to suit different situations:

I'm creating an SQL database documentation website, and I'd like you to help me with one of the pages that introduces the SQL syntax for GlueSQL.

1. Please provide the response content in the "markdown" format, so I can copy and paste it directly. Keep this constraint in mind while writing.
2. Regardless of the language I use, I need the content written in English.
3. I will provide some test case code written in the Rust language, which contains SQL examples. Please write the documentation based on these examples, but feel free to change the table names, column names, and data types as needed. Don't include any Rust related content or text in the response. all the response code example should be in plain SQL.
4. GlueSQL does not have the VARCHAR type. If you want to use that, please use TEXT instead. You don't need to mention this in the response.
5. Wrap the entire response text using <pre> and </pre> tags so I can copy all the content easily.

Now, I'd like you to write the following request:
SQL Statement - "INSERT"

Here's an example test code you can refer to:

test_case!(insert, async move {
run!(...

Generally, we used the template above, and copied and pasted the test code from our existing test-suite. We leveraged this method to harness our many tests to assist in the creation of the user manual. In the next section, we'll showcase a sample of the documentation generated in this manner. It's quite impressive.

Success Case: Automated User Manual of GlueSQL

Thanks to ChatGPT, the resulting INSERT document page can be viewed at the following link. It's important to note that we used ChatGPT 4 for this task. Version 3.5 wasn't quite up to the task, and using version 4 was the minimum requirement.

https://gluesql.org/docs/dev/sql-syntax/statements/data-manipulation/insert

INSERT Statement

The results were quite impressive. ChatGPT neatly categorized the test cases, explained the syntax, outlined constraints, and provided appropriate examples. It didn't stop there; it also skillfully recognized error test cases and incorporated them into the documentation, as shown below.

INSERT Statement

Isn't it amazing?

Future Plans: Fully Automating Documentation Generation

While the current documentation is far from perfect and there are many aspects that can be improved, we see great potential in this approach. We believe it's entirely possible to automate the process of writing this kind of document, and writing in general.

In the past, documents like user manuals required a great deal of effort to maintain once they were written. If a document contained real code examples, verifying that the code still worked was often a tedious task. With the ability to automatically generate documentation as we have done here, these issues are no longer problematic.

Previously, you would have to write tests and then also document them separately. If you had to support multiple languages, that would be an additional task. With a tool like ChatGPT, you can automate all of this. All a developer has to do is write the tests. This alone can be sufficient. You can generate documents automatically based on the tests. Eventually, we can even support automatically translating these documents into multiple languages.

The GlueSQL project repository is currently hosted on GitHub and makes good use of various GitHub Actions. We envision a GitHub Action that automatically regenerates a document corresponding to a test when a user modifies the test and raises a Pull Request. Another GitHub Action could automatically translate updated documents into supported languages and create new Pull Requests. The possibilities are truly endless.

Not only will this help with document generation, but it will also provide clear guidelines for writing better test code. If we can automatically generate documents based on written tests, the quality of those documents can serve as an indicator of the quality of the tests themselves. This means that a document automation tool can play the role of a good reviewer for tests. It can greatly reduce the time and effort required for painstakingly reviewing the quality of each test. Developers can also write tests without pressure, evaluate their test code by looking at the generated document, and improve it.

Furthermore, multi-language support becomes a breeze. In my personal experience as a software engineer over the past decade, developing various products such as games, web services, and applications, I often needed to support multiple languages. Each time, there was no definite solution. The optimal approach varied depending on the situation, and there were many things to consider when entrusting translations, such as effectively communicating the context of the target service to the translator. Moreover, regularly updating content and having it retranslated into various languages was a very tedious process. While I tried to automate as much as possible by creating various tools, I was never fully satisfied. I believe ChatGPT can completely solve these issues. If there is a need to provide project-specific context, all you need to do is prepare a prompt in advance. Instead of having to rely on and wait for professional translators, we can now entrust this task to ChatGPT, and we only need a few people to review the translated content.

We are nearing a world where documentation is no longer a burden for developers.

Conclusion: The Value of Test-Driven Documentation

The use of ChatGPT to generate documentation has proven a significant step forward in the GlueSQL user manual creation process. Through test-driven documentation, we've managed to automate a substantial part of the manual creation process, saving time and effort, and increasing accuracy.

Moreover, this process has unveiled a new potential for documentation: the possibility of fully automating document generation. We've seen that quality tests can become quality documentation with the help of AI, leading to more efficient workflows and possibly better test code as a result.

The journey doesn't stop here. We envision leveraging this capability further to auto-translate our documents into multiple languages, making our product more accessible to a global audience.

As we progress, we hope that our experience can inspire other developers to explore and embrace the benefits of AI-generated, test-driven documentation. It's not just about saving time—it's about improving the way we work, communicate, and share knowledge.

- - +

One post tagged with "Documentation"

View All Tags

· 10 min read
Taehoon Moon

Introduction: GlueSQL and Test-Driven Documentation

Recently, the GlueSQL project reached a significant milestone with the release of version 0.14. This new version brings a host of fresh features to the table, yet one of the most notable changes is in the realm of documentation. For the first time, we're proud to announce the launch of our official documentation website. Interested readers can explore the full range of user manuals at https://gluesql.org/docs.

Prior to this update, the only way to navigate GlueSQL was by manually inspecting the test code within the test suite. With the recent release, however, a comprehensive user manual has been made public to facilitate a more user-friendly experience. We hope that this new addition will prove beneficial to a broad spectrum of users.

The task of compiling an entire database manual in one go was daunting due to the sheer volume of content required. Surprisingly, this process turned out to be smoother than initially anticipated, largely due to the invaluable aid of ChatGPT, which was instrumental in automating much of the document creation. Specifically, around 80% of the SQL Syntax section was generated using this tool.

This remarkable feat was only possible due to the solid foundation of test codes previously established in GlueSQL. In this article, we'll share how we managed to leverage ChatGPT in such a unique way. Based on our recent experience of crafting documents grounded in testing, we've begun to consider the possibility of entirely automating document creation, save for the initial stages.

Along with sharing our journey so far, we will also reveal our plans for future test-based automation of documentation within GlueSQL.

Test Codes and Documentation

The GlueSQL project has placed a significant emphasis on writing test codes. This might be a given for a database project; however, the thoroughness of our approach is evident from our line coverage of nearly 99% for core codes. While we devoted considerable effort to creating these test codes, our primary focus has always been on a different aspect: ensuring that anyone can quickly grasp the content of the tests and easily add new ones.

The intent here is to empower newcomers to GlueSQL to understand the functionality of the software solely by examining integration tests, even in the absence of a user manual.

The integration tests for GlueSQL can be found in the test-suite workspace. For example, here's an excerpt of the test code for the INSERT statement:

test_case!(insert, async move {
run!(
"
CREATE TABLE Test (
id INTEGER DEFAULT 1,
num INTEGER NULL,
name TEXT NOT NULL,
);"
);

test! {
name: "basic insert - single item",
sql: "INSERT INTO Test (id, num, name) VALUES (1, 2, 'Hi boo');",
expected: Ok(Payload::Insert(1))
};


test! {
sql: "INSERT INTO Test VALUES(17, 30, 'Sullivan');",
expected: Ok(Payload::Insert(1))
};

test! {
sql: "INSERT INTO Test (num, name) VALUES (28, 'Wazowski');",
expected: Ok(Payload::Insert(1))
};

test! {
sql: "SELECT * FROM Test;",
expected: Ok(select!(
id | num | name;
I64 | I64 | Str;
1 2 "Hi boo".to_owned();
3 9 "Kitty!".to_owned();
2 7 "Monsters".to_owned();
17 30 "Sullivan".to_owned();
1 28 "Wazowski".to_owned()
))
};

// ...
});

Despite being written in Rust, these test cases are designed to be comprehensible, even to those unfamiliar with the language. Each test is a complete scenario from start to finish, and the results of each operation are readily observable.

Given that identifying results from SELECT operations in the form of Rust enums and structs can be challenging, we actively utilized macros such as select! and select_with_null!. We've composed the test cases to demonstrate that the INSERT statement can handle a wide range of cases, including specifying all columns, omitting some, or omitting all.

test! {
sql: "INSERT INTO Test (id, num) VALUES (1, 10);",
expected: Err(InsertError::LackOfRequiredColumn("name".to_owned()).into())
};

The tests also include scenarios for expected faulty inputs, indicating the error returns in these situations.

By organizing the tests in this manner, we aim to make it easy for anyone to read and write tests. Our goal was for these tests to serve as "documentation" for GlueSQL contributors. At the time we were writing these tests, we didn't anticipate that they could actually become documentation themselves. But we've come to realize that they have extraordinary potential.

Leveraging ChatGPT

When we first embarked on writing the User Manual, we were overwhelmed by the sheer volume of content we had to generate. Around the same time, ChatGPT was gaining prominence, and we thought it might be worth trying out, if only to lighten our load slightly.

To our surprise, ChatGPT exceeded our expectations. If the test codes were well written, it was capable of automatically crafting an exceptional document based on them, capturing all essential details.

After several trials and errors, we settled on the following prompt for document generation. While it's still a challenge to use the same prompt for all documentation, we made minor modifications to suit different situations:

I'm creating an SQL database documentation website, and I'd like you to help me with one of the pages that introduces the SQL syntax for GlueSQL.

1. Please provide the response content in the "markdown" format, so I can copy and paste it directly. Keep this constraint in mind while writing.
2. Regardless of the language I use, I need the content written in English.
3. I will provide some test case code written in the Rust language, which contains SQL examples. Please write the documentation based on these examples, but feel free to change the table names, column names, and data types as needed. Don't include any Rust related content or text in the response. all the response code example should be in plain SQL.
4. GlueSQL does not have the VARCHAR type. If you want to use that, please use TEXT instead. You don't need to mention this in the response.
5. Wrap the entire response text using <pre> and </pre> tags so I can copy all the content easily.

Now, I'd like you to write the following request:
SQL Statement - "INSERT"

Here's an example test code you can refer to:

test_case!(insert, async move {
run!(...

Generally, we used the template above, and copied and pasted the test code from our existing test-suite. We leveraged this method to harness our many tests to assist in the creation of the user manual. In the next section, we'll showcase a sample of the documentation generated in this manner. It's quite impressive.

Success Case: Automated User Manual of GlueSQL

Thanks to ChatGPT, the resulting INSERT document page can be viewed at the following link. It's important to note that we used ChatGPT 4 for this task. Version 3.5 wasn't quite up to the task, and using version 4 was the minimum requirement.

https://gluesql.org/docs/dev/sql-syntax/statements/data-manipulation/insert

INSERT Statement

The results were quite impressive. ChatGPT neatly categorized the test cases, explained the syntax, outlined constraints, and provided appropriate examples. It didn't stop there; it also skillfully recognized error test cases and incorporated them into the documentation, as shown below.

INSERT Statement

Isn't it amazing?

Future Plans: Fully Automating Documentation Generation

While the current documentation is far from perfect and there are many aspects that can be improved, we see great potential in this approach. We believe it's entirely possible to automate the process of writing this kind of document, and writing in general.

In the past, documents like user manuals required a great deal of effort to maintain once they were written. If a document contained real code examples, verifying that the code still worked was often a tedious task. With the ability to automatically generate documentation as we have done here, these issues are no longer problematic.

Previously, you would have to write tests and then also document them separately. If you had to support multiple languages, that would be an additional task. With a tool like ChatGPT, you can automate all of this. All a developer has to do is write the tests. This alone can be sufficient. You can generate documents automatically based on the tests. Eventually, we can even support automatically translating these documents into multiple languages.

The GlueSQL project repository is currently hosted on GitHub and makes good use of various GitHub Actions. We envision a GitHub Action that automatically regenerates a document corresponding to a test when a user modifies the test and raises a Pull Request. Another GitHub Action could automatically translate updated documents into supported languages and create new Pull Requests. The possibilities are truly endless.

Not only will this help with document generation, but it will also provide clear guidelines for writing better test code. If we can automatically generate documents based on written tests, the quality of those documents can serve as an indicator of the quality of the tests themselves. This means that a document automation tool can play the role of a good reviewer for tests. It can greatly reduce the time and effort required for painstakingly reviewing the quality of each test. Developers can also write tests without pressure, evaluate their test code by looking at the generated document, and improve it.

Furthermore, multi-language support becomes a breeze. In my personal experience as a software engineer over the past decade, developing various products such as games, web services, and applications, I often needed to support multiple languages. Each time, there was no definite solution. The optimal approach varied depending on the situation, and there were many things to consider when entrusting translations, such as effectively communicating the context of the target service to the translator. Moreover, regularly updating content and having it retranslated into various languages was a very tedious process. While I tried to automate as much as possible by creating various tools, I was never fully satisfied. I believe ChatGPT can completely solve these issues. If there is a need to provide project-specific context, all you need to do is prepare a prompt in advance. Instead of having to rely on and wait for professional translators, we can now entrust this task to ChatGPT, and we only need a few people to review the translated content.

We are nearing a world where documentation is no longer a burden for developers.

Conclusion: The Value of Test-Driven Documentation

The use of ChatGPT to generate documentation has proven a significant step forward in the GlueSQL user manual creation process. Through test-driven documentation, we've managed to automate a substantial part of the manual creation process, saving time and effort, and increasing accuracy.

Moreover, this process has unveiled a new potential for documentation: the possibility of fully automating document generation. We've seen that quality tests can become quality documentation with the help of AI, leading to more efficient workflows and possibly better test code as a result.

The journey doesn't stop here. We envision leveraging this capability further to auto-translate our documents into multiple languages, making our product more accessible to a global audience.

As we progress, we hope that our experience can inspire other developers to explore and embrace the benefits of AI-generated, test-driven documentation. It's not just about saving time—it's about improving the way we work, communicate, and share knowledge.

+ + \ No newline at end of file diff --git a/docs/dev/blog/tags/gluesql/index.html b/docs/dev/blog/tags/gluesql/index.html index eda746f7..c062f78c 100644 --- a/docs/dev/blog/tags/gluesql/index.html +++ b/docs/dev/blog/tags/gluesql/index.html @@ -1,18 +1,18 @@ - + - + One post tagged with "gluesql" | GlueSQL - - - + + +
-

One post tagged with "gluesql"

View All Tags

· 14 min read
Taehoon Moon

Introduction

GlueSQL is a versatile database project designed for exceptional portability across a broad range of environments, from embedded systems and servers to web and mobile platforms. The core goal is to support diverse storage environments and manage various data types with a standard SQL approach.

Imagine handling files like CSV, JSONL, and Parquet, or transforming key-value or NoSQL databases such as RocksDB, Redis, and MongoDB into SQL-supporting databases—all feasible with GlueSQL. It can also operate with storages supported in web browsers.

GlueSQL's essential feature is providing a management layer for these diverse storage scenarios without requiring data migration. The broader aim is to facilitate portability of GlueSQL to any environment supporting read or read-write operations. This extends to APIs like GitHub, or messengers like Discord or Slack.

GlueSQL supports both structured and unstructured data and is written in Rust for compatibility with various environments. While portability is its core value, the emphasis is on creating an intuitive, comfortable development environment for easy custom storage implementation.

Ultimately, GlueSQL aims to significantly reduce the cost, time, and complexity of developing new databases. By leveraging GlueSQL for the parser, planner, and execution layer, developers can focus on creating specific storage implementations, leading to a more convenient query interface like SQL for many environments.

The Problem: Why Reinvent the Database?

Despite the numerous database implementations that currently exist, the emergence of new databases continues. The primary reason behind this trend is our need for databases for a broad spectrum of distinct purposes. For instance, new databases are surfacing that are specifically optimized for Large Language Models (LLMs) like ChatGPT. The range is wide and diverse, encompassing embedded databases, OLAP for data analysis, OLTP databases optimized for online transactions, databases specialized for time-series data processing, and many more.

With such varied requirements, we find ourselves in constant need of fresh databases. However, constructing a database from scratch is a monumental task. It necessitates defining a query interface for handling the database and implementing a corresponding parser. Moreover, a separate execution layer for running operations must be built. Also, the planning layer, which is responsible for devising execution strategies, is a vital aspect of this process. Let's not forget about the critical storage layer that physically reads and stores the data. In a nutshell, there's a daunting amount of work involved in developing a new database.

Given these circumstances, it's understandable why numerous emerging databases resort to high pricing structures—they need immediate revenue to offset continuous development costs.

But the story doesn't end here. Query interfaces like SQL are indeed useful for serious tasks, but they also provide excellent utility for handling simple log files such as CSV, JSONL, Parquet, and even for utilizing REST APIs for various applications. The issue arises when a complex query interface needs to be provided even for these lighter storage requirements—it necessitates a development process almost identical to building a sophisticated database. Implementing an entire parser and execution layer just to add SQL support to an existing service can seem like an excessive burden.

Whether it's a simple storage environment or a serious task, the key lies in the storage layer, which involves the actual reading and storing of data. So, what if developers focused on implementing these storage mechanisms while the remaining parts could be handled using existing libraries? This is the role that GlueSQL aspires to play.

The Vision of GlueSQL

The GlueSQL project aims to offer a unified query interface for various environments. The goal is to allow anyone to port and use SQL and GlueSQL's proprietary query builder, the AST Builder, in any desired environment. This could range from key-value databases, serious NoSQL databases, log files, and even REST API services. Essentially, if a service supports reading or read-writing data, regardless of the data type, it can readily support a complex query interface via GlueSQL.

Presently, the GlueSQL project itself directly supports a few storage types as reference storages. These include in-memory storage for non-persistent data handling, sled storage, which is a key-value database written in Rust, JSON storage for handling JSON and JSONL files, and a storage that ports SQL to the web browser's IndexedDB. While the GlueSQL Team is primarily developing these, the aim is to allow anyone to create such custom storages for a wide array of purposes, thus enabling them to assemble the database of their choosing.

Imagine using GlueSQL's SQL and AST Builder everywhere, with the simple method of swapping out storages to operate in diverse settings. It could significantly reduce software development costs. Developers wouldn't need to learn the different usage methods for each database. Instead, they could focus solely on implementing business logic using the same interface.

Our vision is to reduce database development costs by 10 times, or even more than 20 times. We aim to gather diverse database creators under the GlueSQL banner, making it the go-to solution for cost-effective database development.

Benefits to Database Users: Unifying Query Interfaces, Streamlining Software Development, and Reducing Costs

From the perspective of the users who engage with databases, there has always been the burden of learning different interfaces to interact with each database. The approach required to work with Redis is different from that necessary for MongoDB. Likewise, handling SQL databases necessitates using SQL. Although SQL databases generally use a common SQL, the SQL they support can considerably vary when examined in detail.

Naturally, there are legitimate reasons for such differences. Each database focuses on different areas, and to cater to specialized functionalities, they incorporate dedicated interface mechanisms. However, not all application development needs to utilize these database-specific core special functionalities.

Let's look at a couple of examples:

Suppose you're developing a back-end application that uses MySQL as the database and Redis for caching. Due to the vast differences in handling SQL databases and Redis, you would have to develop using different methods when storing data.

Here's another scenario: +

One post tagged with "gluesql"

View All Tags

· 14 min read
Taehoon Moon

Introduction

GlueSQL is a versatile database project designed for exceptional portability across a broad range of environments, from embedded systems and servers to web and mobile platforms. The core goal is to support diverse storage environments and manage various data types with a standard SQL approach.

Imagine handling files like CSV, JSONL, and Parquet, or transforming key-value or NoSQL databases such as RocksDB, Redis, and MongoDB into SQL-supporting databases—all feasible with GlueSQL. It can also operate with storages supported in web browsers.

GlueSQL's essential feature is providing a management layer for these diverse storage scenarios without requiring data migration. The broader aim is to facilitate portability of GlueSQL to any environment supporting read or read-write operations. This extends to APIs like GitHub, or messengers like Discord or Slack.

GlueSQL supports both structured and unstructured data and is written in Rust for compatibility with various environments. While portability is its core value, the emphasis is on creating an intuitive, comfortable development environment for easy custom storage implementation.

Ultimately, GlueSQL aims to significantly reduce the cost, time, and complexity of developing new databases. By leveraging GlueSQL for the parser, planner, and execution layer, developers can focus on creating specific storage implementations, leading to a more convenient query interface like SQL for many environments.

The Problem: Why Reinvent the Database?

Despite the numerous database implementations that currently exist, the emergence of new databases continues. The primary reason behind this trend is our need for databases for a broad spectrum of distinct purposes. For instance, new databases are surfacing that are specifically optimized for Large Language Models (LLMs) like ChatGPT. The range is wide and diverse, encompassing embedded databases, OLAP for data analysis, OLTP databases optimized for online transactions, databases specialized for time-series data processing, and many more.

With such varied requirements, we find ourselves in constant need of fresh databases. However, constructing a database from scratch is a monumental task. It necessitates defining a query interface for handling the database and implementing a corresponding parser. Moreover, a separate execution layer for running operations must be built. Also, the planning layer, which is responsible for devising execution strategies, is a vital aspect of this process. Let's not forget about the critical storage layer that physically reads and stores the data. In a nutshell, there's a daunting amount of work involved in developing a new database.

Given these circumstances, it's understandable why numerous emerging databases resort to high pricing structures—they need immediate revenue to offset continuous development costs.

But the story doesn't end here. Query interfaces like SQL are indeed useful for serious tasks, but they also provide excellent utility for handling simple log files such as CSV, JSONL, Parquet, and even for utilizing REST APIs for various applications. The issue arises when a complex query interface needs to be provided even for these lighter storage requirements—it necessitates a development process almost identical to building a sophisticated database. Implementing an entire parser and execution layer just to add SQL support to an existing service can seem like an excessive burden.

Whether it's a simple storage environment or a serious task, the key lies in the storage layer, which involves the actual reading and storing of data. So, what if developers focused on implementing these storage mechanisms while the remaining parts could be handled using existing libraries? This is the role that GlueSQL aspires to play.

The Vision of GlueSQL

The GlueSQL project aims to offer a unified query interface for various environments. The goal is to allow anyone to port and use SQL and GlueSQL's proprietary query builder, the AST Builder, in any desired environment. This could range from key-value databases, serious NoSQL databases, log files, and even REST API services. Essentially, if a service supports reading or read-writing data, regardless of the data type, it can readily support a complex query interface via GlueSQL.

Presently, the GlueSQL project itself directly supports a few storage types as reference storages. These include in-memory storage for non-persistent data handling, sled storage, which is a key-value database written in Rust, JSON storage for handling JSON and JSONL files, and a storage that ports SQL to the web browser's IndexedDB. While the GlueSQL Team is primarily developing these, the aim is to allow anyone to create such custom storages for a wide array of purposes, thus enabling them to assemble the database of their choosing.

Imagine using GlueSQL's SQL and AST Builder everywhere, with the simple method of swapping out storages to operate in diverse settings. It could significantly reduce software development costs. Developers wouldn't need to learn the different usage methods for each database. Instead, they could focus solely on implementing business logic using the same interface.

Our vision is to reduce database development costs by 10 times, or even more than 20 times. We aim to gather diverse database creators under the GlueSQL banner, making it the go-to solution for cost-effective database development.

Benefits to Database Users: Unifying Query Interfaces, Streamlining Software Development, and Reducing Costs

From the perspective of the users who engage with databases, there has always been the burden of learning different interfaces to interact with each database. The approach required to work with Redis is different from that necessary for MongoDB. Likewise, handling SQL databases necessitates using SQL. Although SQL databases generally use a common SQL, the SQL they support can considerably vary when examined in detail.

Naturally, there are legitimate reasons for such differences. Each database focuses on different areas, and to cater to specialized functionalities, they incorporate dedicated interface mechanisms. However, not all application development needs to utilize these database-specific core special functionalities.

Let's look at a couple of examples:

Suppose you're developing a back-end application that uses MySQL as the database and Redis for caching. Due to the vast differences in handling SQL databases and Redis, you would have to develop using different methods when storing data.

Here's another scenario: Imagine you're implementing a data migration pipeline between various databases and log files. Let's say you're transferring Parquet to Redis or MongoDB. In this case, you would need to convert data using different methods for each, all of which would be a cumbersome process.

In both of the above examples, GlueSQL can directly address and solve the issues. It offers the convenience of a uniform query interface to deal with these matters. In certain scenarios, even the construction of a data pipeline can potentially be solved with a single SQL query, thanks to GlueSQL.

Benefits to Database Developers: Drastically Lowering Development Costs and Simplifying the Creation of Purpose-Built Databases

If you want to support SQL in the desired environment, using GlueSQL essentially requires you to implement an interface for Storage. There's no need to support all functionalities from the beginning. You can start lightly, choosing and implementing storage features suitable for the environment you want to create. To facilitate this, GlueSQL also provides a library in the form of a test suite to easily validate the storage you've implemented.

Lowering development costs in this way will enable a broader range of developers to support the GlueSQL query interface. As more developers join, a significant synergy can be generated. Designing a query interface from scratch involves a great deal of work, including planning and supporting the interface for different target programming languages.

However, despite all this hard work, it is not easy to attract database users accustomed to different methods.

Consider that the SQL and AST Builder provided by GlueSQL are already securing numerous users. This eliminates the need for efforts to promote a newly planned query interface. Over the years, many new databases have emphasized compatibility with PostgreSQL or MySQL for similar reasons. As GlueSQL places a strong emphasis on portability in its query interface planning, it allows for more flexible configuration according to the desired situation. Through the AST Builder, it also eliminates the cost of porting to different languages.

For many database developers, using GlueSQL can be an optimal choice, as it can save costs and quickly secure users.

Let me mention one more thing: what's convenient for humans... could be applied to AI as well. Rather than making AI write automation code using different databases, providing a common query interface can be much more efficient.

The Future with GlueSQL

GlueSQL has been and will continue to improve and develop new features to enable portability in various environments. Thanks to the schemaless data support added last year, it is now possible to handle both structured data with schema and unstructured data like JSON simultaneously. This has significantly increased the range of storage environments that can be supported.

One of the key features added last year was the AST Builder. This feature allowed us to escape the confines of SQL and provide an interface for comfortably handling data in the programming languages used for development.

Of course, improving existing features is extremely important, and there are many new features to be added. As a major development plan this year, we aim to develop features to effectively attach GlueSQL to NoSQL databases with their own planners and execution layers. The GlueSQL query planner, currently at a basic level, will see significant changes this year. With the expansion of this planner, not only NoSQL databases but also other SQL databases could be supported without sacrificing performance using GlueSQL.

The synergy that arises from the combination of different databases is a significant bonus in this process.

The Journey of the GlueSQL Team

The GlueSQL project was first conceived in the fall of 2019, and since then we have been developing it continuously. Personally, I have created various products in a variety of environments, including game development, backend server, and frontend development over the past decade. The experience gained through this process was a major motivation to start the GlueSQL project.

To put it grandly, the inconveniences felt while using different databases in various environments were a major motivation, wouldn't you say?

The start was actually a bit simple. Around 2019, I was mainly doing web front-end development. However, the lack of a structured database for state management and internal data processing made it very uncomfortable, especially since I couldn't use SQL databases and the like. So I started to lightly create an SQL database that could run on a web browser. Also, I wanted to use Rust, but after failing to introduce it at the company I was working for at the time, I decided to use it in my own project.

But as I started developing, my dreams grew significantly. Beyond a SQL database that simply operates on a web browser, I started envisioning a database that fits the name "Glue", one that can easily be ported to various environments, and I continue that journey to this day.

Whether I took the database project too lightly, or because the features I wanted kept increasing, the content to be developed kept expanding. As a result, I ended up investing full time in the GlueSQL project development for over three years. For a year in between, I even juggled full-time software engineering work alongside GlueSQL development. Currently, I'm back to developing the GlueSQL project full time, alongside various part-time contributors.

Now, we're getting very close to the starting point of the picture I wanted to create through GlueSQL, and thankfully, with contributors joining me, I am not alone.

The Sustainability and Business Aspect of GlueSQL

I believe that what we create through GlueSQL will make a great contribution to the world and make many software engineers happy. This gives me immense strength to continue developing even in difficult situations. However, we cannot accomplish everything with pure passion alone. As much as the GlueSQL project can make a significant contribution, I also see it as holding great business value.

The business strategy of GlueSQL may be somewhat different from other databases. We distribute the project itself as open source under the Apache-2.0 license, so that anyone can use it fully, and we do not consider pricing methods such as restricting features to the storages we support. In fact, if there is any player who can do it better, there's no way to prevent them from taking the GlueSQL project and making it their own.

But we believe that GlueSQL has great potential in this regard. Anyone can participate and they are free to distribute their own storage in the way they want, whether it's open source, private, or commercial. This eliminates the need to create something to replace the GlueSQL project. We aim to prevent the need to recreate the wheel that we provide using GlueSQL.

Moreover, our GlueSQL team seeks to continually expand our group of developers and companies working with us. During this development process, while they can certainly implement everything on their own, there is also no reason not to collaborate with our GlueSQL Team, especially for databases like NoSQL that have their own planners and execution layers. If you have a REST API and want to enhance convenience through SQL support, you can do it yourself or you can collaborate with us.

In addition, for some storages, we can also participate as players in the same position as other custom storage developers. We plan to expand the GlueSQL ecosystem in various ways, such as technical support and storage development.

We are finally ready to provide GlueSQL to users at the production level. We are accelerating the development of GlueSQL. If you are a company interested in storage development like SQL support, or if you resonate with our vision and want to join us, please contact us at taehoon@gluesql.com.

Conclusion

The continued emergence of new databases is driven by the demand for diverse and specialized databases, such as those optimized for Large Language Models (LLMs) and databases catering to unique requirements, like embedded databases, OLAP, OLTP, and time-series data processing. However, developing a new database from scratch is a significant undertaking, requiring extensive work, which often results in high costs.

GlueSQL presents a solution to this challenge by providing a unified query interface that can be ported across various environments, from key-value databases, NoSQL databases, log files, to REST APIs. It allows anyone to create custom storages, reducing the need for developers to build entirely new databases and to learn different usage methods for each database. Instead, they can focus on implementing their business logic using the same interface.

From a user perspective, GlueSQL offers the convenience of a unified query interface, easing the burden of learning different interfaces for each database. This simplification of interface use can also extend to AI, potentially enhancing the efficiency of AI automation.

GlueSQL's development plan includes significant enhancements to its query planner and aims to enable effective attachment of GlueSQL to NoSQL databases. The synergy of combining different databases is a valuable bonus in this process.

Since its inception in the fall of 2019, the GlueSQL team has continuously developed the project, driven by the desire to mitigate the inconveniences encountered while using different databases in various environments. The journey has been a rewarding one, with the GlueSQL project now at a point where it closely resembles the envisioned product.

GlueSQL, distributed under the Apache-2.0 license, is free for anyone to use and adapt. While the GlueSQL team welcomes collaboration with other developers and companies, they also see significant potential for the project as a business venture. The team is working to expand the GlueSQL ecosystem through a variety of initiatives, including technical support and storage development.

With GlueSQL now sufficiently prepared for practical applications, the team invites companies interested in storage development or those who share their vision to join them in their journey of revolutionizing database development.

- - + + \ No newline at end of file diff --git a/docs/dev/blog/tags/index.html b/docs/dev/blog/tags/index.html index 2270a274..a4896aff 100644 --- a/docs/dev/blog/tags/index.html +++ b/docs/dev/blog/tags/index.html @@ -1,17 +1,17 @@ - + - + Tags | GlueSQL - - - + + + - - + + \ No newline at end of file diff --git a/docs/dev/blog/tags/nosql/index.html b/docs/dev/blog/tags/nosql/index.html index c440d452..e7225e9f 100644 --- a/docs/dev/blog/tags/nosql/index.html +++ b/docs/dev/blog/tags/nosql/index.html @@ -1,16 +1,16 @@ - + - + One post tagged with "nosql" | GlueSQL - - - + + +
-

One post tagged with "nosql"

View All Tags

· 11 min read
Taehoon Moon

Introduction

The divide between SQL and NoSQL databases has often presented challenges in database management. GlueSQL, a unique database maker library, aims to blur this boundary, providing a versatile tool for handling these two distinct types of databases.

In this article, we explore how GlueSQL navigates the features of SQL and NoSQL databases, offering an integrated solution that promotes flexibility and efficiency. With its ability to unify disparate database types, GlueSQL heralds a new age of adaptable database creation and management.

The Interface Perspective: SQL & AST Builder

When we talk about SQL databases, it's almost a given that they support SQL - the standard query language. Although there are slight variations between databases, the convenience of using a similar SQL language across multiple databases cannot be overstated. However, from a software engineer's perspective, there's room for improvement. In most software development scenarios, a specific programming language is used. SQL is a separate language, which can cause friction when integrating it into your software. As a result, rather than using raw SQL, many developers employ query builders or ORMs to manipulate SQL conveniently using their preferred programming language. Although it's not efficient to generate SQL using a query builder and then parse it again in the database, it's a practical and effective choice.

On the other hand, NoSQL databases offer different mechanisms. Some of them have their own language similar to SQL, but most provide an interface library developed specifically for each programming language. While SQL databases rely on external query builder libraries to provide an interface for each programming language, NoSQL databases mostly develop and offer these libraries themselves. If we discount the convenience of SQL language, this is one of the major factors that make NoSQL databases more comfortable to use. Since query builder libraries supporting SQL databases often cater to multiple SQL databases, they are limited in fully supporting unique features of each database. NoSQL databases, on the other hand, can freely manage their interface libraries without these restrictions.

Providing a query interface for each programming language is not a fundamental difference between SQL and NoSQL, but we generally accept it implicitly.

Let's see what happens if we break down this boundary, using GlueSQL as an example. As you can see from the SQL postfix, GlueSQL supports SQL and can be classified as an SQL database.

CREATE TABLE Glue (id INTEGER, name TEXT);

INSERT INTO Glue VALUES (1, "hello"), (2, "gluesql");

SELECT * FROM Glue WHERE id = 1;

However, GlueSQL also supports its own query builder, like a NoSQL database. +

One post tagged with "nosql"

View All Tags

· 11 min read
Taehoon Moon

Introduction

The divide between SQL and NoSQL databases has often presented challenges in database management. GlueSQL, a unique database maker library, aims to blur this boundary, providing a versatile tool for handling these two distinct types of databases.

In this article, we explore how GlueSQL navigates the features of SQL and NoSQL databases, offering an integrated solution that promotes flexibility and efficiency. With its ability to unify disparate database types, GlueSQL heralds a new age of adaptable database creation and management.

The Interface Perspective: SQL & AST Builder

When we talk about SQL databases, it's almost a given that they support SQL - the standard query language. Although there are slight variations between databases, the convenience of using a similar SQL language across multiple databases cannot be overstated. However, from a software engineer's perspective, there's room for improvement. In most software development scenarios, a specific programming language is used. SQL is a separate language, which can cause friction when integrating it into your software. As a result, rather than using raw SQL, many developers employ query builders or ORMs to manipulate SQL conveniently using their preferred programming language. Although it's not efficient to generate SQL using a query builder and then parse it again in the database, it's a practical and effective choice.

On the other hand, NoSQL databases offer different mechanisms. Some of them have their own language similar to SQL, but most provide an interface library developed specifically for each programming language. While SQL databases rely on external query builder libraries to provide an interface for each programming language, NoSQL databases mostly develop and offer these libraries themselves. If we discount the convenience of SQL language, this is one of the major factors that make NoSQL databases more comfortable to use. Since query builder libraries supporting SQL databases often cater to multiple SQL databases, they are limited in fully supporting unique features of each database. NoSQL databases, on the other hand, can freely manage their interface libraries without these restrictions.

Providing a query interface for each programming language is not a fundamental difference between SQL and NoSQL, but we generally accept it implicitly.

Let's see what happens if we break down this boundary, using GlueSQL as an example. As you can see from the SQL postfix, GlueSQL supports SQL and can be classified as an SQL database.

CREATE TABLE Glue (id INTEGER, name TEXT);

INSERT INTO Glue VALUES (1, "hello"), (2, "gluesql");

SELECT * FROM Glue WHERE id = 1;

However, GlueSQL also supports its own query builder, like a NoSQL database. (Currently, only Rust is supported, but we're working on adding support for other languages.)

table("Glue")
.create_table()
.add_column("id INTEGER")
.add_column("name TEXT")
.execute(glue)

table("Glue")
.insert()
.values(vec![
vec![num(1), text("hello")],
vec![num(2), text("gluesql")],
])
.execute(glue)
.await;

table("Glue")
.select()
.filter(col("id").eq(1))
.execute(glue)
.await;

Let's reconsider the implicit distinction between SQL and NoSQL. GlueSQL indeed supports SQL, but it also officially develops and offers its own query builder. This query builder is not a secondary tool for SQL. While most SQL query builder libraries ultimately generate SQL strings, GlueSQL's builder directly creates an AST (Abstract Structure Tree) that is used for execution within GlueSQL. Hence, we call it the AST Builder. This means SQL and the AST Builder are two equally supported interfaces in GlueSQL.

This also offers an additional advantage:

table("Glue")
.select()
// 1.
.filter(col("id").eq(1))
// 2.
.filter("id = 1")
.execute(glue)
.await;

Because GlueSQL already supports SQL, not only can you use the custom interface in the AST Builder, but you can also use familiar SQL syntax in part. Whether you use col("id").eq(1) or "id = 1", you can use it in the way you prefer. The AST Builder interface, although initially unfamiliar, allows a gradual migration similar to writing SQL for your convenience.

Thus, we've dismantled one of the implicit distinctions between SQL and NoSQL. However, it's more of an implicit differentiation than a fundamental one. There are more significant design differences that we'll explore next.

Structured & Unstructured Data

In this section, we'll discuss how SQL and NoSQL handle data. SQL generally deals with structured data, and recently, it's been made to support semi-structured data as well. On the other hand, NoSQL supports schemaless, unstructured data. Then, we'll explain in detail how GlueSQL handles these two types of data. The last part of this section will provide a segue into the next section where we'll discuss the decomposition of database functions.

When talking about SQL databases, one aspect is usually considered together: SQL databases have a defined schema.

CREATE TABLE Foo (
id INTEGER,
name TEXT,
rate FLOAT NULL
);

However, these days, SQL databases tend to support semi-structured data types, such as LIST or JSON. But, supporting completely schemaless, unstructured data is a different matter. SQL databases typically require a minimum schema.

What about NoSQL databases? As NoSQL databases vary significantly, we can't make definitive statements. But let's consider a typical document database like MongoDB. Unlike SQL databases, it doesn't enforce a schema. Essentially, you can insert any form of data directly. Often, NoSQL databases support schemaless data, but they lack features that enforce a schema like SQL. They generally support structure via validation methods, rather than structured access.

Is there no choice but to distinguish between structured data and unstructured, schemaless data so clearly? GlueSQL is being developed with the goal of being adaptable in various environments. Being forced to choose regarding this schema constraint was quite inconvenient. We started pondering if we couldn't benefit from both aspects - supporting both schema and schemaless data simultaneously, and we eventually found the answer. Let's look at how GlueSQL currently solves this issue through familiar SQL examples.

CREATE TABLE Names (id INTEGER, name TEXT);
INSERT INTO Names VALUES (1, 'glue'), (2, 'sql');

You can create a regular table with a schema like this. But GlueSQL's choice for creating a schemaless table is as follows:

CREATE TABLE Logs;
INSERT INTO Logs VALUES
('{ "id": 1, "value": 30 }'),
('{ "id": 2, "rate": 3.0, "list": [1, 2, 3] }'),
('{ "id": 3, "rate": 5.0, "value": 100 }');

It creates a table without column definitions! If you do this, GlueSQL recognizes the table as schemaless and processes it internally.

SELECT id, rate, list[0] FROM Logs WHERE id = 2;

Although the way to create the table was a bit special, using it isn't much different from the regular SQL SELECT statement. Not only can you differentiate between schema and schemaless when creating tables, but you can also use them interchangeably!

SELECT * FROM Names JOIN Logs ON Names.id = Logs.id;
/*
| id | list | name | rate | value |
|----|---------|------|------|-------|
| 1 | | glue | | 30 |
| 2 |[1, 2, 3]| sql | 3 | |
*/

Here's an example of querying data by INNER JOINing the Names table, which has a schema, and the Logs table, which is schemaless. GlueSQL has resolved this problem by allowing the internal execution layer to handle both vector-type data, for cases where each row has a defined schema, and map-type data for schemaless cases.

Thanks to this, the variety of storage that can be supported through GlueSQL has expanded significantly. If there were previously limitations to supporting NoSQL databases that support schemaless data, that is no longer the case. The reference storage where you can directly experience this schemaless data support is JSON Storage. It offers features that allow you to deal directly with unstructured data like JSON using GlueSQL.

If GlueSQL starts from the perspective of an SQL database and expands, by providing the AST Builder directly, it once blurs the boundary, and by supporting unstructured data simultaneously, it knocks down the boundary once more. How do you like it?

Decomposing Database Functionality: Breaking Down SQL and NoSQL Features

The distinction between SQL and NoSQL is not just about whether they support unstructured data. Of course, there are examples like unstructured data, which is mainly supported only in NoSQL, but in many cases, SQL databases tend to support more diverse and complex queries. NoSQL often gains other advantages in exchange for reducing the range of query support provided by SQL databases.

GlueSQL is ambitious. It has devised a rather interesting method to support all of this through SQL and the AST Builder, with the same interface. When we usually say SQL database, it implicitly assumes that a lot of features have been fully implemented. Create tables by specifying a schema, modify schemas with "alter table", support both clustered and non-clustered indexes, and support transactions. And there's so much more. But the functionality that is naturally supported in SQL databases may not be natural in other environments.

Let's think about JSON Storage. GlueSQL's JSON Storage allows you to handle JSON, JSONL files using SQL and the AST Builder. This JSON Storage does not support atomic operations or transactions. Of course, it would be great if it did, but implementing and executing them would be a significant performance burden. In most cases, when you want to simply browse and handle JSONL files, the overhead caused by transactions can be an unnecessary burden. In this case, you want to handle JSON, JSONL files using SQL, but you don't necessarily need transactions.

To meet the requirements of these diverse environments, GlueSQL has separated the functionality of what we usually call an SQL database into multiple independent interfaces. Store, StoreMut, AlterTable, Transaction, .. These are just a few of the various storage interfaces that GlueSQL currently supports. @@ -23,7 +23,7 @@ The Transaction interface works the same way. The interesting part is that, except for Store and StoreMut, all other storage interfaces can be implemented independently. GlueSQL allows you to choose and implement only the features you need. And it's not just about providing interfaces. It also provides integration tests suitable for each situation to verify what you have implemented. You just need to implement the interface and import the corresponding test case for verification.

In addition to supporting both structured and unstructured data simultaneously, GlueSQL provides the ability to divide the functionality of a database into multiple independent features and selectively implement them. This allows GlueSQL to be ported to a wide variety of environments without any burden.

Conclusion

GlueSQL, while serving as a database that provides its own reference storage, is fundamentally a library designed to simplify the creation of databases. One of the substantial challenges GlueSQL had to overcome in order to support a diverse array of environments was to address the distinctive features that separate conventional SQL databases from NoSQL databases. GlueSQL achieved this through several innovative approaches, managing to support both categories simultaneously despite their significantly different characteristics.

It offers support for SQL alongside an AST Builder, and accommodates both structured and unstructured data. Additionally, it decomposes database functionalities into multiple independent features, allowing each environment to selectively implement the functionalities it requires.

These unique attributes enable GlueSQL to live up to its 'Glue' prefix by facilitating effortless porting across various environments. While we have been developing it for several years, there is still much ground to cover. However, the fact that we are now able to introduce it publicly attests to our successful technological validation and completion of a demonstrable level of implementation.

Through GlueSQL, we hope to provide developers with a unified query interface that can be customized according to their needs, thereby enabling them to produce efficient products more effortlessly. There's a promising future ahead for GlueSQL, and we look forward to its contributions to the technology community.

- - + + \ No newline at end of file diff --git a/docs/dev/blog/tags/proposal/index.html b/docs/dev/blog/tags/proposal/index.html index 9b1930b4..bdcc7109 100644 --- a/docs/dev/blog/tags/proposal/index.html +++ b/docs/dev/blog/tags/proposal/index.html @@ -1,18 +1,18 @@ - + - + One post tagged with "proposal" | GlueSQL - - - + + +
-

One post tagged with "proposal"

View All Tags

· 14 min read
Taehoon Moon

Introduction

GlueSQL is a versatile database project designed for exceptional portability across a broad range of environments, from embedded systems and servers to web and mobile platforms. The core goal is to support diverse storage environments and manage various data types with a standard SQL approach.

Imagine handling files like CSV, JSONL, and Parquet, or transforming key-value or NoSQL databases such as RocksDB, Redis, and MongoDB into SQL-supporting databases—all feasible with GlueSQL. It can also operate with storages supported in web browsers.

GlueSQL's essential feature is providing a management layer for these diverse storage scenarios without requiring data migration. The broader aim is to facilitate portability of GlueSQL to any environment supporting read or read-write operations. This extends to APIs like GitHub, or messengers like Discord or Slack.

GlueSQL supports both structured and unstructured data and is written in Rust for compatibility with various environments. While portability is its core value, the emphasis is on creating an intuitive, comfortable development environment for easy custom storage implementation.

Ultimately, GlueSQL aims to significantly reduce the cost, time, and complexity of developing new databases. By leveraging GlueSQL for the parser, planner, and execution layer, developers can focus on creating specific storage implementations, leading to a more convenient query interface like SQL for many environments.

The Problem: Why Reinvent the Database?

Despite the numerous database implementations that currently exist, the emergence of new databases continues. The primary reason behind this trend is our need for databases for a broad spectrum of distinct purposes. For instance, new databases are surfacing that are specifically optimized for Large Language Models (LLMs) like ChatGPT. The range is wide and diverse, encompassing embedded databases, OLAP for data analysis, OLTP databases optimized for online transactions, databases specialized for time-series data processing, and many more.

With such varied requirements, we find ourselves in constant need of fresh databases. However, constructing a database from scratch is a monumental task. It necessitates defining a query interface for handling the database and implementing a corresponding parser. Moreover, a separate execution layer for running operations must be built. Also, the planning layer, which is responsible for devising execution strategies, is a vital aspect of this process. Let's not forget about the critical storage layer that physically reads and stores the data. In a nutshell, there's a daunting amount of work involved in developing a new database.

Given these circumstances, it's understandable why numerous emerging databases resort to high pricing structures—they need immediate revenue to offset continuous development costs.

But the story doesn't end here. Query interfaces like SQL are indeed useful for serious tasks, but they also provide excellent utility for handling simple log files such as CSV, JSONL, Parquet, and even for utilizing REST APIs for various applications. The issue arises when a complex query interface needs to be provided even for these lighter storage requirements—it necessitates a development process almost identical to building a sophisticated database. Implementing an entire parser and execution layer just to add SQL support to an existing service can seem like an excessive burden.

Whether it's a simple storage environment or a serious task, the key lies in the storage layer, which involves the actual reading and storing of data. So, what if developers focused on implementing these storage mechanisms while the remaining parts could be handled using existing libraries? This is the role that GlueSQL aspires to play.

The Vision of GlueSQL

The GlueSQL project aims to offer a unified query interface for various environments. The goal is to allow anyone to port and use SQL and GlueSQL's proprietary query builder, the AST Builder, in any desired environment. This could range from key-value databases, serious NoSQL databases, log files, and even REST API services. Essentially, if a service supports reading or read-writing data, regardless of the data type, it can readily support a complex query interface via GlueSQL.

Presently, the GlueSQL project itself directly supports a few storage types as reference storages. These include in-memory storage for non-persistent data handling, sled storage, which is a key-value database written in Rust, JSON storage for handling JSON and JSONL files, and a storage that ports SQL to the web browser's IndexedDB. While the GlueSQL Team is primarily developing these, the aim is to allow anyone to create such custom storages for a wide array of purposes, thus enabling them to assemble the database of their choosing.

Imagine using GlueSQL's SQL and AST Builder everywhere, with the simple method of swapping out storages to operate in diverse settings. It could significantly reduce software development costs. Developers wouldn't need to learn the different usage methods for each database. Instead, they could focus solely on implementing business logic using the same interface.

Our vision is to reduce database development costs by 10 times, or even more than 20 times. We aim to gather diverse database creators under the GlueSQL banner, making it the go-to solution for cost-effective database development.

Benefits to Database Users: Unifying Query Interfaces, Streamlining Software Development, and Reducing Costs

From the perspective of the users who engage with databases, there has always been the burden of learning different interfaces to interact with each database. The approach required to work with Redis is different from that necessary for MongoDB. Likewise, handling SQL databases necessitates using SQL. Although SQL databases generally use a common SQL, the SQL they support can considerably vary when examined in detail.

Naturally, there are legitimate reasons for such differences. Each database focuses on different areas, and to cater to specialized functionalities, they incorporate dedicated interface mechanisms. However, not all application development needs to utilize these database-specific core special functionalities.

Let's look at a couple of examples:

Suppose you're developing a back-end application that uses MySQL as the database and Redis for caching. Due to the vast differences in handling SQL databases and Redis, you would have to develop using different methods when storing data.

Here's another scenario: +

One post tagged with "proposal"

View All Tags

· 14 min read
Taehoon Moon

Introduction

GlueSQL is a versatile database project designed for exceptional portability across a broad range of environments, from embedded systems and servers to web and mobile platforms. The core goal is to support diverse storage environments and manage various data types with a standard SQL approach.

Imagine handling files like CSV, JSONL, and Parquet, or transforming key-value or NoSQL databases such as RocksDB, Redis, and MongoDB into SQL-supporting databases—all feasible with GlueSQL. It can also operate with storages supported in web browsers.

GlueSQL's essential feature is providing a management layer for these diverse storage scenarios without requiring data migration. The broader aim is to facilitate portability of GlueSQL to any environment supporting read or read-write operations. This extends to APIs like GitHub, or messengers like Discord or Slack.

GlueSQL supports both structured and unstructured data and is written in Rust for compatibility with various environments. While portability is its core value, the emphasis is on creating an intuitive, comfortable development environment for easy custom storage implementation.

Ultimately, GlueSQL aims to significantly reduce the cost, time, and complexity of developing new databases. By leveraging GlueSQL for the parser, planner, and execution layer, developers can focus on creating specific storage implementations, leading to a more convenient query interface like SQL for many environments.

The Problem: Why Reinvent the Database?

Despite the numerous database implementations that currently exist, the emergence of new databases continues. The primary reason behind this trend is our need for databases for a broad spectrum of distinct purposes. For instance, new databases are surfacing that are specifically optimized for Large Language Models (LLMs) like ChatGPT. The range is wide and diverse, encompassing embedded databases, OLAP for data analysis, OLTP databases optimized for online transactions, databases specialized for time-series data processing, and many more.

With such varied requirements, we find ourselves in constant need of fresh databases. However, constructing a database from scratch is a monumental task. It necessitates defining a query interface for handling the database and implementing a corresponding parser. Moreover, a separate execution layer for running operations must be built. Also, the planning layer, which is responsible for devising execution strategies, is a vital aspect of this process. Let's not forget about the critical storage layer that physically reads and stores the data. In a nutshell, there's a daunting amount of work involved in developing a new database.

Given these circumstances, it's understandable why numerous emerging databases resort to high pricing structures—they need immediate revenue to offset continuous development costs.

But the story doesn't end here. Query interfaces like SQL are indeed useful for serious tasks, but they also provide excellent utility for handling simple log files such as CSV, JSONL, Parquet, and even for utilizing REST APIs for various applications. The issue arises when a complex query interface needs to be provided even for these lighter storage requirements—it necessitates a development process almost identical to building a sophisticated database. Implementing an entire parser and execution layer just to add SQL support to an existing service can seem like an excessive burden.

Whether it's a simple storage environment or a serious task, the key lies in the storage layer, which involves the actual reading and storing of data. So, what if developers focused on implementing these storage mechanisms while the remaining parts could be handled using existing libraries? This is the role that GlueSQL aspires to play.

The Vision of GlueSQL

The GlueSQL project aims to offer a unified query interface for various environments. The goal is to allow anyone to port and use SQL and GlueSQL's proprietary query builder, the AST Builder, in any desired environment. This could range from key-value databases, serious NoSQL databases, log files, and even REST API services. Essentially, if a service supports reading or read-writing data, regardless of the data type, it can readily support a complex query interface via GlueSQL.

Presently, the GlueSQL project itself directly supports a few storage types as reference storages. These include in-memory storage for non-persistent data handling, sled storage, which is a key-value database written in Rust, JSON storage for handling JSON and JSONL files, and a storage that ports SQL to the web browser's IndexedDB. While the GlueSQL Team is primarily developing these, the aim is to allow anyone to create such custom storages for a wide array of purposes, thus enabling them to assemble the database of their choosing.

Imagine using GlueSQL's SQL and AST Builder everywhere, with the simple method of swapping out storages to operate in diverse settings. It could significantly reduce software development costs. Developers wouldn't need to learn the different usage methods for each database. Instead, they could focus solely on implementing business logic using the same interface.

Our vision is to reduce database development costs by 10 times, or even more than 20 times. We aim to gather diverse database creators under the GlueSQL banner, making it the go-to solution for cost-effective database development.

Benefits to Database Users: Unifying Query Interfaces, Streamlining Software Development, and Reducing Costs

From the perspective of the users who engage with databases, there has always been the burden of learning different interfaces to interact with each database. The approach required to work with Redis is different from that necessary for MongoDB. Likewise, handling SQL databases necessitates using SQL. Although SQL databases generally use a common SQL, the SQL they support can considerably vary when examined in detail.

Naturally, there are legitimate reasons for such differences. Each database focuses on different areas, and to cater to specialized functionalities, they incorporate dedicated interface mechanisms. However, not all application development needs to utilize these database-specific core special functionalities.

Let's look at a couple of examples:

Suppose you're developing a back-end application that uses MySQL as the database and Redis for caching. Due to the vast differences in handling SQL databases and Redis, you would have to develop using different methods when storing data.

Here's another scenario: Imagine you're implementing a data migration pipeline between various databases and log files. Let's say you're transferring Parquet to Redis or MongoDB. In this case, you would need to convert data using different methods for each, all of which would be a cumbersome process.

In both of the above examples, GlueSQL can directly address and solve the issues. It offers the convenience of a uniform query interface to deal with these matters. In certain scenarios, even the construction of a data pipeline can potentially be solved with a single SQL query, thanks to GlueSQL.

Benefits to Database Developers: Drastically Lowering Development Costs and Simplifying the Creation of Purpose-Built Databases

If you want to support SQL in the desired environment, using GlueSQL essentially requires you to implement an interface for Storage. There's no need to support all functionalities from the beginning. You can start lightly, choosing and implementing storage features suitable for the environment you want to create. To facilitate this, GlueSQL also provides a library in the form of a test suite to easily validate the storage you've implemented.

Lowering development costs in this way will enable a broader range of developers to support the GlueSQL query interface. As more developers join, a significant synergy can be generated. Designing a query interface from scratch involves a great deal of work, including planning and supporting the interface for different target programming languages.

However, despite all this hard work, it is not easy to attract database users accustomed to different methods.

Consider that the SQL and AST Builder provided by GlueSQL are already securing numerous users. This eliminates the need for efforts to promote a newly planned query interface. Over the years, many new databases have emphasized compatibility with PostgreSQL or MySQL for similar reasons. As GlueSQL places a strong emphasis on portability in its query interface planning, it allows for more flexible configuration according to the desired situation. Through the AST Builder, it also eliminates the cost of porting to different languages.

For many database developers, using GlueSQL can be an optimal choice, as it can save costs and quickly secure users.

Let me mention one more thing: what's convenient for humans... could be applied to AI as well. Rather than making AI write automation code using different databases, providing a common query interface can be much more efficient.

The Future with GlueSQL

GlueSQL has been and will continue to improve and develop new features to enable portability in various environments. Thanks to the schemaless data support added last year, it is now possible to handle both structured data with schema and unstructured data like JSON simultaneously. This has significantly increased the range of storage environments that can be supported.

One of the key features added last year was the AST Builder. This feature allowed us to escape the confines of SQL and provide an interface for comfortably handling data in the programming languages used for development.

Of course, improving existing features is extremely important, and there are many new features to be added. As a major development plan this year, we aim to develop features to effectively attach GlueSQL to NoSQL databases with their own planners and execution layers. The GlueSQL query planner, currently at a basic level, will see significant changes this year. With the expansion of this planner, not only NoSQL databases but also other SQL databases could be supported without sacrificing performance using GlueSQL.

The synergy that arises from the combination of different databases is a significant bonus in this process.

The Journey of the GlueSQL Team

The GlueSQL project was first conceived in the fall of 2019, and since then we have been developing it continuously. Personally, I have created various products in a variety of environments, including game development, backend server, and frontend development over the past decade. The experience gained through this process was a major motivation to start the GlueSQL project.

To put it grandly, the inconveniences felt while using different databases in various environments were a major motivation, wouldn't you say?

The start was actually a bit simple. Around 2019, I was mainly doing web front-end development. However, the lack of a structured database for state management and internal data processing made it very uncomfortable, especially since I couldn't use SQL databases and the like. So I started to lightly create an SQL database that could run on a web browser. Also, I wanted to use Rust, but after failing to introduce it at the company I was working for at the time, I decided to use it in my own project.

But as I started developing, my dreams grew significantly. Beyond a SQL database that simply operates on a web browser, I started envisioning a database that fits the name "Glue", one that can easily be ported to various environments, and I continue that journey to this day.

Whether I took the database project too lightly, or because the features I wanted kept increasing, the content to be developed kept expanding. As a result, I ended up investing full time in the GlueSQL project development for over three years. For a year in between, I even juggled full-time software engineering work alongside GlueSQL development. Currently, I'm back to developing the GlueSQL project full time, alongside various part-time contributors.

Now, we're getting very close to the starting point of the picture I wanted to create through GlueSQL, and thankfully, with contributors joining me, I am not alone.

The Sustainability and Business Aspect of GlueSQL

I believe that what we create through GlueSQL will make a great contribution to the world and make many software engineers happy. This gives me immense strength to continue developing even in difficult situations. However, we cannot accomplish everything with pure passion alone. As much as the GlueSQL project can make a significant contribution, I also see it as holding great business value.

The business strategy of GlueSQL may be somewhat different from other databases. We distribute the project itself as open source under the Apache-2.0 license, so that anyone can use it fully, and we do not consider pricing methods such as restricting features to the storages we support. In fact, if there is any player who can do it better, there's no way to prevent them from taking the GlueSQL project and making it their own.

But we believe that GlueSQL has great potential in this regard. Anyone can participate and they are free to distribute their own storage in the way they want, whether it's open source, private, or commercial. This eliminates the need to create something to replace the GlueSQL project. We aim to prevent the need to recreate the wheel that we provide using GlueSQL.

Moreover, our GlueSQL team seeks to continually expand our group of developers and companies working with us. During this development process, while they can certainly implement everything on their own, there is also no reason not to collaborate with our GlueSQL Team, especially for databases like NoSQL that have their own planners and execution layers. If you have a REST API and want to enhance convenience through SQL support, you can do it yourself or you can collaborate with us.

In addition, for some storages, we can also participate as players in the same position as other custom storage developers. We plan to expand the GlueSQL ecosystem in various ways, such as technical support and storage development.

We are finally ready to provide GlueSQL to users at the production level. We are accelerating the development of GlueSQL. If you are a company interested in storage development like SQL support, or if you resonate with our vision and want to join us, please contact us at taehoon@gluesql.com.

Conclusion

The continued emergence of new databases is driven by the demand for diverse and specialized databases, such as those optimized for Large Language Models (LLMs) and databases catering to unique requirements, like embedded databases, OLAP, OLTP, and time-series data processing. However, developing a new database from scratch is a significant undertaking, requiring extensive work, which often results in high costs.

GlueSQL presents a solution to this challenge by providing a unified query interface that can be ported across various environments, from key-value databases, NoSQL databases, log files, to REST APIs. It allows anyone to create custom storages, reducing the need for developers to build entirely new databases and to learn different usage methods for each database. Instead, they can focus on implementing their business logic using the same interface.

From a user perspective, GlueSQL offers the convenience of a unified query interface, easing the burden of learning different interfaces for each database. This simplification of interface use can also extend to AI, potentially enhancing the efficiency of AI automation.

GlueSQL's development plan includes significant enhancements to its query planner and aims to enable effective attachment of GlueSQL to NoSQL databases. The synergy of combining different databases is a valuable bonus in this process.

Since its inception in the fall of 2019, the GlueSQL team has continuously developed the project, driven by the desire to mitigate the inconveniences encountered while using different databases in various environments. The journey has been a rewarding one, with the GlueSQL project now at a point where it closely resembles the envisioned product.

GlueSQL, distributed under the Apache-2.0 license, is free for anyone to use and adapt. While the GlueSQL team welcomes collaboration with other developers and companies, they also see significant potential for the project as a business venture. The team is working to expand the GlueSQL ecosystem through a variety of initiatives, including technical support and storage development.

With GlueSQL now sufficiently prepared for practical applications, the team invites companies interested in storage development or those who share their vision to join them in their journey of revolutionizing database development.

- - + + \ No newline at end of file diff --git a/docs/dev/blog/tags/query-interface/index.html b/docs/dev/blog/tags/query-interface/index.html index 83c9d973..1ebac216 100644 --- a/docs/dev/blog/tags/query-interface/index.html +++ b/docs/dev/blog/tags/query-interface/index.html @@ -1,18 +1,18 @@ - + - + One post tagged with "query-interface" | GlueSQL - - - + + +
-

One post tagged with "query-interface"

View All Tags

· 14 min read
Taehoon Moon

Introduction

GlueSQL is a versatile database project designed for exceptional portability across a broad range of environments, from embedded systems and servers to web and mobile platforms. The core goal is to support diverse storage environments and manage various data types with a standard SQL approach.

Imagine handling files like CSV, JSONL, and Parquet, or transforming key-value or NoSQL databases such as RocksDB, Redis, and MongoDB into SQL-supporting databases—all feasible with GlueSQL. It can also operate with storages supported in web browsers.

GlueSQL's essential feature is providing a management layer for these diverse storage scenarios without requiring data migration. The broader aim is to facilitate portability of GlueSQL to any environment supporting read or read-write operations. This extends to APIs like GitHub, or messengers like Discord or Slack.

GlueSQL supports both structured and unstructured data and is written in Rust for compatibility with various environments. While portability is its core value, the emphasis is on creating an intuitive, comfortable development environment for easy custom storage implementation.

Ultimately, GlueSQL aims to significantly reduce the cost, time, and complexity of developing new databases. By leveraging GlueSQL for the parser, planner, and execution layer, developers can focus on creating specific storage implementations, leading to a more convenient query interface like SQL for many environments.

The Problem: Why Reinvent the Database?

Despite the numerous database implementations that currently exist, the emergence of new databases continues. The primary reason behind this trend is our need for databases for a broad spectrum of distinct purposes. For instance, new databases are surfacing that are specifically optimized for Large Language Models (LLMs) like ChatGPT. The range is wide and diverse, encompassing embedded databases, OLAP for data analysis, OLTP databases optimized for online transactions, databases specialized for time-series data processing, and many more.

With such varied requirements, we find ourselves in constant need of fresh databases. However, constructing a database from scratch is a monumental task. It necessitates defining a query interface for handling the database and implementing a corresponding parser. Moreover, a separate execution layer for running operations must be built. Also, the planning layer, which is responsible for devising execution strategies, is a vital aspect of this process. Let's not forget about the critical storage layer that physically reads and stores the data. In a nutshell, there's a daunting amount of work involved in developing a new database.

Given these circumstances, it's understandable why numerous emerging databases resort to high pricing structures—they need immediate revenue to offset continuous development costs.

But the story doesn't end here. Query interfaces like SQL are indeed useful for serious tasks, but they also provide excellent utility for handling simple log files such as CSV, JSONL, Parquet, and even for utilizing REST APIs for various applications. The issue arises when a complex query interface needs to be provided even for these lighter storage requirements—it necessitates a development process almost identical to building a sophisticated database. Implementing an entire parser and execution layer just to add SQL support to an existing service can seem like an excessive burden.

Whether it's a simple storage environment or a serious task, the key lies in the storage layer, which involves the actual reading and storing of data. So, what if developers focused on implementing these storage mechanisms while the remaining parts could be handled using existing libraries? This is the role that GlueSQL aspires to play.

The Vision of GlueSQL

The GlueSQL project aims to offer a unified query interface for various environments. The goal is to allow anyone to port and use SQL and GlueSQL's proprietary query builder, the AST Builder, in any desired environment. This could range from key-value databases, serious NoSQL databases, log files, and even REST API services. Essentially, if a service supports reading or read-writing data, regardless of the data type, it can readily support a complex query interface via GlueSQL.

Presently, the GlueSQL project itself directly supports a few storage types as reference storages. These include in-memory storage for non-persistent data handling, sled storage, which is a key-value database written in Rust, JSON storage for handling JSON and JSONL files, and a storage that ports SQL to the web browser's IndexedDB. While the GlueSQL Team is primarily developing these, the aim is to allow anyone to create such custom storages for a wide array of purposes, thus enabling them to assemble the database of their choosing.

Imagine using GlueSQL's SQL and AST Builder everywhere, with the simple method of swapping out storages to operate in diverse settings. It could significantly reduce software development costs. Developers wouldn't need to learn the different usage methods for each database. Instead, they could focus solely on implementing business logic using the same interface.

Our vision is to reduce database development costs by 10 times, or even more than 20 times. We aim to gather diverse database creators under the GlueSQL banner, making it the go-to solution for cost-effective database development.

Benefits to Database Users: Unifying Query Interfaces, Streamlining Software Development, and Reducing Costs

From the perspective of the users who engage with databases, there has always been the burden of learning different interfaces to interact with each database. The approach required to work with Redis is different from that necessary for MongoDB. Likewise, handling SQL databases necessitates using SQL. Although SQL databases generally use a common SQL, the SQL they support can considerably vary when examined in detail.

Naturally, there are legitimate reasons for such differences. Each database focuses on different areas, and to cater to specialized functionalities, they incorporate dedicated interface mechanisms. However, not all application development needs to utilize these database-specific core special functionalities.

Let's look at a couple of examples:

Suppose you're developing a back-end application that uses MySQL as the database and Redis for caching. Due to the vast differences in handling SQL databases and Redis, you would have to develop using different methods when storing data.

Here's another scenario: +

One post tagged with "query-interface"

View All Tags

· 14 min read
Taehoon Moon

Introduction

GlueSQL is a versatile database project designed for exceptional portability across a broad range of environments, from embedded systems and servers to web and mobile platforms. The core goal is to support diverse storage environments and manage various data types with a standard SQL approach.

Imagine handling files like CSV, JSONL, and Parquet, or transforming key-value or NoSQL databases such as RocksDB, Redis, and MongoDB into SQL-supporting databases—all feasible with GlueSQL. It can also operate with storages supported in web browsers.

GlueSQL's essential feature is providing a management layer for these diverse storage scenarios without requiring data migration. The broader aim is to facilitate portability of GlueSQL to any environment supporting read or read-write operations. This extends to APIs like GitHub, or messengers like Discord or Slack.

GlueSQL supports both structured and unstructured data and is written in Rust for compatibility with various environments. While portability is its core value, the emphasis is on creating an intuitive, comfortable development environment for easy custom storage implementation.

Ultimately, GlueSQL aims to significantly reduce the cost, time, and complexity of developing new databases. By leveraging GlueSQL for the parser, planner, and execution layer, developers can focus on creating specific storage implementations, leading to a more convenient query interface like SQL for many environments.

The Problem: Why Reinvent the Database?

Despite the numerous database implementations that currently exist, the emergence of new databases continues. The primary reason behind this trend is our need for databases for a broad spectrum of distinct purposes. For instance, new databases are surfacing that are specifically optimized for Large Language Models (LLMs) like ChatGPT. The range is wide and diverse, encompassing embedded databases, OLAP for data analysis, OLTP databases optimized for online transactions, databases specialized for time-series data processing, and many more.

With such varied requirements, we find ourselves in constant need of fresh databases. However, constructing a database from scratch is a monumental task. It necessitates defining a query interface for handling the database and implementing a corresponding parser. Moreover, a separate execution layer for running operations must be built. Also, the planning layer, which is responsible for devising execution strategies, is a vital aspect of this process. Let's not forget about the critical storage layer that physically reads and stores the data. In a nutshell, there's a daunting amount of work involved in developing a new database.

Given these circumstances, it's understandable why numerous emerging databases resort to high pricing structures—they need immediate revenue to offset continuous development costs.

But the story doesn't end here. Query interfaces like SQL are indeed useful for serious tasks, but they also provide excellent utility for handling simple log files such as CSV, JSONL, Parquet, and even for utilizing REST APIs for various applications. The issue arises when a complex query interface needs to be provided even for these lighter storage requirements—it necessitates a development process almost identical to building a sophisticated database. Implementing an entire parser and execution layer just to add SQL support to an existing service can seem like an excessive burden.

Whether it's a simple storage environment or a serious task, the key lies in the storage layer, which involves the actual reading and storing of data. So, what if developers focused on implementing these storage mechanisms while the remaining parts could be handled using existing libraries? This is the role that GlueSQL aspires to play.

The Vision of GlueSQL

The GlueSQL project aims to offer a unified query interface for various environments. The goal is to allow anyone to port and use SQL and GlueSQL's proprietary query builder, the AST Builder, in any desired environment. This could range from key-value databases, serious NoSQL databases, log files, and even REST API services. Essentially, if a service supports reading or read-writing data, regardless of the data type, it can readily support a complex query interface via GlueSQL.

Presently, the GlueSQL project itself directly supports a few storage types as reference storages. These include in-memory storage for non-persistent data handling, sled storage, which is a key-value database written in Rust, JSON storage for handling JSON and JSONL files, and a storage that ports SQL to the web browser's IndexedDB. While the GlueSQL Team is primarily developing these, the aim is to allow anyone to create such custom storages for a wide array of purposes, thus enabling them to assemble the database of their choosing.

Imagine using GlueSQL's SQL and AST Builder everywhere, with the simple method of swapping out storages to operate in diverse settings. It could significantly reduce software development costs. Developers wouldn't need to learn the different usage methods for each database. Instead, they could focus solely on implementing business logic using the same interface.

Our vision is to reduce database development costs by 10 times, or even more than 20 times. We aim to gather diverse database creators under the GlueSQL banner, making it the go-to solution for cost-effective database development.

Benefits to Database Users: Unifying Query Interfaces, Streamlining Software Development, and Reducing Costs

From the perspective of the users who engage with databases, there has always been the burden of learning different interfaces to interact with each database. The approach required to work with Redis is different from that necessary for MongoDB. Likewise, handling SQL databases necessitates using SQL. Although SQL databases generally use a common SQL, the SQL they support can considerably vary when examined in detail.

Naturally, there are legitimate reasons for such differences. Each database focuses on different areas, and to cater to specialized functionalities, they incorporate dedicated interface mechanisms. However, not all application development needs to utilize these database-specific core special functionalities.

Let's look at a couple of examples:

Suppose you're developing a back-end application that uses MySQL as the database and Redis for caching. Due to the vast differences in handling SQL databases and Redis, you would have to develop using different methods when storing data.

Here's another scenario: Imagine you're implementing a data migration pipeline between various databases and log files. Let's say you're transferring Parquet to Redis or MongoDB. In this case, you would need to convert data using different methods for each, all of which would be a cumbersome process.

In both of the above examples, GlueSQL can directly address and solve the issues. It offers the convenience of a uniform query interface to deal with these matters. In certain scenarios, even the construction of a data pipeline can potentially be solved with a single SQL query, thanks to GlueSQL.

Benefits to Database Developers: Drastically Lowering Development Costs and Simplifying the Creation of Purpose-Built Databases

If you want to support SQL in the desired environment, using GlueSQL essentially requires you to implement an interface for Storage. There's no need to support all functionalities from the beginning. You can start lightly, choosing and implementing storage features suitable for the environment you want to create. To facilitate this, GlueSQL also provides a library in the form of a test suite to easily validate the storage you've implemented.

Lowering development costs in this way will enable a broader range of developers to support the GlueSQL query interface. As more developers join, a significant synergy can be generated. Designing a query interface from scratch involves a great deal of work, including planning and supporting the interface for different target programming languages.

However, despite all this hard work, it is not easy to attract database users accustomed to different methods.

Consider that the SQL and AST Builder provided by GlueSQL are already securing numerous users. This eliminates the need for efforts to promote a newly planned query interface. Over the years, many new databases have emphasized compatibility with PostgreSQL or MySQL for similar reasons. As GlueSQL places a strong emphasis on portability in its query interface planning, it allows for more flexible configuration according to the desired situation. Through the AST Builder, it also eliminates the cost of porting to different languages.

For many database developers, using GlueSQL can be an optimal choice, as it can save costs and quickly secure users.

Let me mention one more thing: what's convenient for humans... could be applied to AI as well. Rather than making AI write automation code using different databases, providing a common query interface can be much more efficient.

The Future with GlueSQL

GlueSQL has been and will continue to improve and develop new features to enable portability in various environments. Thanks to the schemaless data support added last year, it is now possible to handle both structured data with schema and unstructured data like JSON simultaneously. This has significantly increased the range of storage environments that can be supported.

One of the key features added last year was the AST Builder. This feature allowed us to escape the confines of SQL and provide an interface for comfortably handling data in the programming languages used for development.

Of course, improving existing features is extremely important, and there are many new features to be added. As a major development plan this year, we aim to develop features to effectively attach GlueSQL to NoSQL databases with their own planners and execution layers. The GlueSQL query planner, currently at a basic level, will see significant changes this year. With the expansion of this planner, not only NoSQL databases but also other SQL databases could be supported without sacrificing performance using GlueSQL.

The synergy that arises from the combination of different databases is a significant bonus in this process.

The Journey of the GlueSQL Team

The GlueSQL project was first conceived in the fall of 2019, and since then we have been developing it continuously. Personally, I have created various products in a variety of environments, including game development, backend server, and frontend development over the past decade. The experience gained through this process was a major motivation to start the GlueSQL project.

To put it grandly, the inconveniences felt while using different databases in various environments were a major motivation, wouldn't you say?

The start was actually a bit simple. Around 2019, I was mainly doing web front-end development. However, the lack of a structured database for state management and internal data processing made it very uncomfortable, especially since I couldn't use SQL databases and the like. So I started to lightly create an SQL database that could run on a web browser. Also, I wanted to use Rust, but after failing to introduce it at the company I was working for at the time, I decided to use it in my own project.

But as I started developing, my dreams grew significantly. Beyond a SQL database that simply operates on a web browser, I started envisioning a database that fits the name "Glue", one that can easily be ported to various environments, and I continue that journey to this day.

Whether I took the database project too lightly, or because the features I wanted kept increasing, the content to be developed kept expanding. As a result, I ended up investing full time in the GlueSQL project development for over three years. For a year in between, I even juggled full-time software engineering work alongside GlueSQL development. Currently, I'm back to developing the GlueSQL project full time, alongside various part-time contributors.

Now, we're getting very close to the starting point of the picture I wanted to create through GlueSQL, and thankfully, with contributors joining me, I am not alone.

The Sustainability and Business Aspect of GlueSQL

I believe that what we create through GlueSQL will make a great contribution to the world and make many software engineers happy. This gives me immense strength to continue developing even in difficult situations. However, we cannot accomplish everything with pure passion alone. As much as the GlueSQL project can make a significant contribution, I also see it as holding great business value.

The business strategy of GlueSQL may be somewhat different from other databases. We distribute the project itself as open source under the Apache-2.0 license, so that anyone can use it fully, and we do not consider pricing methods such as restricting features to the storages we support. In fact, if there is any player who can do it better, there's no way to prevent them from taking the GlueSQL project and making it their own.

But we believe that GlueSQL has great potential in this regard. Anyone can participate and they are free to distribute their own storage in the way they want, whether it's open source, private, or commercial. This eliminates the need to create something to replace the GlueSQL project. We aim to prevent the need to recreate the wheel that we provide using GlueSQL.

Moreover, our GlueSQL team seeks to continually expand our group of developers and companies working with us. During this development process, while they can certainly implement everything on their own, there is also no reason not to collaborate with our GlueSQL Team, especially for databases like NoSQL that have their own planners and execution layers. If you have a REST API and want to enhance convenience through SQL support, you can do it yourself or you can collaborate with us.

In addition, for some storages, we can also participate as players in the same position as other custom storage developers. We plan to expand the GlueSQL ecosystem in various ways, such as technical support and storage development.

We are finally ready to provide GlueSQL to users at the production level. We are accelerating the development of GlueSQL. If you are a company interested in storage development like SQL support, or if you resonate with our vision and want to join us, please contact us at taehoon@gluesql.com.

Conclusion

The continued emergence of new databases is driven by the demand for diverse and specialized databases, such as those optimized for Large Language Models (LLMs) and databases catering to unique requirements, like embedded databases, OLAP, OLTP, and time-series data processing. However, developing a new database from scratch is a significant undertaking, requiring extensive work, which often results in high costs.

GlueSQL presents a solution to this challenge by providing a unified query interface that can be ported across various environments, from key-value databases, NoSQL databases, log files, to REST APIs. It allows anyone to create custom storages, reducing the need for developers to build entirely new databases and to learn different usage methods for each database. Instead, they can focus on implementing their business logic using the same interface.

From a user perspective, GlueSQL offers the convenience of a unified query interface, easing the burden of learning different interfaces for each database. This simplification of interface use can also extend to AI, potentially enhancing the efficiency of AI automation.

GlueSQL's development plan includes significant enhancements to its query planner and aims to enable effective attachment of GlueSQL to NoSQL databases. The synergy of combining different databases is a valuable bonus in this process.

Since its inception in the fall of 2019, the GlueSQL team has continuously developed the project, driven by the desire to mitigate the inconveniences encountered while using different databases in various environments. The journey has been a rewarding one, with the GlueSQL project now at a point where it closely resembles the envisioned product.

GlueSQL, distributed under the Apache-2.0 license, is free for anyone to use and adapt. While the GlueSQL team welcomes collaboration with other developers and companies, they also see significant potential for the project as a business venture. The team is working to expand the GlueSQL ecosystem through a variety of initiatives, including technical support and storage development.

With GlueSQL now sufficiently prepared for practical applications, the team invites companies interested in storage development or those who share their vision to join them in their journey of revolutionizing database development.

- - + + \ No newline at end of file diff --git a/docs/dev/blog/tags/release-note/index.html b/docs/dev/blog/tags/release-note/index.html index 9ceb0205..fc65cf09 100644 --- a/docs/dev/blog/tags/release-note/index.html +++ b/docs/dev/blog/tags/release-note/index.html @@ -1,19 +1,19 @@ - + - + One post tagged with "release-note" | GlueSQL - - - + + +
-

One post tagged with "release-note"

View All Tags

· 11 min read
Taehoon Moon

We now provide an official documentation website at https://gluesql.org/docs

🚀 Features

🍀 Schemaless data support

GlueSQL now supports creating tables without a schema, allowing for both structured and unstructured data to be stored in the same table. +

One post tagged with "release-note"

View All Tags

· 11 min read
Taehoon Moon

We now provide an official documentation website at https://gluesql.org/docs

🚀 Features

🍀 Schemaless data support

GlueSQL now supports creating tables without a schema, allowing for both structured and unstructured data to be stored in the same table. To create a schemaless table, simply run CREATE TABLE without specifying any columns. For more information on querying schemaless data, please refer to the following link: querying schemaless data

CREATE TABLE Bar;

To insert values,

INSERT INTO Bar VALUES
('{ "name": "ast", "value": 30 }'),
('{ "name": "glue", "rate": 3.0, "list": [1, 2, 3] }'),

Then, selecting values from schemaless table is simple.

SELECT name, rate, list[0] FROM Bar WHERE name = 'glue';

e.g.

CREATE TABLE Names (id INTEGER, name TEXT);
INSERT INTO Names VALUES (1, 'glue'), (2, 'sql');

CREATE TABLE Logs;
INSERT INTO Logs VALUES
('{ "id": 1, "value": 30 }'),
('{ "id": 2, "rate": 3.0, "list": [1, 2, 3] }'),
('{ "id": 3, "rate": 5.0, "value": 100 }');

SELECT * FROM Names JOIN Logs ON Names.id = Logs.id;
/*
| id | list | name | rate | value |
|----|---------|------|------|-------|
| 1 | | glue | | 30 |
| 2 |[1, 2, 3]| sql | 3 | |
*/

🍀 IndexedDB & WebStorage supports in JavaScript package

GlueSQL supports handling in-memory, localStorage, sessionStorage, and even IndexedDB using the same SQL syntax. All you need to know is how to specify the ENGINE when creating a table.

e.g.

CREATE TABLE Mem (mid INTEGER) ENGINE = memory;
CREATE TABLE Loc (lid INTEGER) ENGINE = localStorage;
CREATE TABLE Ses (sid INTEGER) ENGINE = sessionStorage;
CREATE TABLE Idb (iid INTEGER) ENGINE = indexedDB;

SELECT
mid, lid, sid, iid
FROM Mem
JOIN Loc
JOIN Ses
JOIN Idb;

🍀 Data Types - UINT32, UINT64, UINT128, POINT and FLOAT32

🍀 Functions - APPEND, PREPEND, RAND, FIND_IDX, INITCAP and CALC_DISTANCE

🍀 Store traits

User-level custom function

By implementing both the CustomFunction and CustomFunctionMut traits, users can create, use, and delete user-level custom functions. Although GlueSQL plans to continuously add various functions, users may still find them insufficient. In such cases, users can create their own user-level custom functions to supplement the built-in functions. Additionally, if there are repetitive business logic codes, they can be stored as custom functions. e.g.

CREATE FUNCTION ADD_ONE (n INT, x INT DEFAULT 1) RETURN n + x;

SELECT ADD_ONE(10) AS test;

DROP FUNCTION ADD_ONE;

Metadata

The Metadata trait is an optional implementation for providing additional metadata support in GlueSQL. GlueSQL does not enforce any specific metadata implementation, allowing custom storage developers to decide which type of metadata, such as create time, modify time, etc., they want to provide.

🍀 Storages

JSON Storage

Composite Storage

  • Add CompositeStorage which bundles multiple storages @panarch (#1068)

IndexedDB Storage

Web Storage

  • Add WebStorage - support localStorage \& sessionStorage for web browsers @panarch (#1050)

🍀 Other new features

🌊 Interface Changes

  • Remove Store trait related cfg features, @panarch (#1091)
  • Refactor CreateTable.columns from Vec<ColumnDef> to Option<Vec<ColumnDef>> @devgony (#1086)
  • Remove MutResult @panarch (#1073)
  • Update all store mut trait methods to take \&mut self @panarch (#1072)
  • Change StoreMut interface to use \&mut self, not to take ownership @panarch (#1071)
  • Modify default ColumnOption from NOT NULL to NULL @devgony (#997)

🌟 Improvements

🌳 Documentation

We now provide an official documentation website at https://gluesql.org/docs

Docs - setup

📋 Tests

🐛 Bug Fixes

  • Fix docusaurus pages/index broken link @panarch (#1214)
  • Fix docs/ Discord GlueSQL channel invite link address @panarch (#1213)
  • Fix InvalidJsonString error message replacing payload to fileName @devgony (#1185)
  • Fix TryFrom Value::Str to u128 not to use parse_uuid @ChobobDev (#1134)
  • Fix column alias with identifer for TableFactor::Derived @ding-young (#1119)
  • Pass data even when deleted_by is not present @ever0de (#1117)
  • Fix MemoryStorage \& WebStorage primary key support @panarch (#1115)
  • Fix plan::validate to handle CTAS and ITAS adding unit test @devgony (#1074)
  • Fix test-suite tester functions to show (found, expected) shape @panarch (#1028)
- - + + \ No newline at end of file diff --git a/docs/dev/blog/tags/sql/index.html b/docs/dev/blog/tags/sql/index.html index 646f040d..7af0222a 100644 --- a/docs/dev/blog/tags/sql/index.html +++ b/docs/dev/blog/tags/sql/index.html @@ -1,16 +1,16 @@ - + - + One post tagged with "sql" | GlueSQL - - - + + +
-

One post tagged with "sql"

View All Tags

· 11 min read
Taehoon Moon

Introduction

The divide between SQL and NoSQL databases has often presented challenges in database management. GlueSQL, a unique database maker library, aims to blur this boundary, providing a versatile tool for handling these two distinct types of databases.

In this article, we explore how GlueSQL navigates the features of SQL and NoSQL databases, offering an integrated solution that promotes flexibility and efficiency. With its ability to unify disparate database types, GlueSQL heralds a new age of adaptable database creation and management.

The Interface Perspective: SQL & AST Builder

When we talk about SQL databases, it's almost a given that they support SQL - the standard query language. Although there are slight variations between databases, the convenience of using a similar SQL language across multiple databases cannot be overstated. However, from a software engineer's perspective, there's room for improvement. In most software development scenarios, a specific programming language is used. SQL is a separate language, which can cause friction when integrating it into your software. As a result, rather than using raw SQL, many developers employ query builders or ORMs to manipulate SQL conveniently using their preferred programming language. Although it's not efficient to generate SQL using a query builder and then parse it again in the database, it's a practical and effective choice.

On the other hand, NoSQL databases offer different mechanisms. Some of them have their own language similar to SQL, but most provide an interface library developed specifically for each programming language. While SQL databases rely on external query builder libraries to provide an interface for each programming language, NoSQL databases mostly develop and offer these libraries themselves. If we discount the convenience of SQL language, this is one of the major factors that make NoSQL databases more comfortable to use. Since query builder libraries supporting SQL databases often cater to multiple SQL databases, they are limited in fully supporting unique features of each database. NoSQL databases, on the other hand, can freely manage their interface libraries without these restrictions.

Providing a query interface for each programming language is not a fundamental difference between SQL and NoSQL, but we generally accept it implicitly.

Let's see what happens if we break down this boundary, using GlueSQL as an example. As you can see from the SQL postfix, GlueSQL supports SQL and can be classified as an SQL database.

CREATE TABLE Glue (id INTEGER, name TEXT);

INSERT INTO Glue VALUES (1, "hello"), (2, "gluesql");

SELECT * FROM Glue WHERE id = 1;

However, GlueSQL also supports its own query builder, like a NoSQL database. +

One post tagged with "sql"

View All Tags

· 11 min read
Taehoon Moon

Introduction

The divide between SQL and NoSQL databases has often presented challenges in database management. GlueSQL, a unique database maker library, aims to blur this boundary, providing a versatile tool for handling these two distinct types of databases.

In this article, we explore how GlueSQL navigates the features of SQL and NoSQL databases, offering an integrated solution that promotes flexibility and efficiency. With its ability to unify disparate database types, GlueSQL heralds a new age of adaptable database creation and management.

The Interface Perspective: SQL & AST Builder

When we talk about SQL databases, it's almost a given that they support SQL - the standard query language. Although there are slight variations between databases, the convenience of using a similar SQL language across multiple databases cannot be overstated. However, from a software engineer's perspective, there's room for improvement. In most software development scenarios, a specific programming language is used. SQL is a separate language, which can cause friction when integrating it into your software. As a result, rather than using raw SQL, many developers employ query builders or ORMs to manipulate SQL conveniently using their preferred programming language. Although it's not efficient to generate SQL using a query builder and then parse it again in the database, it's a practical and effective choice.

On the other hand, NoSQL databases offer different mechanisms. Some of them have their own language similar to SQL, but most provide an interface library developed specifically for each programming language. While SQL databases rely on external query builder libraries to provide an interface for each programming language, NoSQL databases mostly develop and offer these libraries themselves. If we discount the convenience of SQL language, this is one of the major factors that make NoSQL databases more comfortable to use. Since query builder libraries supporting SQL databases often cater to multiple SQL databases, they are limited in fully supporting unique features of each database. NoSQL databases, on the other hand, can freely manage their interface libraries without these restrictions.

Providing a query interface for each programming language is not a fundamental difference between SQL and NoSQL, but we generally accept it implicitly.

Let's see what happens if we break down this boundary, using GlueSQL as an example. As you can see from the SQL postfix, GlueSQL supports SQL and can be classified as an SQL database.

CREATE TABLE Glue (id INTEGER, name TEXT);

INSERT INTO Glue VALUES (1, "hello"), (2, "gluesql");

SELECT * FROM Glue WHERE id = 1;

However, GlueSQL also supports its own query builder, like a NoSQL database. (Currently, only Rust is supported, but we're working on adding support for other languages.)

table("Glue")
.create_table()
.add_column("id INTEGER")
.add_column("name TEXT")
.execute(glue)

table("Glue")
.insert()
.values(vec![
vec![num(1), text("hello")],
vec![num(2), text("gluesql")],
])
.execute(glue)
.await;

table("Glue")
.select()
.filter(col("id").eq(1))
.execute(glue)
.await;

Let's reconsider the implicit distinction between SQL and NoSQL. GlueSQL indeed supports SQL, but it also officially develops and offers its own query builder. This query builder is not a secondary tool for SQL. While most SQL query builder libraries ultimately generate SQL strings, GlueSQL's builder directly creates an AST (Abstract Structure Tree) that is used for execution within GlueSQL. Hence, we call it the AST Builder. This means SQL and the AST Builder are two equally supported interfaces in GlueSQL.

This also offers an additional advantage:

table("Glue")
.select()
// 1.
.filter(col("id").eq(1))
// 2.
.filter("id = 1")
.execute(glue)
.await;

Because GlueSQL already supports SQL, not only can you use the custom interface in the AST Builder, but you can also use familiar SQL syntax in part. Whether you use col("id").eq(1) or "id = 1", you can use it in the way you prefer. The AST Builder interface, although initially unfamiliar, allows a gradual migration similar to writing SQL for your convenience.

Thus, we've dismantled one of the implicit distinctions between SQL and NoSQL. However, it's more of an implicit differentiation than a fundamental one. There are more significant design differences that we'll explore next.

Structured & Unstructured Data

In this section, we'll discuss how SQL and NoSQL handle data. SQL generally deals with structured data, and recently, it's been made to support semi-structured data as well. On the other hand, NoSQL supports schemaless, unstructured data. Then, we'll explain in detail how GlueSQL handles these two types of data. The last part of this section will provide a segue into the next section where we'll discuss the decomposition of database functions.

When talking about SQL databases, one aspect is usually considered together: SQL databases have a defined schema.

CREATE TABLE Foo (
id INTEGER,
name TEXT,
rate FLOAT NULL
);

However, these days, SQL databases tend to support semi-structured data types, such as LIST or JSON. But, supporting completely schemaless, unstructured data is a different matter. SQL databases typically require a minimum schema.

What about NoSQL databases? As NoSQL databases vary significantly, we can't make definitive statements. But let's consider a typical document database like MongoDB. Unlike SQL databases, it doesn't enforce a schema. Essentially, you can insert any form of data directly. Often, NoSQL databases support schemaless data, but they lack features that enforce a schema like SQL. They generally support structure via validation methods, rather than structured access.

Is there no choice but to distinguish between structured data and unstructured, schemaless data so clearly? GlueSQL is being developed with the goal of being adaptable in various environments. Being forced to choose regarding this schema constraint was quite inconvenient. We started pondering if we couldn't benefit from both aspects - supporting both schema and schemaless data simultaneously, and we eventually found the answer. Let's look at how GlueSQL currently solves this issue through familiar SQL examples.

CREATE TABLE Names (id INTEGER, name TEXT);
INSERT INTO Names VALUES (1, 'glue'), (2, 'sql');

You can create a regular table with a schema like this. But GlueSQL's choice for creating a schemaless table is as follows:

CREATE TABLE Logs;
INSERT INTO Logs VALUES
('{ "id": 1, "value": 30 }'),
('{ "id": 2, "rate": 3.0, "list": [1, 2, 3] }'),
('{ "id": 3, "rate": 5.0, "value": 100 }');

It creates a table without column definitions! If you do this, GlueSQL recognizes the table as schemaless and processes it internally.

SELECT id, rate, list[0] FROM Logs WHERE id = 2;

Although the way to create the table was a bit special, using it isn't much different from the regular SQL SELECT statement. Not only can you differentiate between schema and schemaless when creating tables, but you can also use them interchangeably!

SELECT * FROM Names JOIN Logs ON Names.id = Logs.id;
/*
| id | list | name | rate | value |
|----|---------|------|------|-------|
| 1 | | glue | | 30 |
| 2 |[1, 2, 3]| sql | 3 | |
*/

Here's an example of querying data by INNER JOINing the Names table, which has a schema, and the Logs table, which is schemaless. GlueSQL has resolved this problem by allowing the internal execution layer to handle both vector-type data, for cases where each row has a defined schema, and map-type data for schemaless cases.

Thanks to this, the variety of storage that can be supported through GlueSQL has expanded significantly. If there were previously limitations to supporting NoSQL databases that support schemaless data, that is no longer the case. The reference storage where you can directly experience this schemaless data support is JSON Storage. It offers features that allow you to deal directly with unstructured data like JSON using GlueSQL.

If GlueSQL starts from the perspective of an SQL database and expands, by providing the AST Builder directly, it once blurs the boundary, and by supporting unstructured data simultaneously, it knocks down the boundary once more. How do you like it?

Decomposing Database Functionality: Breaking Down SQL and NoSQL Features

The distinction between SQL and NoSQL is not just about whether they support unstructured data. Of course, there are examples like unstructured data, which is mainly supported only in NoSQL, but in many cases, SQL databases tend to support more diverse and complex queries. NoSQL often gains other advantages in exchange for reducing the range of query support provided by SQL databases.

GlueSQL is ambitious. It has devised a rather interesting method to support all of this through SQL and the AST Builder, with the same interface. When we usually say SQL database, it implicitly assumes that a lot of features have been fully implemented. Create tables by specifying a schema, modify schemas with "alter table", support both clustered and non-clustered indexes, and support transactions. And there's so much more. But the functionality that is naturally supported in SQL databases may not be natural in other environments.

Let's think about JSON Storage. GlueSQL's JSON Storage allows you to handle JSON, JSONL files using SQL and the AST Builder. This JSON Storage does not support atomic operations or transactions. Of course, it would be great if it did, but implementing and executing them would be a significant performance burden. In most cases, when you want to simply browse and handle JSONL files, the overhead caused by transactions can be an unnecessary burden. In this case, you want to handle JSON, JSONL files using SQL, but you don't necessarily need transactions.

To meet the requirements of these diverse environments, GlueSQL has separated the functionality of what we usually call an SQL database into multiple independent interfaces. Store, StoreMut, AlterTable, Transaction, .. These are just a few of the various storage interfaces that GlueSQL currently supports. @@ -23,7 +23,7 @@ The Transaction interface works the same way. The interesting part is that, except for Store and StoreMut, all other storage interfaces can be implemented independently. GlueSQL allows you to choose and implement only the features you need. And it's not just about providing interfaces. It also provides integration tests suitable for each situation to verify what you have implemented. You just need to implement the interface and import the corresponding test case for verification.

In addition to supporting both structured and unstructured data simultaneously, GlueSQL provides the ability to divide the functionality of a database into multiple independent features and selectively implement them. This allows GlueSQL to be ported to a wide variety of environments without any burden.

Conclusion

GlueSQL, while serving as a database that provides its own reference storage, is fundamentally a library designed to simplify the creation of databases. One of the substantial challenges GlueSQL had to overcome in order to support a diverse array of environments was to address the distinctive features that separate conventional SQL databases from NoSQL databases. GlueSQL achieved this through several innovative approaches, managing to support both categories simultaneously despite their significantly different characteristics.

It offers support for SQL alongside an AST Builder, and accommodates both structured and unstructured data. Additionally, it decomposes database functionalities into multiple independent features, allowing each environment to selectively implement the functionalities it requires.

These unique attributes enable GlueSQL to live up to its 'Glue' prefix by facilitating effortless porting across various environments. While we have been developing it for several years, there is still much ground to cover. However, the fact that we are now able to introduce it publicly attests to our successful technological validation and completion of a demonstrable level of implementation.

Through GlueSQL, we hope to provide developers with a unified query interface that can be customized according to their needs, thereby enabling them to produce efficient products more effortlessly. There's a promising future ahead for GlueSQL, and we look forward to its contributions to the technology community.

- - + + \ No newline at end of file diff --git a/docs/dev/blog/tags/tdd/index.html b/docs/dev/blog/tags/tdd/index.html index ff086506..2dd5f076 100644 --- a/docs/dev/blog/tags/tdd/index.html +++ b/docs/dev/blog/tags/tdd/index.html @@ -1,17 +1,17 @@ - + - + One post tagged with "TDD" | GlueSQL - - - + + +
-

One post tagged with "TDD"

View All Tags

· 10 min read
Taehoon Moon

Introduction: GlueSQL and Test-Driven Documentation

Recently, the GlueSQL project reached a significant milestone with the release of version 0.14. This new version brings a host of fresh features to the table, yet one of the most notable changes is in the realm of documentation. For the first time, we're proud to announce the launch of our official documentation website. Interested readers can explore the full range of user manuals at https://gluesql.org/docs.

Prior to this update, the only way to navigate GlueSQL was by manually inspecting the test code within the test suite. With the recent release, however, a comprehensive user manual has been made public to facilitate a more user-friendly experience. We hope that this new addition will prove beneficial to a broad spectrum of users.

The task of compiling an entire database manual in one go was daunting due to the sheer volume of content required. Surprisingly, this process turned out to be smoother than initially anticipated, largely due to the invaluable aid of ChatGPT, which was instrumental in automating much of the document creation. Specifically, around 80% of the SQL Syntax section was generated using this tool.

This remarkable feat was only possible due to the solid foundation of test codes previously established in GlueSQL. In this article, we'll share how we managed to leverage ChatGPT in such a unique way. Based on our recent experience of crafting documents grounded in testing, we've begun to consider the possibility of entirely automating document creation, save for the initial stages.

Along with sharing our journey so far, we will also reveal our plans for future test-based automation of documentation within GlueSQL.

Test Codes and Documentation

The GlueSQL project has placed a significant emphasis on writing test codes. This might be a given for a database project; however, the thoroughness of our approach is evident from our line coverage of nearly 99% for core codes. While we devoted considerable effort to creating these test codes, our primary focus has always been on a different aspect: ensuring that anyone can quickly grasp the content of the tests and easily add new ones.

The intent here is to empower newcomers to GlueSQL to understand the functionality of the software solely by examining integration tests, even in the absence of a user manual.

The integration tests for GlueSQL can be found in the test-suite workspace. For example, here's an excerpt of the test code for the INSERT statement:

test_case!(insert, async move {
run!(
"
CREATE TABLE Test (
id INTEGER DEFAULT 1,
num INTEGER NULL,
name TEXT NOT NULL,
);"
);

test! {
name: "basic insert - single item",
sql: "INSERT INTO Test (id, num, name) VALUES (1, 2, 'Hi boo');",
expected: Ok(Payload::Insert(1))
};


test! {
sql: "INSERT INTO Test VALUES(17, 30, 'Sullivan');",
expected: Ok(Payload::Insert(1))
};

test! {
sql: "INSERT INTO Test (num, name) VALUES (28, 'Wazowski');",
expected: Ok(Payload::Insert(1))
};

test! {
sql: "SELECT * FROM Test;",
expected: Ok(select!(
id | num | name;
I64 | I64 | Str;
1 2 "Hi boo".to_owned();
3 9 "Kitty!".to_owned();
2 7 "Monsters".to_owned();
17 30 "Sullivan".to_owned();
1 28 "Wazowski".to_owned()
))
};

// ...
});

Despite being written in Rust, these test cases are designed to be comprehensible, even to those unfamiliar with the language. Each test is a complete scenario from start to finish, and the results of each operation are readily observable.

Given that identifying results from SELECT operations in the form of Rust enums and structs can be challenging, we actively utilized macros such as select! and select_with_null!. We've composed the test cases to demonstrate that the INSERT statement can handle a wide range of cases, including specifying all columns, omitting some, or omitting all.

test! {
sql: "INSERT INTO Test (id, num) VALUES (1, 10);",
expected: Err(InsertError::LackOfRequiredColumn("name".to_owned()).into())
};

The tests also include scenarios for expected faulty inputs, indicating the error returns in these situations.

By organizing the tests in this manner, we aim to make it easy for anyone to read and write tests. Our goal was for these tests to serve as "documentation" for GlueSQL contributors. At the time we were writing these tests, we didn't anticipate that they could actually become documentation themselves. But we've come to realize that they have extraordinary potential.

Leveraging ChatGPT

When we first embarked on writing the User Manual, we were overwhelmed by the sheer volume of content we had to generate. Around the same time, ChatGPT was gaining prominence, and we thought it might be worth trying out, if only to lighten our load slightly.

To our surprise, ChatGPT exceeded our expectations. If the test codes were well written, it was capable of automatically crafting an exceptional document based on them, capturing all essential details.

After several trials and errors, we settled on the following prompt for document generation. While it's still a challenge to use the same prompt for all documentation, we made minor modifications to suit different situations:

I'm creating an SQL database documentation website, and I'd like you to help me with one of the pages that introduces the SQL syntax for GlueSQL.

1. Please provide the response content in the "markdown" format, so I can copy and paste it directly. Keep this constraint in mind while writing.
2. Regardless of the language I use, I need the content written in English.
3. I will provide some test case code written in the Rust language, which contains SQL examples. Please write the documentation based on these examples, but feel free to change the table names, column names, and data types as needed. Don't include any Rust related content or text in the response. all the response code example should be in plain SQL.
4. GlueSQL does not have the VARCHAR type. If you want to use that, please use TEXT instead. You don't need to mention this in the response.
5. Wrap the entire response text using <pre> and </pre> tags so I can copy all the content easily.

Now, I'd like you to write the following request:
SQL Statement - "INSERT"

Here's an example test code you can refer to:

test_case!(insert, async move {
run!(...

Generally, we used the template above, and copied and pasted the test code from our existing test-suite. We leveraged this method to harness our many tests to assist in the creation of the user manual. In the next section, we'll showcase a sample of the documentation generated in this manner. It's quite impressive.

Success Case: Automated User Manual of GlueSQL

Thanks to ChatGPT, the resulting INSERT document page can be viewed at the following link. It's important to note that we used ChatGPT 4 for this task. Version 3.5 wasn't quite up to the task, and using version 4 was the minimum requirement.

https://gluesql.org/docs/dev/sql-syntax/statements/data-manipulation/insert

INSERT Statement

The results were quite impressive. ChatGPT neatly categorized the test cases, explained the syntax, outlined constraints, and provided appropriate examples. It didn't stop there; it also skillfully recognized error test cases and incorporated them into the documentation, as shown below.

INSERT Statement

Isn't it amazing?

Future Plans: Fully Automating Documentation Generation

While the current documentation is far from perfect and there are many aspects that can be improved, we see great potential in this approach. We believe it's entirely possible to automate the process of writing this kind of document, and writing in general.

In the past, documents like user manuals required a great deal of effort to maintain once they were written. If a document contained real code examples, verifying that the code still worked was often a tedious task. With the ability to automatically generate documentation as we have done here, these issues are no longer problematic.

Previously, you would have to write tests and then also document them separately. If you had to support multiple languages, that would be an additional task. With a tool like ChatGPT, you can automate all of this. All a developer has to do is write the tests. This alone can be sufficient. You can generate documents automatically based on the tests. Eventually, we can even support automatically translating these documents into multiple languages.

The GlueSQL project repository is currently hosted on GitHub and makes good use of various GitHub Actions. We envision a GitHub Action that automatically regenerates a document corresponding to a test when a user modifies the test and raises a Pull Request. Another GitHub Action could automatically translate updated documents into supported languages and create new Pull Requests. The possibilities are truly endless.

Not only will this help with document generation, but it will also provide clear guidelines for writing better test code. If we can automatically generate documents based on written tests, the quality of those documents can serve as an indicator of the quality of the tests themselves. This means that a document automation tool can play the role of a good reviewer for tests. It can greatly reduce the time and effort required for painstakingly reviewing the quality of each test. Developers can also write tests without pressure, evaluate their test code by looking at the generated document, and improve it.

Furthermore, multi-language support becomes a breeze. In my personal experience as a software engineer over the past decade, developing various products such as games, web services, and applications, I often needed to support multiple languages. Each time, there was no definite solution. The optimal approach varied depending on the situation, and there were many things to consider when entrusting translations, such as effectively communicating the context of the target service to the translator. Moreover, regularly updating content and having it retranslated into various languages was a very tedious process. While I tried to automate as much as possible by creating various tools, I was never fully satisfied. I believe ChatGPT can completely solve these issues. If there is a need to provide project-specific context, all you need to do is prepare a prompt in advance. Instead of having to rely on and wait for professional translators, we can now entrust this task to ChatGPT, and we only need a few people to review the translated content.

We are nearing a world where documentation is no longer a burden for developers.

Conclusion: The Value of Test-Driven Documentation

The use of ChatGPT to generate documentation has proven a significant step forward in the GlueSQL user manual creation process. Through test-driven documentation, we've managed to automate a substantial part of the manual creation process, saving time and effort, and increasing accuracy.

Moreover, this process has unveiled a new potential for documentation: the possibility of fully automating document generation. We've seen that quality tests can become quality documentation with the help of AI, leading to more efficient workflows and possibly better test code as a result.

The journey doesn't stop here. We envision leveraging this capability further to auto-translate our documents into multiple languages, making our product more accessible to a global audience.

As we progress, we hope that our experience can inspire other developers to explore and embrace the benefits of AI-generated, test-driven documentation. It's not just about saving time—it's about improving the way we work, communicate, and share knowledge.

- - +

One post tagged with "TDD"

View All Tags

· 10 min read
Taehoon Moon

Introduction: GlueSQL and Test-Driven Documentation

Recently, the GlueSQL project reached a significant milestone with the release of version 0.14. This new version brings a host of fresh features to the table, yet one of the most notable changes is in the realm of documentation. For the first time, we're proud to announce the launch of our official documentation website. Interested readers can explore the full range of user manuals at https://gluesql.org/docs.

Prior to this update, the only way to navigate GlueSQL was by manually inspecting the test code within the test suite. With the recent release, however, a comprehensive user manual has been made public to facilitate a more user-friendly experience. We hope that this new addition will prove beneficial to a broad spectrum of users.

The task of compiling an entire database manual in one go was daunting due to the sheer volume of content required. Surprisingly, this process turned out to be smoother than initially anticipated, largely due to the invaluable aid of ChatGPT, which was instrumental in automating much of the document creation. Specifically, around 80% of the SQL Syntax section was generated using this tool.

This remarkable feat was only possible due to the solid foundation of test codes previously established in GlueSQL. In this article, we'll share how we managed to leverage ChatGPT in such a unique way. Based on our recent experience of crafting documents grounded in testing, we've begun to consider the possibility of entirely automating document creation, save for the initial stages.

Along with sharing our journey so far, we will also reveal our plans for future test-based automation of documentation within GlueSQL.

Test Codes and Documentation

The GlueSQL project has placed a significant emphasis on writing test codes. This might be a given for a database project; however, the thoroughness of our approach is evident from our line coverage of nearly 99% for core codes. While we devoted considerable effort to creating these test codes, our primary focus has always been on a different aspect: ensuring that anyone can quickly grasp the content of the tests and easily add new ones.

The intent here is to empower newcomers to GlueSQL to understand the functionality of the software solely by examining integration tests, even in the absence of a user manual.

The integration tests for GlueSQL can be found in the test-suite workspace. For example, here's an excerpt of the test code for the INSERT statement:

test_case!(insert, async move {
run!(
"
CREATE TABLE Test (
id INTEGER DEFAULT 1,
num INTEGER NULL,
name TEXT NOT NULL,
);"
);

test! {
name: "basic insert - single item",
sql: "INSERT INTO Test (id, num, name) VALUES (1, 2, 'Hi boo');",
expected: Ok(Payload::Insert(1))
};


test! {
sql: "INSERT INTO Test VALUES(17, 30, 'Sullivan');",
expected: Ok(Payload::Insert(1))
};

test! {
sql: "INSERT INTO Test (num, name) VALUES (28, 'Wazowski');",
expected: Ok(Payload::Insert(1))
};

test! {
sql: "SELECT * FROM Test;",
expected: Ok(select!(
id | num | name;
I64 | I64 | Str;
1 2 "Hi boo".to_owned();
3 9 "Kitty!".to_owned();
2 7 "Monsters".to_owned();
17 30 "Sullivan".to_owned();
1 28 "Wazowski".to_owned()
))
};

// ...
});

Despite being written in Rust, these test cases are designed to be comprehensible, even to those unfamiliar with the language. Each test is a complete scenario from start to finish, and the results of each operation are readily observable.

Given that identifying results from SELECT operations in the form of Rust enums and structs can be challenging, we actively utilized macros such as select! and select_with_null!. We've composed the test cases to demonstrate that the INSERT statement can handle a wide range of cases, including specifying all columns, omitting some, or omitting all.

test! {
sql: "INSERT INTO Test (id, num) VALUES (1, 10);",
expected: Err(InsertError::LackOfRequiredColumn("name".to_owned()).into())
};

The tests also include scenarios for expected faulty inputs, indicating the error returns in these situations.

By organizing the tests in this manner, we aim to make it easy for anyone to read and write tests. Our goal was for these tests to serve as "documentation" for GlueSQL contributors. At the time we were writing these tests, we didn't anticipate that they could actually become documentation themselves. But we've come to realize that they have extraordinary potential.

Leveraging ChatGPT

When we first embarked on writing the User Manual, we were overwhelmed by the sheer volume of content we had to generate. Around the same time, ChatGPT was gaining prominence, and we thought it might be worth trying out, if only to lighten our load slightly.

To our surprise, ChatGPT exceeded our expectations. If the test codes were well written, it was capable of automatically crafting an exceptional document based on them, capturing all essential details.

After several trials and errors, we settled on the following prompt for document generation. While it's still a challenge to use the same prompt for all documentation, we made minor modifications to suit different situations:

I'm creating an SQL database documentation website, and I'd like you to help me with one of the pages that introduces the SQL syntax for GlueSQL.

1. Please provide the response content in the "markdown" format, so I can copy and paste it directly. Keep this constraint in mind while writing.
2. Regardless of the language I use, I need the content written in English.
3. I will provide some test case code written in the Rust language, which contains SQL examples. Please write the documentation based on these examples, but feel free to change the table names, column names, and data types as needed. Don't include any Rust related content or text in the response. all the response code example should be in plain SQL.
4. GlueSQL does not have the VARCHAR type. If you want to use that, please use TEXT instead. You don't need to mention this in the response.
5. Wrap the entire response text using <pre> and </pre> tags so I can copy all the content easily.

Now, I'd like you to write the following request:
SQL Statement - "INSERT"

Here's an example test code you can refer to:

test_case!(insert, async move {
run!(...

Generally, we used the template above, and copied and pasted the test code from our existing test-suite. We leveraged this method to harness our many tests to assist in the creation of the user manual. In the next section, we'll showcase a sample of the documentation generated in this manner. It's quite impressive.

Success Case: Automated User Manual of GlueSQL

Thanks to ChatGPT, the resulting INSERT document page can be viewed at the following link. It's important to note that we used ChatGPT 4 for this task. Version 3.5 wasn't quite up to the task, and using version 4 was the minimum requirement.

https://gluesql.org/docs/dev/sql-syntax/statements/data-manipulation/insert

INSERT Statement

The results were quite impressive. ChatGPT neatly categorized the test cases, explained the syntax, outlined constraints, and provided appropriate examples. It didn't stop there; it also skillfully recognized error test cases and incorporated them into the documentation, as shown below.

INSERT Statement

Isn't it amazing?

Future Plans: Fully Automating Documentation Generation

While the current documentation is far from perfect and there are many aspects that can be improved, we see great potential in this approach. We believe it's entirely possible to automate the process of writing this kind of document, and writing in general.

In the past, documents like user manuals required a great deal of effort to maintain once they were written. If a document contained real code examples, verifying that the code still worked was often a tedious task. With the ability to automatically generate documentation as we have done here, these issues are no longer problematic.

Previously, you would have to write tests and then also document them separately. If you had to support multiple languages, that would be an additional task. With a tool like ChatGPT, you can automate all of this. All a developer has to do is write the tests. This alone can be sufficient. You can generate documents automatically based on the tests. Eventually, we can even support automatically translating these documents into multiple languages.

The GlueSQL project repository is currently hosted on GitHub and makes good use of various GitHub Actions. We envision a GitHub Action that automatically regenerates a document corresponding to a test when a user modifies the test and raises a Pull Request. Another GitHub Action could automatically translate updated documents into supported languages and create new Pull Requests. The possibilities are truly endless.

Not only will this help with document generation, but it will also provide clear guidelines for writing better test code. If we can automatically generate documents based on written tests, the quality of those documents can serve as an indicator of the quality of the tests themselves. This means that a document automation tool can play the role of a good reviewer for tests. It can greatly reduce the time and effort required for painstakingly reviewing the quality of each test. Developers can also write tests without pressure, evaluate their test code by looking at the generated document, and improve it.

Furthermore, multi-language support becomes a breeze. In my personal experience as a software engineer over the past decade, developing various products such as games, web services, and applications, I often needed to support multiple languages. Each time, there was no definite solution. The optimal approach varied depending on the situation, and there were many things to consider when entrusting translations, such as effectively communicating the context of the target service to the translator. Moreover, regularly updating content and having it retranslated into various languages was a very tedious process. While I tried to automate as much as possible by creating various tools, I was never fully satisfied. I believe ChatGPT can completely solve these issues. If there is a need to provide project-specific context, all you need to do is prepare a prompt in advance. Instead of having to rely on and wait for professional translators, we can now entrust this task to ChatGPT, and we only need a few people to review the translated content.

We are nearing a world where documentation is no longer a burden for developers.

Conclusion: The Value of Test-Driven Documentation

The use of ChatGPT to generate documentation has proven a significant step forward in the GlueSQL user manual creation process. Through test-driven documentation, we've managed to automate a substantial part of the manual creation process, saving time and effort, and increasing accuracy.

Moreover, this process has unveiled a new potential for documentation: the possibility of fully automating document generation. We've seen that quality tests can become quality documentation with the help of AI, leading to more efficient workflows and possibly better test code as a result.

The journey doesn't stop here. We envision leveraging this capability further to auto-translate our documents into multiple languages, making our product more accessible to a global audience.

As we progress, we hope that our experience can inspire other developers to explore and embrace the benefits of AI-generated, test-driven documentation. It's not just about saving time—it's about improving the way we work, communicate, and share knowledge.

+ + \ No newline at end of file diff --git a/docs/dev/blog/tags/test-driven-documentation/index.html b/docs/dev/blog/tags/test-driven-documentation/index.html index 55d9b6c0..828cdf03 100644 --- a/docs/dev/blog/tags/test-driven-documentation/index.html +++ b/docs/dev/blog/tags/test-driven-documentation/index.html @@ -1,17 +1,17 @@ - + - + One post tagged with "Test-Driven-Documentation" | GlueSQL - - - + + +
-

One post tagged with "Test-Driven-Documentation"

View All Tags

· 10 min read
Taehoon Moon

Introduction: GlueSQL and Test-Driven Documentation

Recently, the GlueSQL project reached a significant milestone with the release of version 0.14. This new version brings a host of fresh features to the table, yet one of the most notable changes is in the realm of documentation. For the first time, we're proud to announce the launch of our official documentation website. Interested readers can explore the full range of user manuals at https://gluesql.org/docs.

Prior to this update, the only way to navigate GlueSQL was by manually inspecting the test code within the test suite. With the recent release, however, a comprehensive user manual has been made public to facilitate a more user-friendly experience. We hope that this new addition will prove beneficial to a broad spectrum of users.

The task of compiling an entire database manual in one go was daunting due to the sheer volume of content required. Surprisingly, this process turned out to be smoother than initially anticipated, largely due to the invaluable aid of ChatGPT, which was instrumental in automating much of the document creation. Specifically, around 80% of the SQL Syntax section was generated using this tool.

This remarkable feat was only possible due to the solid foundation of test codes previously established in GlueSQL. In this article, we'll share how we managed to leverage ChatGPT in such a unique way. Based on our recent experience of crafting documents grounded in testing, we've begun to consider the possibility of entirely automating document creation, save for the initial stages.

Along with sharing our journey so far, we will also reveal our plans for future test-based automation of documentation within GlueSQL.

Test Codes and Documentation

The GlueSQL project has placed a significant emphasis on writing test codes. This might be a given for a database project; however, the thoroughness of our approach is evident from our line coverage of nearly 99% for core codes. While we devoted considerable effort to creating these test codes, our primary focus has always been on a different aspect: ensuring that anyone can quickly grasp the content of the tests and easily add new ones.

The intent here is to empower newcomers to GlueSQL to understand the functionality of the software solely by examining integration tests, even in the absence of a user manual.

The integration tests for GlueSQL can be found in the test-suite workspace. For example, here's an excerpt of the test code for the INSERT statement:

test_case!(insert, async move {
run!(
"
CREATE TABLE Test (
id INTEGER DEFAULT 1,
num INTEGER NULL,
name TEXT NOT NULL,
);"
);

test! {
name: "basic insert - single item",
sql: "INSERT INTO Test (id, num, name) VALUES (1, 2, 'Hi boo');",
expected: Ok(Payload::Insert(1))
};


test! {
sql: "INSERT INTO Test VALUES(17, 30, 'Sullivan');",
expected: Ok(Payload::Insert(1))
};

test! {
sql: "INSERT INTO Test (num, name) VALUES (28, 'Wazowski');",
expected: Ok(Payload::Insert(1))
};

test! {
sql: "SELECT * FROM Test;",
expected: Ok(select!(
id | num | name;
I64 | I64 | Str;
1 2 "Hi boo".to_owned();
3 9 "Kitty!".to_owned();
2 7 "Monsters".to_owned();
17 30 "Sullivan".to_owned();
1 28 "Wazowski".to_owned()
))
};

// ...
});

Despite being written in Rust, these test cases are designed to be comprehensible, even to those unfamiliar with the language. Each test is a complete scenario from start to finish, and the results of each operation are readily observable.

Given that identifying results from SELECT operations in the form of Rust enums and structs can be challenging, we actively utilized macros such as select! and select_with_null!. We've composed the test cases to demonstrate that the INSERT statement can handle a wide range of cases, including specifying all columns, omitting some, or omitting all.

test! {
sql: "INSERT INTO Test (id, num) VALUES (1, 10);",
expected: Err(InsertError::LackOfRequiredColumn("name".to_owned()).into())
};

The tests also include scenarios for expected faulty inputs, indicating the error returns in these situations.

By organizing the tests in this manner, we aim to make it easy for anyone to read and write tests. Our goal was for these tests to serve as "documentation" for GlueSQL contributors. At the time we were writing these tests, we didn't anticipate that they could actually become documentation themselves. But we've come to realize that they have extraordinary potential.

Leveraging ChatGPT

When we first embarked on writing the User Manual, we were overwhelmed by the sheer volume of content we had to generate. Around the same time, ChatGPT was gaining prominence, and we thought it might be worth trying out, if only to lighten our load slightly.

To our surprise, ChatGPT exceeded our expectations. If the test codes were well written, it was capable of automatically crafting an exceptional document based on them, capturing all essential details.

After several trials and errors, we settled on the following prompt for document generation. While it's still a challenge to use the same prompt for all documentation, we made minor modifications to suit different situations:

I'm creating an SQL database documentation website, and I'd like you to help me with one of the pages that introduces the SQL syntax for GlueSQL.

1. Please provide the response content in the "markdown" format, so I can copy and paste it directly. Keep this constraint in mind while writing.
2. Regardless of the language I use, I need the content written in English.
3. I will provide some test case code written in the Rust language, which contains SQL examples. Please write the documentation based on these examples, but feel free to change the table names, column names, and data types as needed. Don't include any Rust related content or text in the response. all the response code example should be in plain SQL.
4. GlueSQL does not have the VARCHAR type. If you want to use that, please use TEXT instead. You don't need to mention this in the response.
5. Wrap the entire response text using <pre> and </pre> tags so I can copy all the content easily.

Now, I'd like you to write the following request:
SQL Statement - "INSERT"

Here's an example test code you can refer to:

test_case!(insert, async move {
run!(...

Generally, we used the template above, and copied and pasted the test code from our existing test-suite. We leveraged this method to harness our many tests to assist in the creation of the user manual. In the next section, we'll showcase a sample of the documentation generated in this manner. It's quite impressive.

Success Case: Automated User Manual of GlueSQL

Thanks to ChatGPT, the resulting INSERT document page can be viewed at the following link. It's important to note that we used ChatGPT 4 for this task. Version 3.5 wasn't quite up to the task, and using version 4 was the minimum requirement.

https://gluesql.org/docs/dev/sql-syntax/statements/data-manipulation/insert

INSERT Statement

The results were quite impressive. ChatGPT neatly categorized the test cases, explained the syntax, outlined constraints, and provided appropriate examples. It didn't stop there; it also skillfully recognized error test cases and incorporated them into the documentation, as shown below.

INSERT Statement

Isn't it amazing?

Future Plans: Fully Automating Documentation Generation

While the current documentation is far from perfect and there are many aspects that can be improved, we see great potential in this approach. We believe it's entirely possible to automate the process of writing this kind of document, and writing in general.

In the past, documents like user manuals required a great deal of effort to maintain once they were written. If a document contained real code examples, verifying that the code still worked was often a tedious task. With the ability to automatically generate documentation as we have done here, these issues are no longer problematic.

Previously, you would have to write tests and then also document them separately. If you had to support multiple languages, that would be an additional task. With a tool like ChatGPT, you can automate all of this. All a developer has to do is write the tests. This alone can be sufficient. You can generate documents automatically based on the tests. Eventually, we can even support automatically translating these documents into multiple languages.

The GlueSQL project repository is currently hosted on GitHub and makes good use of various GitHub Actions. We envision a GitHub Action that automatically regenerates a document corresponding to a test when a user modifies the test and raises a Pull Request. Another GitHub Action could automatically translate updated documents into supported languages and create new Pull Requests. The possibilities are truly endless.

Not only will this help with document generation, but it will also provide clear guidelines for writing better test code. If we can automatically generate documents based on written tests, the quality of those documents can serve as an indicator of the quality of the tests themselves. This means that a document automation tool can play the role of a good reviewer for tests. It can greatly reduce the time and effort required for painstakingly reviewing the quality of each test. Developers can also write tests without pressure, evaluate their test code by looking at the generated document, and improve it.

Furthermore, multi-language support becomes a breeze. In my personal experience as a software engineer over the past decade, developing various products such as games, web services, and applications, I often needed to support multiple languages. Each time, there was no definite solution. The optimal approach varied depending on the situation, and there were many things to consider when entrusting translations, such as effectively communicating the context of the target service to the translator. Moreover, regularly updating content and having it retranslated into various languages was a very tedious process. While I tried to automate as much as possible by creating various tools, I was never fully satisfied. I believe ChatGPT can completely solve these issues. If there is a need to provide project-specific context, all you need to do is prepare a prompt in advance. Instead of having to rely on and wait for professional translators, we can now entrust this task to ChatGPT, and we only need a few people to review the translated content.

We are nearing a world where documentation is no longer a burden for developers.

Conclusion: The Value of Test-Driven Documentation

The use of ChatGPT to generate documentation has proven a significant step forward in the GlueSQL user manual creation process. Through test-driven documentation, we've managed to automate a substantial part of the manual creation process, saving time and effort, and increasing accuracy.

Moreover, this process has unveiled a new potential for documentation: the possibility of fully automating document generation. We've seen that quality tests can become quality documentation with the help of AI, leading to more efficient workflows and possibly better test code as a result.

The journey doesn't stop here. We envision leveraging this capability further to auto-translate our documents into multiple languages, making our product more accessible to a global audience.

As we progress, we hope that our experience can inspire other developers to explore and embrace the benefits of AI-generated, test-driven documentation. It's not just about saving time—it's about improving the way we work, communicate, and share knowledge.

- - +

One post tagged with "Test-Driven-Documentation"

View All Tags

· 10 min read
Taehoon Moon

Introduction: GlueSQL and Test-Driven Documentation

Recently, the GlueSQL project reached a significant milestone with the release of version 0.14. This new version brings a host of fresh features to the table, yet one of the most notable changes is in the realm of documentation. For the first time, we're proud to announce the launch of our official documentation website. Interested readers can explore the full range of user manuals at https://gluesql.org/docs.

Prior to this update, the only way to navigate GlueSQL was by manually inspecting the test code within the test suite. With the recent release, however, a comprehensive user manual has been made public to facilitate a more user-friendly experience. We hope that this new addition will prove beneficial to a broad spectrum of users.

The task of compiling an entire database manual in one go was daunting due to the sheer volume of content required. Surprisingly, this process turned out to be smoother than initially anticipated, largely due to the invaluable aid of ChatGPT, which was instrumental in automating much of the document creation. Specifically, around 80% of the SQL Syntax section was generated using this tool.

This remarkable feat was only possible due to the solid foundation of test codes previously established in GlueSQL. In this article, we'll share how we managed to leverage ChatGPT in such a unique way. Based on our recent experience of crafting documents grounded in testing, we've begun to consider the possibility of entirely automating document creation, save for the initial stages.

Along with sharing our journey so far, we will also reveal our plans for future test-based automation of documentation within GlueSQL.

Test Codes and Documentation

The GlueSQL project has placed a significant emphasis on writing test codes. This might be a given for a database project; however, the thoroughness of our approach is evident from our line coverage of nearly 99% for core codes. While we devoted considerable effort to creating these test codes, our primary focus has always been on a different aspect: ensuring that anyone can quickly grasp the content of the tests and easily add new ones.

The intent here is to empower newcomers to GlueSQL to understand the functionality of the software solely by examining integration tests, even in the absence of a user manual.

The integration tests for GlueSQL can be found in the test-suite workspace. For example, here's an excerpt of the test code for the INSERT statement:

test_case!(insert, async move {
run!(
"
CREATE TABLE Test (
id INTEGER DEFAULT 1,
num INTEGER NULL,
name TEXT NOT NULL,
);"
);

test! {
name: "basic insert - single item",
sql: "INSERT INTO Test (id, num, name) VALUES (1, 2, 'Hi boo');",
expected: Ok(Payload::Insert(1))
};


test! {
sql: "INSERT INTO Test VALUES(17, 30, 'Sullivan');",
expected: Ok(Payload::Insert(1))
};

test! {
sql: "INSERT INTO Test (num, name) VALUES (28, 'Wazowski');",
expected: Ok(Payload::Insert(1))
};

test! {
sql: "SELECT * FROM Test;",
expected: Ok(select!(
id | num | name;
I64 | I64 | Str;
1 2 "Hi boo".to_owned();
3 9 "Kitty!".to_owned();
2 7 "Monsters".to_owned();
17 30 "Sullivan".to_owned();
1 28 "Wazowski".to_owned()
))
};

// ...
});

Despite being written in Rust, these test cases are designed to be comprehensible, even to those unfamiliar with the language. Each test is a complete scenario from start to finish, and the results of each operation are readily observable.

Given that identifying results from SELECT operations in the form of Rust enums and structs can be challenging, we actively utilized macros such as select! and select_with_null!. We've composed the test cases to demonstrate that the INSERT statement can handle a wide range of cases, including specifying all columns, omitting some, or omitting all.

test! {
sql: "INSERT INTO Test (id, num) VALUES (1, 10);",
expected: Err(InsertError::LackOfRequiredColumn("name".to_owned()).into())
};

The tests also include scenarios for expected faulty inputs, indicating the error returns in these situations.

By organizing the tests in this manner, we aim to make it easy for anyone to read and write tests. Our goal was for these tests to serve as "documentation" for GlueSQL contributors. At the time we were writing these tests, we didn't anticipate that they could actually become documentation themselves. But we've come to realize that they have extraordinary potential.

Leveraging ChatGPT

When we first embarked on writing the User Manual, we were overwhelmed by the sheer volume of content we had to generate. Around the same time, ChatGPT was gaining prominence, and we thought it might be worth trying out, if only to lighten our load slightly.

To our surprise, ChatGPT exceeded our expectations. If the test codes were well written, it was capable of automatically crafting an exceptional document based on them, capturing all essential details.

After several trials and errors, we settled on the following prompt for document generation. While it's still a challenge to use the same prompt for all documentation, we made minor modifications to suit different situations:

I'm creating an SQL database documentation website, and I'd like you to help me with one of the pages that introduces the SQL syntax for GlueSQL.

1. Please provide the response content in the "markdown" format, so I can copy and paste it directly. Keep this constraint in mind while writing.
2. Regardless of the language I use, I need the content written in English.
3. I will provide some test case code written in the Rust language, which contains SQL examples. Please write the documentation based on these examples, but feel free to change the table names, column names, and data types as needed. Don't include any Rust related content or text in the response. all the response code example should be in plain SQL.
4. GlueSQL does not have the VARCHAR type. If you want to use that, please use TEXT instead. You don't need to mention this in the response.
5. Wrap the entire response text using <pre> and </pre> tags so I can copy all the content easily.

Now, I'd like you to write the following request:
SQL Statement - "INSERT"

Here's an example test code you can refer to:

test_case!(insert, async move {
run!(...

Generally, we used the template above, and copied and pasted the test code from our existing test-suite. We leveraged this method to harness our many tests to assist in the creation of the user manual. In the next section, we'll showcase a sample of the documentation generated in this manner. It's quite impressive.

Success Case: Automated User Manual of GlueSQL

Thanks to ChatGPT, the resulting INSERT document page can be viewed at the following link. It's important to note that we used ChatGPT 4 for this task. Version 3.5 wasn't quite up to the task, and using version 4 was the minimum requirement.

https://gluesql.org/docs/dev/sql-syntax/statements/data-manipulation/insert

INSERT Statement

The results were quite impressive. ChatGPT neatly categorized the test cases, explained the syntax, outlined constraints, and provided appropriate examples. It didn't stop there; it also skillfully recognized error test cases and incorporated them into the documentation, as shown below.

INSERT Statement

Isn't it amazing?

Future Plans: Fully Automating Documentation Generation

While the current documentation is far from perfect and there are many aspects that can be improved, we see great potential in this approach. We believe it's entirely possible to automate the process of writing this kind of document, and writing in general.

In the past, documents like user manuals required a great deal of effort to maintain once they were written. If a document contained real code examples, verifying that the code still worked was often a tedious task. With the ability to automatically generate documentation as we have done here, these issues are no longer problematic.

Previously, you would have to write tests and then also document them separately. If you had to support multiple languages, that would be an additional task. With a tool like ChatGPT, you can automate all of this. All a developer has to do is write the tests. This alone can be sufficient. You can generate documents automatically based on the tests. Eventually, we can even support automatically translating these documents into multiple languages.

The GlueSQL project repository is currently hosted on GitHub and makes good use of various GitHub Actions. We envision a GitHub Action that automatically regenerates a document corresponding to a test when a user modifies the test and raises a Pull Request. Another GitHub Action could automatically translate updated documents into supported languages and create new Pull Requests. The possibilities are truly endless.

Not only will this help with document generation, but it will also provide clear guidelines for writing better test code. If we can automatically generate documents based on written tests, the quality of those documents can serve as an indicator of the quality of the tests themselves. This means that a document automation tool can play the role of a good reviewer for tests. It can greatly reduce the time and effort required for painstakingly reviewing the quality of each test. Developers can also write tests without pressure, evaluate their test code by looking at the generated document, and improve it.

Furthermore, multi-language support becomes a breeze. In my personal experience as a software engineer over the past decade, developing various products such as games, web services, and applications, I often needed to support multiple languages. Each time, there was no definite solution. The optimal approach varied depending on the situation, and there were many things to consider when entrusting translations, such as effectively communicating the context of the target service to the translator. Moreover, regularly updating content and having it retranslated into various languages was a very tedious process. While I tried to automate as much as possible by creating various tools, I was never fully satisfied. I believe ChatGPT can completely solve these issues. If there is a need to provide project-specific context, all you need to do is prepare a prompt in advance. Instead of having to rely on and wait for professional translators, we can now entrust this task to ChatGPT, and we only need a few people to review the translated content.

We are nearing a world where documentation is no longer a burden for developers.

Conclusion: The Value of Test-Driven Documentation

The use of ChatGPT to generate documentation has proven a significant step forward in the GlueSQL user manual creation process. Through test-driven documentation, we've managed to automate a substantial part of the manual creation process, saving time and effort, and increasing accuracy.

Moreover, this process has unveiled a new potential for documentation: the possibility of fully automating document generation. We've seen that quality tests can become quality documentation with the help of AI, leading to more efficient workflows and possibly better test code as a result.

The journey doesn't stop here. We envision leveraging this capability further to auto-translate our documents into multiple languages, making our product more accessible to a global audience.

As we progress, we hope that our experience can inspire other developers to explore and embrace the benefits of AI-generated, test-driven documentation. It's not just about saving time—it's about improving the way we work, communicate, and share knowledge.

+ + \ No newline at end of file diff --git a/docs/dev/blog/tags/v-0-14/index.html b/docs/dev/blog/tags/v-0-14/index.html index f646d665..e29b2213 100644 --- a/docs/dev/blog/tags/v-0-14/index.html +++ b/docs/dev/blog/tags/v-0-14/index.html @@ -1,19 +1,19 @@ - + - + One post tagged with "v0.14" | GlueSQL - - - + + +
-

One post tagged with "v0.14"

View All Tags

· 11 min read
Taehoon Moon

We now provide an official documentation website at https://gluesql.org/docs

🚀 Features

🍀 Schemaless data support

GlueSQL now supports creating tables without a schema, allowing for both structured and unstructured data to be stored in the same table. +

One post tagged with "v0.14"

View All Tags

· 11 min read
Taehoon Moon

We now provide an official documentation website at https://gluesql.org/docs

🚀 Features

🍀 Schemaless data support

GlueSQL now supports creating tables without a schema, allowing for both structured and unstructured data to be stored in the same table. To create a schemaless table, simply run CREATE TABLE without specifying any columns. For more information on querying schemaless data, please refer to the following link: querying schemaless data

CREATE TABLE Bar;

To insert values,

INSERT INTO Bar VALUES
('{ "name": "ast", "value": 30 }'),
('{ "name": "glue", "rate": 3.0, "list": [1, 2, 3] }'),

Then, selecting values from schemaless table is simple.

SELECT name, rate, list[0] FROM Bar WHERE name = 'glue';

e.g.

CREATE TABLE Names (id INTEGER, name TEXT);
INSERT INTO Names VALUES (1, 'glue'), (2, 'sql');

CREATE TABLE Logs;
INSERT INTO Logs VALUES
('{ "id": 1, "value": 30 }'),
('{ "id": 2, "rate": 3.0, "list": [1, 2, 3] }'),
('{ "id": 3, "rate": 5.0, "value": 100 }');

SELECT * FROM Names JOIN Logs ON Names.id = Logs.id;
/*
| id | list | name | rate | value |
|----|---------|------|------|-------|
| 1 | | glue | | 30 |
| 2 |[1, 2, 3]| sql | 3 | |
*/

🍀 IndexedDB & WebStorage supports in JavaScript package

GlueSQL supports handling in-memory, localStorage, sessionStorage, and even IndexedDB using the same SQL syntax. All you need to know is how to specify the ENGINE when creating a table.

e.g.

CREATE TABLE Mem (mid INTEGER) ENGINE = memory;
CREATE TABLE Loc (lid INTEGER) ENGINE = localStorage;
CREATE TABLE Ses (sid INTEGER) ENGINE = sessionStorage;
CREATE TABLE Idb (iid INTEGER) ENGINE = indexedDB;

SELECT
mid, lid, sid, iid
FROM Mem
JOIN Loc
JOIN Ses
JOIN Idb;

🍀 Data Types - UINT32, UINT64, UINT128, POINT and FLOAT32

🍀 Functions - APPEND, PREPEND, RAND, FIND_IDX, INITCAP and CALC_DISTANCE

🍀 Store traits

User-level custom function

By implementing both the CustomFunction and CustomFunctionMut traits, users can create, use, and delete user-level custom functions. Although GlueSQL plans to continuously add various functions, users may still find them insufficient. In such cases, users can create their own user-level custom functions to supplement the built-in functions. Additionally, if there are repetitive business logic codes, they can be stored as custom functions. e.g.

CREATE FUNCTION ADD_ONE (n INT, x INT DEFAULT 1) RETURN n + x;

SELECT ADD_ONE(10) AS test;

DROP FUNCTION ADD_ONE;

Metadata

The Metadata trait is an optional implementation for providing additional metadata support in GlueSQL. GlueSQL does not enforce any specific metadata implementation, allowing custom storage developers to decide which type of metadata, such as create time, modify time, etc., they want to provide.

🍀 Storages

JSON Storage

Composite Storage

  • Add CompositeStorage which bundles multiple storages @panarch (#1068)

IndexedDB Storage

Web Storage

  • Add WebStorage - support localStorage \& sessionStorage for web browsers @panarch (#1050)

🍀 Other new features

🌊 Interface Changes

  • Remove Store trait related cfg features, @panarch (#1091)
  • Refactor CreateTable.columns from Vec<ColumnDef> to Option<Vec<ColumnDef>> @devgony (#1086)
  • Remove MutResult @panarch (#1073)
  • Update all store mut trait methods to take \&mut self @panarch (#1072)
  • Change StoreMut interface to use \&mut self, not to take ownership @panarch (#1071)
  • Modify default ColumnOption from NOT NULL to NULL @devgony (#997)

🌟 Improvements

🌳 Documentation

We now provide an official documentation website at https://gluesql.org/docs

Docs - setup

📋 Tests

🐛 Bug Fixes

  • Fix docusaurus pages/index broken link @panarch (#1214)
  • Fix docs/ Discord GlueSQL channel invite link address @panarch (#1213)
  • Fix InvalidJsonString error message replacing payload to fileName @devgony (#1185)
  • Fix TryFrom Value::Str to u128 not to use parse_uuid @ChobobDev (#1134)
  • Fix column alias with identifer for TableFactor::Derived @ding-young (#1119)
  • Pass data even when deleted_by is not present @ever0de (#1117)
  • Fix MemoryStorage \& WebStorage primary key support @panarch (#1115)
  • Fix plan::validate to handle CTAS and ITAS adding unit test @devgony (#1074)
  • Fix test-suite tester functions to show (found, expected) shape @panarch (#1028)
- - + + \ No newline at end of file diff --git a/docs/dev/blog/test-driven-documentation/index.html b/docs/dev/blog/test-driven-documentation/index.html index 25b3f1fb..476f2a19 100644 --- a/docs/dev/blog/test-driven-documentation/index.html +++ b/docs/dev/blog/test-driven-documentation/index.html @@ -1,17 +1,17 @@ - + - + Test-Driven Documentation - Automating User Manual Creation in GlueSQL | GlueSQL - - - + + +
-

Test-Driven Documentation - Automating User Manual Creation in GlueSQL

· 10 min read
Taehoon Moon

Introduction: GlueSQL and Test-Driven Documentation

Recently, the GlueSQL project reached a significant milestone with the release of version 0.14. This new version brings a host of fresh features to the table, yet one of the most notable changes is in the realm of documentation. For the first time, we're proud to announce the launch of our official documentation website. Interested readers can explore the full range of user manuals at https://gluesql.org/docs.

Prior to this update, the only way to navigate GlueSQL was by manually inspecting the test code within the test suite. With the recent release, however, a comprehensive user manual has been made public to facilitate a more user-friendly experience. We hope that this new addition will prove beneficial to a broad spectrum of users.

The task of compiling an entire database manual in one go was daunting due to the sheer volume of content required. Surprisingly, this process turned out to be smoother than initially anticipated, largely due to the invaluable aid of ChatGPT, which was instrumental in automating much of the document creation. Specifically, around 80% of the SQL Syntax section was generated using this tool.

This remarkable feat was only possible due to the solid foundation of test codes previously established in GlueSQL. In this article, we'll share how we managed to leverage ChatGPT in such a unique way. Based on our recent experience of crafting documents grounded in testing, we've begun to consider the possibility of entirely automating document creation, save for the initial stages.

Along with sharing our journey so far, we will also reveal our plans for future test-based automation of documentation within GlueSQL.

Test Codes and Documentation

The GlueSQL project has placed a significant emphasis on writing test codes. This might be a given for a database project; however, the thoroughness of our approach is evident from our line coverage of nearly 99% for core codes. While we devoted considerable effort to creating these test codes, our primary focus has always been on a different aspect: ensuring that anyone can quickly grasp the content of the tests and easily add new ones.

The intent here is to empower newcomers to GlueSQL to understand the functionality of the software solely by examining integration tests, even in the absence of a user manual.

The integration tests for GlueSQL can be found in the test-suite workspace. For example, here's an excerpt of the test code for the INSERT statement:

test_case!(insert, async move {
run!(
"
CREATE TABLE Test (
id INTEGER DEFAULT 1,
num INTEGER NULL,
name TEXT NOT NULL,
);"
);

test! {
name: "basic insert - single item",
sql: "INSERT INTO Test (id, num, name) VALUES (1, 2, 'Hi boo');",
expected: Ok(Payload::Insert(1))
};


test! {
sql: "INSERT INTO Test VALUES(17, 30, 'Sullivan');",
expected: Ok(Payload::Insert(1))
};

test! {
sql: "INSERT INTO Test (num, name) VALUES (28, 'Wazowski');",
expected: Ok(Payload::Insert(1))
};

test! {
sql: "SELECT * FROM Test;",
expected: Ok(select!(
id | num | name;
I64 | I64 | Str;
1 2 "Hi boo".to_owned();
3 9 "Kitty!".to_owned();
2 7 "Monsters".to_owned();
17 30 "Sullivan".to_owned();
1 28 "Wazowski".to_owned()
))
};

// ...
});

Despite being written in Rust, these test cases are designed to be comprehensible, even to those unfamiliar with the language. Each test is a complete scenario from start to finish, and the results of each operation are readily observable.

Given that identifying results from SELECT operations in the form of Rust enums and structs can be challenging, we actively utilized macros such as select! and select_with_null!. We've composed the test cases to demonstrate that the INSERT statement can handle a wide range of cases, including specifying all columns, omitting some, or omitting all.

test! {
sql: "INSERT INTO Test (id, num) VALUES (1, 10);",
expected: Err(InsertError::LackOfRequiredColumn("name".to_owned()).into())
};

The tests also include scenarios for expected faulty inputs, indicating the error returns in these situations.

By organizing the tests in this manner, we aim to make it easy for anyone to read and write tests. Our goal was for these tests to serve as "documentation" for GlueSQL contributors. At the time we were writing these tests, we didn't anticipate that they could actually become documentation themselves. But we've come to realize that they have extraordinary potential.

Leveraging ChatGPT

When we first embarked on writing the User Manual, we were overwhelmed by the sheer volume of content we had to generate. Around the same time, ChatGPT was gaining prominence, and we thought it might be worth trying out, if only to lighten our load slightly.

To our surprise, ChatGPT exceeded our expectations. If the test codes were well written, it was capable of automatically crafting an exceptional document based on them, capturing all essential details.

After several trials and errors, we settled on the following prompt for document generation. While it's still a challenge to use the same prompt for all documentation, we made minor modifications to suit different situations:

I'm creating an SQL database documentation website, and I'd like you to help me with one of the pages that introduces the SQL syntax for GlueSQL.

1. Please provide the response content in the "markdown" format, so I can copy and paste it directly. Keep this constraint in mind while writing.
2. Regardless of the language I use, I need the content written in English.
3. I will provide some test case code written in the Rust language, which contains SQL examples. Please write the documentation based on these examples, but feel free to change the table names, column names, and data types as needed. Don't include any Rust related content or text in the response. all the response code example should be in plain SQL.
4. GlueSQL does not have the VARCHAR type. If you want to use that, please use TEXT instead. You don't need to mention this in the response.
5. Wrap the entire response text using <pre> and </pre> tags so I can copy all the content easily.

Now, I'd like you to write the following request:
SQL Statement - "INSERT"

Here's an example test code you can refer to:

test_case!(insert, async move {
run!(...

Generally, we used the template above, and copied and pasted the test code from our existing test-suite. We leveraged this method to harness our many tests to assist in the creation of the user manual. In the next section, we'll showcase a sample of the documentation generated in this manner. It's quite impressive.

Success Case: Automated User Manual of GlueSQL

Thanks to ChatGPT, the resulting INSERT document page can be viewed at the following link. It's important to note that we used ChatGPT 4 for this task. Version 3.5 wasn't quite up to the task, and using version 4 was the minimum requirement.

https://gluesql.org/docs/dev/sql-syntax/statements/data-manipulation/insert

INSERT Statement

The results were quite impressive. ChatGPT neatly categorized the test cases, explained the syntax, outlined constraints, and provided appropriate examples. It didn't stop there; it also skillfully recognized error test cases and incorporated them into the documentation, as shown below.

INSERT Statement

Isn't it amazing?

Future Plans: Fully Automating Documentation Generation

While the current documentation is far from perfect and there are many aspects that can be improved, we see great potential in this approach. We believe it's entirely possible to automate the process of writing this kind of document, and writing in general.

In the past, documents like user manuals required a great deal of effort to maintain once they were written. If a document contained real code examples, verifying that the code still worked was often a tedious task. With the ability to automatically generate documentation as we have done here, these issues are no longer problematic.

Previously, you would have to write tests and then also document them separately. If you had to support multiple languages, that would be an additional task. With a tool like ChatGPT, you can automate all of this. All a developer has to do is write the tests. This alone can be sufficient. You can generate documents automatically based on the tests. Eventually, we can even support automatically translating these documents into multiple languages.

The GlueSQL project repository is currently hosted on GitHub and makes good use of various GitHub Actions. We envision a GitHub Action that automatically regenerates a document corresponding to a test when a user modifies the test and raises a Pull Request. Another GitHub Action could automatically translate updated documents into supported languages and create new Pull Requests. The possibilities are truly endless.

Not only will this help with document generation, but it will also provide clear guidelines for writing better test code. If we can automatically generate documents based on written tests, the quality of those documents can serve as an indicator of the quality of the tests themselves. This means that a document automation tool can play the role of a good reviewer for tests. It can greatly reduce the time and effort required for painstakingly reviewing the quality of each test. Developers can also write tests without pressure, evaluate their test code by looking at the generated document, and improve it.

Furthermore, multi-language support becomes a breeze. In my personal experience as a software engineer over the past decade, developing various products such as games, web services, and applications, I often needed to support multiple languages. Each time, there was no definite solution. The optimal approach varied depending on the situation, and there were many things to consider when entrusting translations, such as effectively communicating the context of the target service to the translator. Moreover, regularly updating content and having it retranslated into various languages was a very tedious process. While I tried to automate as much as possible by creating various tools, I was never fully satisfied. I believe ChatGPT can completely solve these issues. If there is a need to provide project-specific context, all you need to do is prepare a prompt in advance. Instead of having to rely on and wait for professional translators, we can now entrust this task to ChatGPT, and we only need a few people to review the translated content.

We are nearing a world where documentation is no longer a burden for developers.

Conclusion: The Value of Test-Driven Documentation

The use of ChatGPT to generate documentation has proven a significant step forward in the GlueSQL user manual creation process. Through test-driven documentation, we've managed to automate a substantial part of the manual creation process, saving time and effort, and increasing accuracy.

Moreover, this process has unveiled a new potential for documentation: the possibility of fully automating document generation. We've seen that quality tests can become quality documentation with the help of AI, leading to more efficient workflows and possibly better test code as a result.

The journey doesn't stop here. We envision leveraging this capability further to auto-translate our documents into multiple languages, making our product more accessible to a global audience.

As we progress, we hope that our experience can inspire other developers to explore and embrace the benefits of AI-generated, test-driven documentation. It's not just about saving time—it's about improving the way we work, communicate, and share knowledge.

- - +

Test-Driven Documentation - Automating User Manual Creation in GlueSQL

· 10 min read
Taehoon Moon

Introduction: GlueSQL and Test-Driven Documentation

Recently, the GlueSQL project reached a significant milestone with the release of version 0.14. This new version brings a host of fresh features to the table, yet one of the most notable changes is in the realm of documentation. For the first time, we're proud to announce the launch of our official documentation website. Interested readers can explore the full range of user manuals at https://gluesql.org/docs.

Prior to this update, the only way to navigate GlueSQL was by manually inspecting the test code within the test suite. With the recent release, however, a comprehensive user manual has been made public to facilitate a more user-friendly experience. We hope that this new addition will prove beneficial to a broad spectrum of users.

The task of compiling an entire database manual in one go was daunting due to the sheer volume of content required. Surprisingly, this process turned out to be smoother than initially anticipated, largely due to the invaluable aid of ChatGPT, which was instrumental in automating much of the document creation. Specifically, around 80% of the SQL Syntax section was generated using this tool.

This remarkable feat was only possible due to the solid foundation of test codes previously established in GlueSQL. In this article, we'll share how we managed to leverage ChatGPT in such a unique way. Based on our recent experience of crafting documents grounded in testing, we've begun to consider the possibility of entirely automating document creation, save for the initial stages.

Along with sharing our journey so far, we will also reveal our plans for future test-based automation of documentation within GlueSQL.

Test Codes and Documentation

The GlueSQL project has placed a significant emphasis on writing test codes. This might be a given for a database project; however, the thoroughness of our approach is evident from our line coverage of nearly 99% for core codes. While we devoted considerable effort to creating these test codes, our primary focus has always been on a different aspect: ensuring that anyone can quickly grasp the content of the tests and easily add new ones.

The intent here is to empower newcomers to GlueSQL to understand the functionality of the software solely by examining integration tests, even in the absence of a user manual.

The integration tests for GlueSQL can be found in the test-suite workspace. For example, here's an excerpt of the test code for the INSERT statement:

test_case!(insert, async move {
run!(
"
CREATE TABLE Test (
id INTEGER DEFAULT 1,
num INTEGER NULL,
name TEXT NOT NULL,
);"
);

test! {
name: "basic insert - single item",
sql: "INSERT INTO Test (id, num, name) VALUES (1, 2, 'Hi boo');",
expected: Ok(Payload::Insert(1))
};


test! {
sql: "INSERT INTO Test VALUES(17, 30, 'Sullivan');",
expected: Ok(Payload::Insert(1))
};

test! {
sql: "INSERT INTO Test (num, name) VALUES (28, 'Wazowski');",
expected: Ok(Payload::Insert(1))
};

test! {
sql: "SELECT * FROM Test;",
expected: Ok(select!(
id | num | name;
I64 | I64 | Str;
1 2 "Hi boo".to_owned();
3 9 "Kitty!".to_owned();
2 7 "Monsters".to_owned();
17 30 "Sullivan".to_owned();
1 28 "Wazowski".to_owned()
))
};

// ...
});

Despite being written in Rust, these test cases are designed to be comprehensible, even to those unfamiliar with the language. Each test is a complete scenario from start to finish, and the results of each operation are readily observable.

Given that identifying results from SELECT operations in the form of Rust enums and structs can be challenging, we actively utilized macros such as select! and select_with_null!. We've composed the test cases to demonstrate that the INSERT statement can handle a wide range of cases, including specifying all columns, omitting some, or omitting all.

test! {
sql: "INSERT INTO Test (id, num) VALUES (1, 10);",
expected: Err(InsertError::LackOfRequiredColumn("name".to_owned()).into())
};

The tests also include scenarios for expected faulty inputs, indicating the error returns in these situations.

By organizing the tests in this manner, we aim to make it easy for anyone to read and write tests. Our goal was for these tests to serve as "documentation" for GlueSQL contributors. At the time we were writing these tests, we didn't anticipate that they could actually become documentation themselves. But we've come to realize that they have extraordinary potential.

Leveraging ChatGPT

When we first embarked on writing the User Manual, we were overwhelmed by the sheer volume of content we had to generate. Around the same time, ChatGPT was gaining prominence, and we thought it might be worth trying out, if only to lighten our load slightly.

To our surprise, ChatGPT exceeded our expectations. If the test codes were well written, it was capable of automatically crafting an exceptional document based on them, capturing all essential details.

After several trials and errors, we settled on the following prompt for document generation. While it's still a challenge to use the same prompt for all documentation, we made minor modifications to suit different situations:

I'm creating an SQL database documentation website, and I'd like you to help me with one of the pages that introduces the SQL syntax for GlueSQL.

1. Please provide the response content in the "markdown" format, so I can copy and paste it directly. Keep this constraint in mind while writing.
2. Regardless of the language I use, I need the content written in English.
3. I will provide some test case code written in the Rust language, which contains SQL examples. Please write the documentation based on these examples, but feel free to change the table names, column names, and data types as needed. Don't include any Rust related content or text in the response. all the response code example should be in plain SQL.
4. GlueSQL does not have the VARCHAR type. If you want to use that, please use TEXT instead. You don't need to mention this in the response.
5. Wrap the entire response text using <pre> and </pre> tags so I can copy all the content easily.

Now, I'd like you to write the following request:
SQL Statement - "INSERT"

Here's an example test code you can refer to:

test_case!(insert, async move {
run!(...

Generally, we used the template above, and copied and pasted the test code from our existing test-suite. We leveraged this method to harness our many tests to assist in the creation of the user manual. In the next section, we'll showcase a sample of the documentation generated in this manner. It's quite impressive.

Success Case: Automated User Manual of GlueSQL

Thanks to ChatGPT, the resulting INSERT document page can be viewed at the following link. It's important to note that we used ChatGPT 4 for this task. Version 3.5 wasn't quite up to the task, and using version 4 was the minimum requirement.

https://gluesql.org/docs/dev/sql-syntax/statements/data-manipulation/insert

INSERT Statement

The results were quite impressive. ChatGPT neatly categorized the test cases, explained the syntax, outlined constraints, and provided appropriate examples. It didn't stop there; it also skillfully recognized error test cases and incorporated them into the documentation, as shown below.

INSERT Statement

Isn't it amazing?

Future Plans: Fully Automating Documentation Generation

While the current documentation is far from perfect and there are many aspects that can be improved, we see great potential in this approach. We believe it's entirely possible to automate the process of writing this kind of document, and writing in general.

In the past, documents like user manuals required a great deal of effort to maintain once they were written. If a document contained real code examples, verifying that the code still worked was often a tedious task. With the ability to automatically generate documentation as we have done here, these issues are no longer problematic.

Previously, you would have to write tests and then also document them separately. If you had to support multiple languages, that would be an additional task. With a tool like ChatGPT, you can automate all of this. All a developer has to do is write the tests. This alone can be sufficient. You can generate documents automatically based on the tests. Eventually, we can even support automatically translating these documents into multiple languages.

The GlueSQL project repository is currently hosted on GitHub and makes good use of various GitHub Actions. We envision a GitHub Action that automatically regenerates a document corresponding to a test when a user modifies the test and raises a Pull Request. Another GitHub Action could automatically translate updated documents into supported languages and create new Pull Requests. The possibilities are truly endless.

Not only will this help with document generation, but it will also provide clear guidelines for writing better test code. If we can automatically generate documents based on written tests, the quality of those documents can serve as an indicator of the quality of the tests themselves. This means that a document automation tool can play the role of a good reviewer for tests. It can greatly reduce the time and effort required for painstakingly reviewing the quality of each test. Developers can also write tests without pressure, evaluate their test code by looking at the generated document, and improve it.

Furthermore, multi-language support becomes a breeze. In my personal experience as a software engineer over the past decade, developing various products such as games, web services, and applications, I often needed to support multiple languages. Each time, there was no definite solution. The optimal approach varied depending on the situation, and there were many things to consider when entrusting translations, such as effectively communicating the context of the target service to the translator. Moreover, regularly updating content and having it retranslated into various languages was a very tedious process. While I tried to automate as much as possible by creating various tools, I was never fully satisfied. I believe ChatGPT can completely solve these issues. If there is a need to provide project-specific context, all you need to do is prepare a prompt in advance. Instead of having to rely on and wait for professional translators, we can now entrust this task to ChatGPT, and we only need a few people to review the translated content.

We are nearing a world where documentation is no longer a burden for developers.

Conclusion: The Value of Test-Driven Documentation

The use of ChatGPT to generate documentation has proven a significant step forward in the GlueSQL user manual creation process. Through test-driven documentation, we've managed to automate a substantial part of the manual creation process, saving time and effort, and increasing accuracy.

Moreover, this process has unveiled a new potential for documentation: the possibility of fully automating document generation. We've seen that quality tests can become quality documentation with the help of AI, leading to more efficient workflows and possibly better test code as a result.

The journey doesn't stop here. We envision leveraging this capability further to auto-translate our documents into multiple languages, making our product more accessible to a global audience.

As we progress, we hope that our experience can inspire other developers to explore and embrace the benefits of AI-generated, test-driven documentation. It's not just about saving time—it's about improving the way we work, communicate, and share knowledge.

+ + \ No newline at end of file diff --git a/docs/dev/getting-started/cli/index.html b/docs/dev/getting-started/cli/index.html index 04387268..db1449b5 100644 --- a/docs/dev/getting-started/cli/index.html +++ b/docs/dev/getting-started/cli/index.html @@ -1,17 +1,17 @@ - + - + Command-Line Interface | GlueSQL - - - + + +

Command-Line Interface

Introduction

The Command-Line Interface (CLI) is a tool that allows interactive execution of SQL on GlueSQL. It supports Dot commands for more convenient use, and the .edit command allows immediate modification of query files, which can then be executed with .execute. In addition, it supports HTML table format output for SQL results, making it possible to use the results directly on the web.

Installation

To install the GlueSQL Command-Line Interface (CLI), run the following command:

$ cargo install gluesql

Running the CLI

Once you have installed the GlueSQL CLI, you can use it to interact with your database. The CLI has several options that you can use to customize your database configuration:

$ gluesql [--execute ~/sql_path] [--path ~/data_path --storage={sled | json}]

--execute

This option allows you to execute a SQL query that is stored in a specific file path. You need to provide the path to the SQL file that contains the query you want to execute. For example, you can use the following command to execute a file located at ~/sql_path/query.sql

gluesql --execute ~/sql_path/query.sql

--path

This option allows you to specify the path to your database's data directory. By default, GlueSQL stores your database in the current directory. However, you can use the --path option to specify a custom directory where you want to store your database files. For example, you can use the following command to specify a custom data directory ~/mydatabase:

gluesql --path ~/mydatabase

--storage

This option allows you to specify the storage engine you want to use for your database. By default, GlueSQL uses the memory storage engine. However, you can also use sled or json storage engine by using the --storage option. Note that sled and json should be with --path option. For example, you can use the following command to specify the json storage engine:

gluesql --path ~/mydatabase --storage=json

Dot command

.show

This command shows current Print options.

gluesql> .show all
tabular ON
colsep "|"
colwrap ""
heading ON

or you can specify a option

gluesql> .show colsep
colsep "|"

.set

This command can set each Print options

commanddescription
tabular {ON|OFF}turn on/off html table format
colsep {SEPARATOR}set column separator(tabular OFF only)
colwrap {WRAPPER}set column wrapper(tabular OFF only)
heading {ON|OFF}turn on/off heading
gluesql> VALUES (1, 'Glue'), (2, 'SQL');
| column1 | column2 |
|---------|---------|
| 1 | Glue |
| 2 | SQL |

gluesql> .set tabular off
gluesql> VALUES (1, 'Glue'), (2, 'SQL');
column1|column2
1|Glue
2|SQL
gluesql> .set colsep ,
gluesql> VALUES (1, 'Glue'), (2, 'SQL');
column1,column2
1,Glue
2,SQL
gluesql> .set colwrap '
gluesql> VALUES (1, 'Glue'), (2, 'SQL');
'column1','column2'
'1','Glue'
'2','SQL'
gluesql> .set heading off
gluesql> VALUES (1, 'Glue'), (2, 'SQL');
'1','Glue'
'2','SQL'

.edit

This command open editor with last executed SQL or PATH

With last executed SQL

if you execute .edit, it opens specified (set on $EDITOR env) or OS default editor.

$ export $EDITOR=vi
$ gluesql
gluesql> VALUES (1, 'Glue'), (2, 'SQL');
| column1 | column2 |
|---------|---------|
| 1 | Glue |
| 2 | SQL |
gluesql> .edit

Last executed SQL is opened with vi

--! /tmp/Glue_xxxxx.sql
VALUES (1, 'Glue'), (2, 'SQL');

With PATH

gluesql> .edit insert.sql

It opens editor and shows the contents of create_insert.sql

--! create_insert.sql
CREATE TABLE Items (id INT, name TEXT);
INSERT INTO Items VALUES (1, 'Glue'), (2, 'SQL');

.execute

This command executes SQL from PATH

gluesql> .execute create_insert.sql
Table created

2 rows inserted

.run

This command executes last executed command again.

gluesql> VALUES (1, 'Glue'), (2, 'SQL');
| column1 | column2 |
|---------|---------|
| 1 | Glue |
| 2 | SQL |

gluesql> .run
| column1 | column2 |
|---------|---------|
| 1 | Glue |
| 2 | SQL |

Also possible to combinate with .edit

gluesql> VALUES (1, 'Glue'), (2, 'SQL');
| column1 | column2 |
|---------|---------|
| 1 | Glue |
| 2 | SQL |

gluesql> .edit

edit to add (3, 'Rust')

--! /tmp/Glue_xxxxxx.sql
VALUES (1, 'Glue'), (2, 'SQL'), (3, 'Rust')
gluesql> .run
| column1 | column2 |
|---------|---------|
| 1 | Glue |
| 2 | SQL |
| 3 | Rust |

More commands

If you execute .help, you can see various helper command starting with dot(.)

commanddescription
.helpshow help
.quitquit program
.tablesshow table names
.functionsshow function names
.columns TABLEshow columns from TABLE
.versionshow version
.execute PATHexecute SQL from PATH
.spool PATH|offspool to PATH or off
.show OPTIONshow print option eg).show all
.set OPTIONset print option eg).set tabular off
.edit [PATH]open editor with last command or PATH
.runexecute last command

Migration using CLI

GlueSQL CLI supports generating SQL scripts for dumping whole schemas and data.

For instance, if you want to dump your database schema and data to a file named dump.sql, you can use the following command:

$ gluesql --path ~/glue_data --dump ./dump.sql

This will create a SQL script in the current directory that you can use to recreate your database.

If you want to import the database from the dump.sql file, you can use the following command:

$ gluesql --execute ./dump.sql --path ~/new_data --storage=sled

This will create a new database in the specified path, using the Sled Storage engine.

That's it! You now know how to use GlueSQL to migrate your database schema and data using the CLI.

- - + + \ No newline at end of file diff --git a/docs/dev/getting-started/javascript-web/index.html b/docs/dev/getting-started/javascript-web/index.html index 602e3848..97057585 100644 --- a/docs/dev/getting-started/javascript-web/index.html +++ b/docs/dev/getting-started/javascript-web/index.html @@ -1,17 +1,17 @@ - + - + JavaScript (Web Browser) | GlueSQL - - - + + +

JavaScript (Web Browser)

GlueSQL is a SQL database engine written in Rust, compiled to WebAssembly, and can be used in JavaScript. This guide will walk you through the process of installing and using the GlueSQL package.

Installation

Installing GlueSQL is as simple as running the following command:

npm install gluesql

In your package.json, it will be added to the dependencies list as follows:

{
"dependencies": {
"gluesql": "latest"
}
}

Usage

GlueSQL can be used in different environments. Here we will look at how to use it with JavaScript modules, Webpack, and Rollup.

JavaScript Modules

In an HTML file, you can use GlueSQL by importing it with a script tag:

<script type="module">
import { gluesql } from 'gluesql';

async function main() {
const db = await gluesql();
await db.loadIndexedDB();

const result = await db.query(`
CREATE TABLE Foo (id INTEGER) ENGINE = memory;
INSERT INTO Foo (1, 'glue'), (2, 'sql');
SELECT * FROM Foo;
`);

console.log(result);
}
</script>

Webpack

For Webpack, the usage is almost the same as JavaScript modules:

import { gluesql } from 'gluesql';

async function run() {
const db = await gluesql();
await db.loadIndexedDB();

const result = await db.query(`
CREATE TABLE Foo (id INTEGER) ENGINE = memory;
INSERT INTO Foo VALUES (1, 'glue'), (2, 'sql');
SELECT * FROM Foo;
`);

console.log(result);
}

Rollup

For Rollup, you need to adjust your import statement and add some configurations to your rollup.config.js file.

First, modify your import statement as follows:

import { gluesql } from 'gluesql/gluesql.rollup';
// ...

Second, add the following configurations to your rollup.config.js file:

import resolve from '@rollup/plugin-node-resolve';
import { wasm } from '@rollup/plugin-wasm';

export default {
input: 'main.js',
output: {
file: 'dist/bundle.js',
format: 'iife',
},
plugins: [
resolve({ browser: true }),
wasm({ targetEnv: 'auto-inline' }),
],
};

These configurations allow Rollup to correctly handle WebAssembly modules and resolve dependencies for browsers.

Don't forget to run the rollup command to bundle your JavaScript files:

rollup -c

Now, you can use GlueSQL in your Rollup project as you would in any other JavaScript module.

Supported Storage Engines

GlueSQL supports four storage types: In-Memory Storage, Local Storage, Session Storage, and IndexedDB.

You can specify the storage type when creating a table using the ENGINE clause:

  • For In-Memory Storage: ENGINE = memory
  • For Local Storage: ENGINE = localStorage
  • For Session Storage: ENGINE = sessionStorage
  • For IndexedDB: ENGINE = indexedDB

For example:

CREATE TABLE Foo (id INTEGER) ENGINE = memory;
- - + + \ No newline at end of file diff --git a/docs/dev/getting-started/nodejs/index.html b/docs/dev/getting-started/nodejs/index.html index af74db34..72d7cd3c 100644 --- a/docs/dev/getting-started/nodejs/index.html +++ b/docs/dev/getting-started/nodejs/index.html @@ -1,17 +1,17 @@ - + - + Node.js | GlueSQL - - - + + +

Node.js

This guide will help you get started with GlueSQL in a Node.js project. First, install the gluesql package using npm by running the following command in your terminal:

npm install gluesql

Alternatively, you can add it as a dependency in your package.json file:

{
"dependencies": {
"gluesql": "latest"
}
}

Please note that the Node.js version of GlueSQL currently supports only non-persistent memory storage.

Next, you can use GlueSQL in your Node.js project by following this simple example:

const { gluesql } = require('gluesql');
const db = gluesql();

async function run() {
await db.query(`
CREATE TABLE User (id INTEGER, name TEXT);
CREATE TABLE Device (name TEXT, userId INTEGER);
INSERT INTO User VALUES (1, 'glue'), (2, 'sticky'), (3, 'watt');
INSERT INTO Device VALUES ('Phone', 1), ('Mic', 1), ('Monitor', 3), ('Mouse', 2), ('Touchpad', 2);
`);

const sql = `
SELECT
u.name as user,
d.name as device
FROM User u
JOIN Device d ON u.id = d.userId
`;
const [{ rows }] = await db.query(sql);
console.table(rows);
}

run();

This example demonstrates how to create tables, insert data, and perform a join query using GlueSQL in Node.js.

- - + + \ No newline at end of file diff --git a/docs/dev/getting-started/rust/index.html b/docs/dev/getting-started/rust/index.html index 13651b25..769c6c0c 100644 --- a/docs/dev/getting-started/rust/index.html +++ b/docs/dev/getting-started/rust/index.html @@ -1,17 +1,17 @@ - + - + Rust | GlueSQL - - - + + +

Rust

To install and use GlueSQL in your Rust project, you'll first need to add it as a dependency from crates.io. You can do this by adding the following lines to your Cargo.toml file:

[dependencies]
gluesql = "0.14"

By default, all available storage features are included with GlueSQL. Here's a list of the available features:

  • sled-storage - Storage based on the persistent key-value database called sled
  • memory-storage - Simple in-memory storage
  • shared-memory-storage - A wrapper around memory-storage for easy use in multi-threaded environments
  • json-storage - Storage that allows you to analyze and modify JSON or JSONL files using SQL
  • composite-storage - A storage feature that enables joining and processing data from multiple storage types simultaneously
  • web-storage - Storage supporting localStorage and sessionStorage, available only in web assembly builds
  • idb-storage - IndexedDB-based storage, available only in web assembly builds

If you don't need all the default storage features, you can disable them and select only the ones you require. To do this, update your Cargo.toml file with the following lines:

[dependencies.gluesql]
version = "0.14"
default-features = false
features = ["memory-storage", "json-storage"]

This configuration will disable the default storage features and only include the memory-storage and json-storage features in your project.

- - + + \ No newline at end of file diff --git a/docs/dev/index.html b/docs/dev/index.html index 1470186d..9f7c9241 100644 --- a/docs/dev/index.html +++ b/docs/dev/index.html @@ -1,12 +1,12 @@ - + - + Introduction | GlueSQL - - - + + +
@@ -17,7 +17,7 @@ docs.rs Chat Coverage Status

Multi-Model Database Engine as a Library

GlueSQL is a Rust library for SQL databases that includes a parser (sqlparser-rs), an execution layer, and a variety of storage options, both persistent and non-persistent, all in one package. It is a versatile tool for developers, supporting both SQL and its own query builder (AST Builder). GlueSQL can handle structured and unstructured data, making it suitable for a wide range of use cases. It is portable and can be used with various storage types, including log files and read-write capable storage. GlueSQL is designed to be extensible and supports custom planners, making it a powerful tool for developers who need SQL support for their databases or services. GlueSQL is also flexible, as it can be used in Rust and JavaScript environments, and its language support is constantly expanding to include more programming languages.

"We offer a service where the GlueSQL team can implement and maintain your custom storage, especially beneficial for NoSQL databases with their own query planner and execution layer. We welcome any services wishing to support SQL and GlueSQL query interfaces. For more details, please refer to here."

If you're interested in learning more about GlueSQL, we recommend the following blog articles for a deeper dive into its capabilities and benefits:

  1. Breaking the Boundary between SQL and NoSQL Database
  2. Revolutionizing Databases by Unifying Query Interfaces
  3. Test-Driven Documentation - Automating User Manual Creation

Supporting SQL and AST Builder

GlueSQL supports both SQL and its own query builder (AST Builder). Unlike other ORMs, GlueSQL's AST Builder allows developers to build queries directly with GlueSQL's AST, enabling the use of all of GlueSQL's features. This is why we named it AST Builder instead of Query Builder.

SQL Example

SELECT id, name FROM Foo WHERE name = 'Lemon' AND price > 100

AST Builder Example

table("Foo")
.select()
// Filter by name using a SQL string
.filter("name = 'Lemon'")
// Filter by price using AST Builder methods
.filter(col("price").gt(100))
.project("id, name")
.execute(glue)
.await;

Supporting Structured and Unstructured Data with Schema Flexibility

GlueSQL supports both structured and unstructured (schemaless) data. While SQL databases typically assume that schemas are defined and used, GlueSQL does not make this assumption. It supports completely unstructured data, similar to a NoSQL document database, as well as semi-structured types such as MAP and LIST. This makes GlueSQL suitable for a wide range of use cases, including those that require handling of unstructured data. Additionally, it is possible to join tables with schemas and schemaless tables together and execute queries.

Schemaless SQL Example

CREATE TABLE Names (id INTEGER, name TEXT);
INSERT INTO Names VALUES (1, 'glue'), (2, 'sql');

CREATE TABLE Logs;
INSERT INTO Logs VALUES
('{ "id": 1, "value": 30 }'),
('{ "id": 2, "rate": 3.0, "list": [1, 2, 3] }'),
('{ "id": 3, "rate": 5.0, "value": 100 }');

SELECT * FROM Names JOIN Logs ON Names.id = Logs.id;
/*
| id | list | name | rate | value |
|----|---------|------|------|-------|
| 1 | | glue | | 30 |
| 2 |[1, 2, 3]| sql | 3 | |
*/

Supported Reference Storages

GlueSQL provides a variety of reference storages out of the box, including simple in-memory storage, key-value databases, log file-based storage like JSON & JSONL, and even Web Storage and IndexedDB supported by web browsers. These reference storages are readily available for use and can be easily adapted to a variety of storage systems. Additionally, GlueSQL is constantly expanding its list of supported storages, making it a versatile tool for developers.

Memory Storage

Memory Storage is a foundational storage option designed for in-memory, non-persistent data. It is a simple yet robust storage option that can be used in production environments.

Shared Memory Storage

Shared Memory Storage is a storage option designed to provide more comfortable usage of Memory Storage in concurrent environments. It wraps the Memory Storage with a read-write lock and an atomic reference count, allowing you to clone the storage instance and use it effortlessly across multiple threads. All storage instances will refer to the same data, making it a convenient option for concurrent environments.

Sled Storage

Sled Storage is a persistent data storage option for GlueSQL that is built on the Sled key-value embedded database in Rust. It is the only storage option currently supported by GlueSQL that implements all Store traits, from non-clustered indexes to transactions. Sled Storage is an excellent choice for handling and storing data in a Rust environment. To use Sled Storage, you can create a SledStorage instance using a path.

JSON Storage

With GlueSQL, you can use JSONL or JSON files as a database that supports SQL and AST Builder, making it a powerful option for developers who need to work with JSON data. JSON Storage is a storage system that uses two types of files: a schema file (optional) and a data file. The schema file is written in Standard SQL and stores the structure of the table, while the data file contains the actual data and supports two file formats: .json and .jsonl. JSON Storage supports all DML features, but is particularly specialized for SELECT and INSERT.

Web Storage

WebStorage, specifically localStorage and sessionStorage, can be used as a data storage system for GlueSQL. While WebStorage is a simple key-value database that uses string keys, GlueSQL makes it more powerful by adding support for SQL queries. This allows you to use SQL to interact with WebStorage, making it a convenient option for developers who are familiar with SQL. WebStorage can be used in JavaScript (Web) environments and Rust WebAssembly environments.

IndexedDB Storage

IndexedDB Storage is a powerful storage system that allows you to interact with IndexedDB using SQL. While using IndexedDB directly can be challenging, GlueSQL makes it easy to use by handling version management internally and storing data in JSON format. With GlueSQL, you can use SQL to interact with IndexedDB, making it a convenient option for developers who are familiar with SQL. You can use IndexedDB Storage in both JavaScript (Web) and Rust WebAssembly environments.

Composite Storage

Composite Storage is a powerful feature of GlueSQL that allows you to bundle together multiple existing storages, enabling you to perform JOIN operations across two distinct storages. This feature is utilized in various environments, including GlueSQL's JavaScript (Web) interface. Specifically, GlueSQL bundles together memory, localStorage, sessionStorage, and IndexedDB using Composite Storage in its JavaScript (Web) interface. This allows you to create tables using four different storages and perform operations like JOIN using SQL, all at once. Composite Storage is a versatile feature that can be used in many different scenarios, making it a valuable tool for developers who need to work with multiple storage systems, including those that require data migration between different storage systems.

Adapting GlueSQL to Your Environment: Creating Custom Storage

GlueSQL is designed to be adaptable to a wide variety of environments, including file systems, key-value databases, complex NoSQL databases, and remote APIs. To create a custom storage for GlueSQL, you only need to implement the Store and StoreMut traits provided by GlueSQL. These traits allow you to support SELECT queries and modify data, such as INSERT, UPDATE, and DELETE.

If you want to support additional features, such as schema changes, transactions, or custom functions, you can implement the corresponding traits. However, these traits are optional, and you can choose to implement only the ones that are relevant to your storage system.

To make it even easier to develop custom storages, GlueSQL provides a Test Suite that allows you to test your storage implementation against a set of standard SQL queries. This ensures that your storage system is compatible with GlueSQL and can handle common SQL operations.

Overall, creating a custom storage for GlueSQL is a straightforward process that allows you to adapt SQL and the AST Builder to your environment with ease.

GlueSQL Custom Storage: Let Us Handle It for You

Although anyone can develop a custom storage for GlueSQL with ease, our GlueSQL team can also implement and maintain it for you. This is especially recommended for NoSQL databases with their own query planner and execution layer, as adapting GlueSQL to them requires a deep understanding of GlueSQL's planner and storage layer details. We welcome not only database companies but also any services that want to support SQL and GlueSQL query interfaces. As GlueSQL is rapidly adding and improving features, we can help you develop and manage your custom storage effectively if you entrust it to us. If you're interested, please contact us at taehoon@gluesql.com.

Contribution

GlueSQL is a database project that is simpler than you might think. You only need to know three common Rust project commands: cargo fmt, cargo clippy, and cargo test. Don't hesitate to make pull requests and change the code as you see fit. We have set up GitHub Actions to validate your changes, so you don't have to worry about making mistakes. The line coverage of GlueSQL's core code is almost 99%, which is the result of not only careful test writing, but also of making the test suite easy to understand and use for anyone, even those who are not familiar with Rust. If you're not sure where to start, we recommend exploring the test suite first. Take a look at the existing features and try to understand how they work. Even if you're not familiar with Rust, you should be able to navigate the test suite without any problems. If there's a feature you'd like to see but isn't there yet, implementing it yourself and contributing it to GlueSQL is a great way to get involved. You can also check out the issues on the GlueSQL GitHub repository for more ideas on how to contribute.

License

This project is licensed under the Apache License, Version 2.0 - see the LICENSE file for details.

- - + + \ No newline at end of file diff --git a/docs/dev/sitemap.xml b/docs/dev/sitemap.xml index e1dcfa17..6d333371 100644 --- a/docs/dev/sitemap.xml +++ b/docs/dev/sitemap.xml @@ -1 +1 @@ -https://gluesql.org/docs/dev/blogweekly0.5https://gluesql.org/docs/dev/blog/archiveweekly0.5https://gluesql.org/docs/dev/blog/breaking-the-boundary-between-sql-and-nosqlweekly0.5https://gluesql.org/docs/dev/blog/release-v0.14weekly0.5https://gluesql.org/docs/dev/blog/revolutionizing-databases-by-unifying-query-interfacesweekly0.5https://gluesql.org/docs/dev/blog/tagsweekly0.5https://gluesql.org/docs/dev/blog/tags/automationweekly0.5https://gluesql.org/docs/dev/blog/tags/chat-gptweekly0.5https://gluesql.org/docs/dev/blog/tags/databaseweekly0.5https://gluesql.org/docs/dev/blog/tags/documentationweekly0.5https://gluesql.org/docs/dev/blog/tags/gluesqlweekly0.5https://gluesql.org/docs/dev/blog/tags/nosqlweekly0.5https://gluesql.org/docs/dev/blog/tags/proposalweekly0.5https://gluesql.org/docs/dev/blog/tags/query-interfaceweekly0.5https://gluesql.org/docs/dev/blog/tags/release-noteweekly0.5https://gluesql.org/docs/dev/blog/tags/sqlweekly0.5https://gluesql.org/docs/dev/blog/tags/tddweekly0.5https://gluesql.org/docs/dev/blog/tags/test-driven-documentationweekly0.5https://gluesql.org/docs/dev/blog/tags/v-0-14weekly0.5https://gluesql.org/docs/dev/blog/test-driven-documentationweekly0.5https://gluesql.org/docs/dev/weekly0.5https://gluesql.org/docs/dev/ast-builder/expressions/conditionalweekly0.5https://gluesql.org/docs/dev/ast-builder/expressions/nestedweekly0.5https://gluesql.org/docs/dev/ast-builder/expressions/operator-basedweekly0.5https://gluesql.org/docs/dev/ast-builder/expressions/pattern-matchingweekly0.5https://gluesql.org/docs/dev/ast-builder/expressions/value-checkingweekly0.5https://gluesql.org/docs/dev/ast-builder/functions/date-&-time/conversionweekly0.5https://gluesql.org/docs/dev/ast-builder/functions/date-&-time/current-date-and-timeweekly0.5https://gluesql.org/docs/dev/ast-builder/functions/date-&-time/date-and-time-extractionweekly0.5https://gluesql.org/docs/dev/ast-builder/functions/date-&-time/formattingweekly0.5https://gluesql.org/docs/dev/ast-builder/functions/geometry/coordinate-extractionweekly0.5https://gluesql.org/docs/dev/ast-builder/functions/geometry/distance-calculationweekly0.5https://gluesql.org/docs/dev/ast-builder/functions/geometry/point-creationweekly0.5https://gluesql.org/docs/dev/ast-builder/functions/list-&-map/list-and-map-concatenationweekly0.5https://gluesql.org/docs/dev/ast-builder/functions/list-&-map/list-manipulationweekly0.5https://gluesql.org/docs/dev/ast-builder/functions/math/basic-arithmeticweekly0.5https://gluesql.org/docs/dev/ast-builder/functions/math/conversionweekly0.5https://gluesql.org/docs/dev/ast-builder/functions/math/logarithmic-and-exponentialweekly0.5https://gluesql.org/docs/dev/ast-builder/functions/math/roundingweekly0.5https://gluesql.org/docs/dev/ast-builder/functions/math/special-mathematicalweekly0.5https://gluesql.org/docs/dev/ast-builder/functions/math/trigonometricweekly0.5https://gluesql.org/docs/dev/ast-builder/functions/others/null-handlingweekly0.5https://gluesql.org/docs/dev/ast-builder/functions/others/type-conversionweekly0.5https://gluesql.org/docs/dev/ast-builder/functions/others/unique-identifierweekly0.5https://gluesql.org/docs/dev/ast-builder/functions/text/case-conversionweekly0.5https://gluesql.org/docs/dev/ast-builder/functions/text/character-conversionweekly0.5https://gluesql.org/docs/dev/ast-builder/functions/text/paddingweekly0.5https://gluesql.org/docs/dev/ast-builder/functions/text/position-and-indexingweekly0.5https://gluesql.org/docs/dev/ast-builder/functions/text/text-manipulationweekly0.5https://gluesql.org/docs/dev/ast-builder/functions/text/trimmingweekly0.5https://gluesql.org/docs/dev/ast-builder/introweekly0.5https://gluesql.org/docs/dev/ast-builder/statements/data-manipulation/deleting-dataweekly0.5https://gluesql.org/docs/dev/ast-builder/statements/data-manipulation/inserting-dataweekly0.5https://gluesql.org/docs/dev/ast-builder/statements/data-manipulation/updating-dataweekly0.5https://gluesql.org/docs/dev/ast-builder/statements/querying/creating-derived-subqueriesweekly0.5https://gluesql.org/docs/dev/ast-builder/statements/querying/data-aggregationweekly0.5https://gluesql.org/docs/dev/ast-builder/statements/querying/data-injectionweekly0.5https://gluesql.org/docs/dev/ast-builder/statements/querying/data-joiningweekly0.5https://gluesql.org/docs/dev/ast-builder/statements/querying/data-selection-and-projectionweekly0.5https://gluesql.org/docs/dev/ast-builder/statements/querying/data-sorting-and-limitingweekly0.5https://gluesql.org/docs/dev/ast-builder/statements/querying/fetching-data-from-storageweekly0.5https://gluesql.org/docs/dev/ast-builder/statements/querying/using-preloaded-dataweekly0.5https://gluesql.org/docs/dev/getting-started/cliweekly0.5https://gluesql.org/docs/dev/getting-started/javascript-webweekly0.5https://gluesql.org/docs/dev/getting-started/nodejsweekly0.5https://gluesql.org/docs/dev/getting-started/rustweekly0.5https://gluesql.org/docs/dev/sql-syntax/data-types/booleanweekly0.5https://gluesql.org/docs/dev/sql-syntax/data-types/byteaweekly0.5https://gluesql.org/docs/dev/sql-syntax/data-types/dateweekly0.5https://gluesql.org/docs/dev/sql-syntax/data-types/decimalweekly0.5https://gluesql.org/docs/dev/sql-syntax/data-types/floatweekly0.5https://gluesql.org/docs/dev/sql-syntax/data-types/inetweekly0.5https://gluesql.org/docs/dev/sql-syntax/data-types/integersweekly0.5https://gluesql.org/docs/dev/sql-syntax/data-types/intervalweekly0.5https://gluesql.org/docs/dev/sql-syntax/data-types/listweekly0.5https://gluesql.org/docs/dev/sql-syntax/data-types/mapweekly0.5https://gluesql.org/docs/dev/sql-syntax/data-types/textweekly0.5https://gluesql.org/docs/dev/sql-syntax/data-types/timeweekly0.5https://gluesql.org/docs/dev/sql-syntax/data-types/timestampweekly0.5https://gluesql.org/docs/dev/sql-syntax/data-types/uuidweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/datetime/extractweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/datetime/formatweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/datetime/nowweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/datetime/to-dateweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/datetime/to-timeweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/datetime/to-timestampweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/geometry/calc-distanceweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/geometry/get-xweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/geometry/get-yweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/geometry/pointweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/list-map/appendweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/list-map/concatweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/list-map/prependweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/math/absweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/math/acosweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/math/asinweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/math/atanweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/math/ceilweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/math/cosweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/math/degreesweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/math/divweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/math/expweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/math/floorweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/math/gcdweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/math/lcmweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/math/lnweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/math/logweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/math/log10weekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/math/log2weekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/math/modweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/math/piweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/math/powerweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/math/radiansweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/math/randweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/math/roundweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/math/signweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/math/sinweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/math/sqrtweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/math/tanweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/others/castweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/others/generate-uuidweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/others/ifnullweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/text/asciiweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/text/chrweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/text/concatweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/text/concat-wsweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/text/find-idxweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/text/initcapweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/text/leftweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/text/lowerweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/text/lpadweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/text/ltrimweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/text/positionweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/text/repeatweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/text/reverseweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/text/rightweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/text/rpadweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/text/rtrimweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/text/substrweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/text/trimweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/text/upperweekly0.5https://gluesql.org/docs/dev/sql-syntax/introweekly0.5https://gluesql.org/docs/dev/sql-syntax/statements/data-definition/alter-tableweekly0.5https://gluesql.org/docs/dev/sql-syntax/statements/data-definition/create-indexweekly0.5https://gluesql.org/docs/dev/sql-syntax/statements/data-definition/create-tableweekly0.5https://gluesql.org/docs/dev/sql-syntax/statements/data-definition/drop-indexweekly0.5https://gluesql.org/docs/dev/sql-syntax/statements/data-definition/drop-tableweekly0.5https://gluesql.org/docs/dev/sql-syntax/statements/data-manipulation/deleteweekly0.5https://gluesql.org/docs/dev/sql-syntax/statements/data-manipulation/insertweekly0.5https://gluesql.org/docs/dev/sql-syntax/statements/data-manipulation/updateweekly0.5https://gluesql.org/docs/dev/sql-syntax/statements/metadata/data-dictionaryweekly0.5https://gluesql.org/docs/dev/sql-syntax/statements/metadata/show-tablesweekly0.5https://gluesql.org/docs/dev/sql-syntax/statements/querying/aggregationweekly0.5https://gluesql.org/docs/dev/sql-syntax/statements/querying/joinweekly0.5https://gluesql.org/docs/dev/sql-syntax/statements/querying/limitweekly0.5https://gluesql.org/docs/dev/sql-syntax/statements/querying/schemalessweekly0.5https://gluesql.org/docs/dev/sql-syntax/statements/querying/whereweekly0.5https://gluesql.org/docs/dev/sql-syntax/statements/transactionweekly0.5https://gluesql.org/docs/dev/storages/developing-custom-storages/introweekly0.5https://gluesql.org/docs/dev/storages/developing-custom-storages/store-traits/alter-tableweekly0.5https://gluesql.org/docs/dev/storages/developing-custom-storages/store-traits/custom-functionweekly0.5https://gluesql.org/docs/dev/storages/developing-custom-storages/store-traits/custom-function-mutweekly0.5https://gluesql.org/docs/dev/storages/developing-custom-storages/store-traits/index-mutweekly0.5https://gluesql.org/docs/dev/storages/developing-custom-storages/store-traits/index-traitweekly0.5https://gluesql.org/docs/dev/storages/developing-custom-storages/store-traits/metadataweekly0.5https://gluesql.org/docs/dev/storages/developing-custom-storages/store-traits/storeweekly0.5https://gluesql.org/docs/dev/storages/developing-custom-storages/store-traits/store-mutweekly0.5https://gluesql.org/docs/dev/storages/developing-custom-storages/store-traits/transactionweekly0.5https://gluesql.org/docs/dev/storages/developing-custom-storages/using-test-suiteweekly0.5https://gluesql.org/docs/dev/storages/introweekly0.5https://gluesql.org/docs/dev/storages/supported-storages/composite-storageweekly0.5https://gluesql.org/docs/dev/storages/supported-storages/idb-storageweekly0.5https://gluesql.org/docs/dev/storages/supported-storages/json-storageweekly0.5https://gluesql.org/docs/dev/storages/supported-storages/memory-storageweekly0.5https://gluesql.org/docs/dev/storages/supported-storages/shared-memory-storageweekly0.5https://gluesql.org/docs/dev/storages/supported-storages/sled-storageweekly0.5https://gluesql.org/docs/dev/storages/supported-storages/web-storageweekly0.5 \ No newline at end of file +https://gluesql.org/docs/dev/blogweekly0.5https://gluesql.org/docs/dev/blog/archiveweekly0.5https://gluesql.org/docs/dev/blog/breaking-the-boundary-between-sql-and-nosqlweekly0.5https://gluesql.org/docs/dev/blog/release-v0.14weekly0.5https://gluesql.org/docs/dev/blog/revolutionizing-databases-by-unifying-query-interfacesweekly0.5https://gluesql.org/docs/dev/blog/tagsweekly0.5https://gluesql.org/docs/dev/blog/tags/automationweekly0.5https://gluesql.org/docs/dev/blog/tags/chat-gptweekly0.5https://gluesql.org/docs/dev/blog/tags/databaseweekly0.5https://gluesql.org/docs/dev/blog/tags/documentationweekly0.5https://gluesql.org/docs/dev/blog/tags/gluesqlweekly0.5https://gluesql.org/docs/dev/blog/tags/nosqlweekly0.5https://gluesql.org/docs/dev/blog/tags/proposalweekly0.5https://gluesql.org/docs/dev/blog/tags/query-interfaceweekly0.5https://gluesql.org/docs/dev/blog/tags/release-noteweekly0.5https://gluesql.org/docs/dev/blog/tags/sqlweekly0.5https://gluesql.org/docs/dev/blog/tags/tddweekly0.5https://gluesql.org/docs/dev/blog/tags/test-driven-documentationweekly0.5https://gluesql.org/docs/dev/blog/tags/v-0-14weekly0.5https://gluesql.org/docs/dev/blog/test-driven-documentationweekly0.5https://gluesql.org/docs/dev/weekly0.5https://gluesql.org/docs/dev/ast-builder/expressions/conditionalweekly0.5https://gluesql.org/docs/dev/ast-builder/expressions/nestedweekly0.5https://gluesql.org/docs/dev/ast-builder/expressions/operator-basedweekly0.5https://gluesql.org/docs/dev/ast-builder/expressions/pattern-matchingweekly0.5https://gluesql.org/docs/dev/ast-builder/expressions/value-checkingweekly0.5https://gluesql.org/docs/dev/ast-builder/functions/date-&-time/conversionweekly0.5https://gluesql.org/docs/dev/ast-builder/functions/date-&-time/current-date-and-timeweekly0.5https://gluesql.org/docs/dev/ast-builder/functions/date-&-time/date-and-time-extractionweekly0.5https://gluesql.org/docs/dev/ast-builder/functions/date-&-time/formattingweekly0.5https://gluesql.org/docs/dev/ast-builder/functions/geometry/coordinate-extractionweekly0.5https://gluesql.org/docs/dev/ast-builder/functions/geometry/distance-calculationweekly0.5https://gluesql.org/docs/dev/ast-builder/functions/geometry/point-creationweekly0.5https://gluesql.org/docs/dev/ast-builder/functions/list-&-map/list-and-map-concatenationweekly0.5https://gluesql.org/docs/dev/ast-builder/functions/list-&-map/list-manipulationweekly0.5https://gluesql.org/docs/dev/ast-builder/functions/math/basic-arithmeticweekly0.5https://gluesql.org/docs/dev/ast-builder/functions/math/conversionweekly0.5https://gluesql.org/docs/dev/ast-builder/functions/math/logarithmic-and-exponentialweekly0.5https://gluesql.org/docs/dev/ast-builder/functions/math/roundingweekly0.5https://gluesql.org/docs/dev/ast-builder/functions/math/special-mathematicalweekly0.5https://gluesql.org/docs/dev/ast-builder/functions/math/trigonometricweekly0.5https://gluesql.org/docs/dev/ast-builder/functions/others/null-handlingweekly0.5https://gluesql.org/docs/dev/ast-builder/functions/others/type-conversionweekly0.5https://gluesql.org/docs/dev/ast-builder/functions/others/unique-identifierweekly0.5https://gluesql.org/docs/dev/ast-builder/functions/text/case-conversionweekly0.5https://gluesql.org/docs/dev/ast-builder/functions/text/character-conversionweekly0.5https://gluesql.org/docs/dev/ast-builder/functions/text/paddingweekly0.5https://gluesql.org/docs/dev/ast-builder/functions/text/position-and-indexingweekly0.5https://gluesql.org/docs/dev/ast-builder/functions/text/text-manipulationweekly0.5https://gluesql.org/docs/dev/ast-builder/functions/text/trimmingweekly0.5https://gluesql.org/docs/dev/ast-builder/introweekly0.5https://gluesql.org/docs/dev/ast-builder/statements/data-manipulation/deleting-dataweekly0.5https://gluesql.org/docs/dev/ast-builder/statements/data-manipulation/inserting-dataweekly0.5https://gluesql.org/docs/dev/ast-builder/statements/data-manipulation/updating-dataweekly0.5https://gluesql.org/docs/dev/ast-builder/statements/querying/creating-derived-subqueriesweekly0.5https://gluesql.org/docs/dev/ast-builder/statements/querying/data-aggregationweekly0.5https://gluesql.org/docs/dev/ast-builder/statements/querying/data-injectionweekly0.5https://gluesql.org/docs/dev/ast-builder/statements/querying/data-joiningweekly0.5https://gluesql.org/docs/dev/ast-builder/statements/querying/data-selection-and-projectionweekly0.5https://gluesql.org/docs/dev/ast-builder/statements/querying/data-sorting-and-limitingweekly0.5https://gluesql.org/docs/dev/ast-builder/statements/querying/fetching-data-from-storageweekly0.5https://gluesql.org/docs/dev/ast-builder/statements/querying/using-preloaded-dataweekly0.5https://gluesql.org/docs/dev/getting-started/cliweekly0.5https://gluesql.org/docs/dev/getting-started/javascript-webweekly0.5https://gluesql.org/docs/dev/getting-started/nodejsweekly0.5https://gluesql.org/docs/dev/getting-started/rustweekly0.5https://gluesql.org/docs/dev/sql-syntax/data-types/booleanweekly0.5https://gluesql.org/docs/dev/sql-syntax/data-types/byteaweekly0.5https://gluesql.org/docs/dev/sql-syntax/data-types/dateweekly0.5https://gluesql.org/docs/dev/sql-syntax/data-types/decimalweekly0.5https://gluesql.org/docs/dev/sql-syntax/data-types/floatweekly0.5https://gluesql.org/docs/dev/sql-syntax/data-types/inetweekly0.5https://gluesql.org/docs/dev/sql-syntax/data-types/integersweekly0.5https://gluesql.org/docs/dev/sql-syntax/data-types/intervalweekly0.5https://gluesql.org/docs/dev/sql-syntax/data-types/listweekly0.5https://gluesql.org/docs/dev/sql-syntax/data-types/mapweekly0.5https://gluesql.org/docs/dev/sql-syntax/data-types/textweekly0.5https://gluesql.org/docs/dev/sql-syntax/data-types/timeweekly0.5https://gluesql.org/docs/dev/sql-syntax/data-types/timestampweekly0.5https://gluesql.org/docs/dev/sql-syntax/data-types/uuidweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/datetime/extractweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/datetime/formatweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/datetime/nowweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/datetime/to-dateweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/datetime/to-timeweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/datetime/to-timestampweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/geometry/calc-distanceweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/geometry/get-xweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/geometry/get-yweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/geometry/pointweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/list-map/appendweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/list-map/concatweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/list-map/prependweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/list-map/spliceweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/math/absweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/math/acosweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/math/asinweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/math/atanweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/math/ceilweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/math/cosweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/math/degreesweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/math/divweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/math/expweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/math/floorweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/math/gcdweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/math/lcmweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/math/lnweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/math/logweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/math/log10weekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/math/log2weekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/math/modweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/math/piweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/math/powerweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/math/radiansweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/math/randweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/math/roundweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/math/signweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/math/sinweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/math/sqrtweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/math/tanweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/others/castweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/others/generate-uuidweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/others/ifnullweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/text/asciiweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/text/chrweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/text/concatweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/text/concat-wsweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/text/find-idxweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/text/initcapweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/text/leftweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/text/lowerweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/text/lpadweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/text/ltrimweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/text/positionweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/text/repeatweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/text/reverseweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/text/rightweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/text/rpadweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/text/rtrimweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/text/substrweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/text/trimweekly0.5https://gluesql.org/docs/dev/sql-syntax/functions/text/upperweekly0.5https://gluesql.org/docs/dev/sql-syntax/introweekly0.5https://gluesql.org/docs/dev/sql-syntax/statements/data-definition/alter-tableweekly0.5https://gluesql.org/docs/dev/sql-syntax/statements/data-definition/create-indexweekly0.5https://gluesql.org/docs/dev/sql-syntax/statements/data-definition/create-tableweekly0.5https://gluesql.org/docs/dev/sql-syntax/statements/data-definition/drop-indexweekly0.5https://gluesql.org/docs/dev/sql-syntax/statements/data-definition/drop-tableweekly0.5https://gluesql.org/docs/dev/sql-syntax/statements/data-manipulation/deleteweekly0.5https://gluesql.org/docs/dev/sql-syntax/statements/data-manipulation/insertweekly0.5https://gluesql.org/docs/dev/sql-syntax/statements/data-manipulation/updateweekly0.5https://gluesql.org/docs/dev/sql-syntax/statements/metadata/data-dictionaryweekly0.5https://gluesql.org/docs/dev/sql-syntax/statements/metadata/show-tablesweekly0.5https://gluesql.org/docs/dev/sql-syntax/statements/querying/aggregationweekly0.5https://gluesql.org/docs/dev/sql-syntax/statements/querying/joinweekly0.5https://gluesql.org/docs/dev/sql-syntax/statements/querying/limitweekly0.5https://gluesql.org/docs/dev/sql-syntax/statements/querying/schemalessweekly0.5https://gluesql.org/docs/dev/sql-syntax/statements/querying/whereweekly0.5https://gluesql.org/docs/dev/sql-syntax/statements/transactionweekly0.5https://gluesql.org/docs/dev/storages/developing-custom-storages/introweekly0.5https://gluesql.org/docs/dev/storages/developing-custom-storages/store-traits/alter-tableweekly0.5https://gluesql.org/docs/dev/storages/developing-custom-storages/store-traits/custom-functionweekly0.5https://gluesql.org/docs/dev/storages/developing-custom-storages/store-traits/custom-function-mutweekly0.5https://gluesql.org/docs/dev/storages/developing-custom-storages/store-traits/index-mutweekly0.5https://gluesql.org/docs/dev/storages/developing-custom-storages/store-traits/index-traitweekly0.5https://gluesql.org/docs/dev/storages/developing-custom-storages/store-traits/metadataweekly0.5https://gluesql.org/docs/dev/storages/developing-custom-storages/store-traits/storeweekly0.5https://gluesql.org/docs/dev/storages/developing-custom-storages/store-traits/store-mutweekly0.5https://gluesql.org/docs/dev/storages/developing-custom-storages/store-traits/transactionweekly0.5https://gluesql.org/docs/dev/storages/developing-custom-storages/using-test-suiteweekly0.5https://gluesql.org/docs/dev/storages/introweekly0.5https://gluesql.org/docs/dev/storages/supported-storages/composite-storageweekly0.5https://gluesql.org/docs/dev/storages/supported-storages/idb-storageweekly0.5https://gluesql.org/docs/dev/storages/supported-storages/json-storageweekly0.5https://gluesql.org/docs/dev/storages/supported-storages/memory-storageweekly0.5https://gluesql.org/docs/dev/storages/supported-storages/shared-memory-storageweekly0.5https://gluesql.org/docs/dev/storages/supported-storages/sled-storageweekly0.5https://gluesql.org/docs/dev/storages/supported-storages/web-storageweekly0.5 \ No newline at end of file diff --git a/docs/dev/sql-syntax/data-types/boolean/index.html b/docs/dev/sql-syntax/data-types/boolean/index.html index 2f302073..de065fc0 100644 --- a/docs/dev/sql-syntax/data-types/boolean/index.html +++ b/docs/dev/sql-syntax/data-types/boolean/index.html @@ -1,17 +1,17 @@ - + - + BOOLEAN | GlueSQL - - - + + +

BOOLEAN

The BOOLEAN data type in SQL is used to store boolean values, which can be either TRUE or FALSE. This data type is useful for representing binary states or conditions in your data.

Here's an example of how to create a table, insert data, and query data using the BOOLEAN data type:

Creating a table with a BOOLEAN column

To create a table with a BOOLEAN column, use the following SQL syntax:

CREATE TABLE user_active (username TEXT, is_active BOOLEAN);

Inserting data into the BOOLEAN column

To insert data into the BOOLEAN column, provide the boolean values as TRUE or FALSE:

INSERT INTO user_active (username, is_active) VALUES
('user1', TRUE),
('user2', FALSE),
('user3', TRUE);

Querying data from the BOOLEAN column

To query data from the BOOLEAN column, use standard SQL syntax:

SELECT username, is_active FROM user_active;

This query will return the following result:

username | is_active
---------|----------
user1 | TRUE
user2 | FALSE
user3 | TRUE

Casting between BOOLEAN and INTEGER

You can cast between BOOLEAN and INTEGER values:

  • When casting a BOOLEAN to an INTEGER, TRUE becomes 1 and FALSE becomes 0.
  • When casting an INTEGER to a BOOLEAN, 1 becomes TRUE and 0 becomes FALSE. Other integer values will result in an error.

Example:

SELECT CAST(1 AS BOOLEAN); -- Result: TRUE
SELECT CAST(0 AS BOOLEAN); -- Result: FALSE
SELECT CAST(TRUE AS INTEGER); -- Result: 1
SELECT CAST(FALSE AS INTEGER); -- Result: 0

Note that casting negative integers or integers greater than 1 to BOOLEAN will result in an error.

Conclusion

In summary, the BOOLEAN data type is a simple yet powerful way to represent binary states in SQL databases. With its ability to store TRUE and FALSE values, it can be used in various applications where binary conditions are necessary. Additionally, its compatibility with casting to and from INTEGER values provides added flexibility in data manipulation and querying. By understanding the basics of the BOOLEAN data type and its use cases, you can effectively use it in your database designs and operations.

- - + + \ No newline at end of file diff --git a/docs/dev/sql-syntax/data-types/bytea/index.html b/docs/dev/sql-syntax/data-types/bytea/index.html index cf95b703..eb4d0ee5 100644 --- a/docs/dev/sql-syntax/data-types/bytea/index.html +++ b/docs/dev/sql-syntax/data-types/bytea/index.html @@ -1,17 +1,17 @@ - + - + BYTEA | GlueSQL - - - + + +

BYTEA

The BYTEA data type in SQL is used to store binary data, such as images, audio files, or any other type of data that needs to be stored in its raw form. In GlueSQL, the BYTEA data type is represented as a sequence of bytes.

Here's an example of how to create a table, insert data, and query data using the BYTEA data type:

Creating a table with a BYTEA column

To create a table with a BYTEA column, use the following SQL syntax:

CREATE TABLE binary_data (data BYTEA);

Inserting data into the BYTEA column

To insert data into the BYTEA column, provide the binary data in hexadecimal format using the X prefix:

INSERT INTO binary_data (data) VALUES
(X'123456'),
(X'ab0123'),
(X'936DA0');

Please note that the hexadecimal string must have an even number of characters, or an error will be thrown.

Querying data from the BYTEA column

To query data from the BYTEA column, use standard SQL syntax:

SELECT data FROM binary_data;

This query will return the following result:

data
----------------
123456
ab0123
936DA0

Error handling

When inserting data into the BYTEA column, you may encounter errors due to incompatible data types or incorrectly formatted hexadecimal strings. For example, inserting a regular integer or an odd-length hexadecimal string will result in an error:

INSERT INTO binary_data (data) VALUES (0);
-- Error: Incompatible literal for data type BYTEA

INSERT INTO binary_data (data) VALUES (X'123');
-- Error: Failed to decode hexadecimal string

Conclusion

The BYTEA data type is essential for storing binary data in SQL databases. By understanding the basics of the BYTEA data type and its use cases, you can effectively use it in your database designs and operations, ensuring that your applications can manage binary data efficiently and securely.

- - + + \ No newline at end of file diff --git a/docs/dev/sql-syntax/data-types/date/index.html b/docs/dev/sql-syntax/data-types/date/index.html index 1b936bc8..5d1fa649 100644 --- a/docs/dev/sql-syntax/data-types/date/index.html +++ b/docs/dev/sql-syntax/data-types/date/index.html @@ -1,17 +1,17 @@ - + - + DATE | GlueSQL - - - + + +

DATE

In GlueSQL, the DATE data type is used to store date values in the format 'YYYY-MM-DD'. Note that GlueSQL currently does not support timezones.

Creating a table with DATE columns

To create a table with columns of type DATE, use the CREATE TABLE statement:

CREATE TABLE DateLog (
id INTEGER,
date1 DATE,
date2 DATE
);

Inserting data into a table with DATE columns

To insert data into a table with DATE columns, use the INSERT INTO statement:

INSERT INTO DateLog VALUES
(1, '2020-06-11', '2021-03-01'),
(2, '2020-09-30', '1989-01-01'),
(3, '2021-05-01', '2021-05-01');

Querying data from a table with DATE columns

To query data from a table with DATE columns, use the SELECT statement:

SELECT id, date1, date2 FROM DateLog;

Filtering data using DATE columns

You can use various comparison operators like >, <, <=, >=, and = to filter data based on DATE columns:

SELECT * FROM DateLog WHERE date1 > date2;

SELECT * FROM DateLog WHERE date1 <= date2;

SELECT * FROM DateLog WHERE date1 = DATE '2020-06-11';

SELECT * FROM DateLog WHERE date2 < '2000-01-01';

SELECT * FROM DateLog WHERE '1999-01-03' < DATE '2000-01-01';

Performing date arithmetic

You can perform arithmetic operations on DATE columns using INTERVAL and various date arithmetic operators:

SELECT
id,
date1 - date2 AS date_sub,
date1 - INTERVAL '1' DAY AS sub,
date2 + INTERVAL '1' MONTH AS add
FROM DateLog;

Handling invalid date values

If you try to insert an invalid date value into a DATE column, GlueSQL will return an error:

INSERT INTO DateLog VALUES (1, '12345-678', '2021-05-01');

This will result in an error similar to the following:

failed to parse date 12345-678

Conclusion

In summary, the DATE data type in GlueSQL allows you to store and manipulate date values in your database. You can create tables with DATE columns, insert and query data, filter data based on date comparisons, and perform date arithmetic using various operators and intervals. Always remember to use valid date formats when inserting data into DATE columns to avoid errors.

- - + + \ No newline at end of file diff --git a/docs/dev/sql-syntax/data-types/decimal/index.html b/docs/dev/sql-syntax/data-types/decimal/index.html index 5f1770a6..2435895e 100644 --- a/docs/dev/sql-syntax/data-types/decimal/index.html +++ b/docs/dev/sql-syntax/data-types/decimal/index.html @@ -1,17 +1,17 @@ - + - + DECIMAL | GlueSQL - - - + + +

DECIMAL

The DECIMAL data type in SQL is used to store exact numeric values, making it suitable for financial calculations and other operations requiring a high level of precision without round-off errors. In GlueSQL, the DECIMAL data type is implemented using a pure Rust library, providing a 96-bit integer number, a scaling factor for specifying the decimal fraction, and a 1-bit sign.

Here's an example of how to create a table, insert data, and query data using the DECIMAL data type:

Creating a table with a DECIMAL column

To create a table with a DECIMAL column, use the following SQL syntax:

CREATE TABLE financial_data (description TEXT, value DECIMAL);

Inserting data into the DECIMAL column

To insert data into the DECIMAL column, provide the exact numeric values:

INSERT INTO financial_data (description, value) VALUES
('Revenue', 15000.25),
('Expense', 12000.75),
('Profit', 2999.50);

Querying data from the DECIMAL column

To query data from the DECIMAL column, use standard SQL syntax:

SELECT description, value FROM financial_data;

This query will return the following result:

description | value
------------|---------
Revenue | 15000.25
Expense | 12000.75
Profit | 2999.50

Truncating trailing zeros

In GlueSQL's DECIMAL implementation, trailing zeros are preserved in the binary representation and may be exposed when converting the value to a string. To truncate trailing zeros, you can use the normalize or round_dp functions in Rust.

Conclusion

The DECIMAL data type is crucial for handling precise numeric values in SQL databases, especially in financial calculations and other applications requiring high accuracy without round-off errors. By understanding the basics of the DECIMAL data type and its use cases, you can effectively use it in your database designs and operations, ensuring that your applications can manage exact numeric values with precision.

- - + + \ No newline at end of file diff --git a/docs/dev/sql-syntax/data-types/float/index.html b/docs/dev/sql-syntax/data-types/float/index.html index 2107d80f..7d3dadd3 100644 --- a/docs/dev/sql-syntax/data-types/float/index.html +++ b/docs/dev/sql-syntax/data-types/float/index.html @@ -1,17 +1,17 @@ - + - + FLOAT | GlueSQL - - - + + +

FLOAT

The FLOAT data type in SQL is used to store floating-point numbers. In GlueSQL, the FLOAT data type represents a 64-bit floating-point number, providing the ability to store numbers with decimal values and a wide range of magnitude.

Here's an example of how to create a table, insert data, and query data using the FLOAT data type:

Creating a table with a FLOAT column

To create a table with a FLOAT column, use the following SQL syntax:

CREATE TABLE product_prices (product_name TEXT, price FLOAT);

Inserting data into the FLOAT column

To insert data into the FLOAT column, provide the floating-point values:

INSERT INTO product_prices (product_name, price) VALUES
('Product A', 19.99),
('Product B', 39.49),
('Product C', 12.75);

Querying data from the FLOAT column

To query data from the FLOAT column, use standard SQL syntax:

SELECT product_name, price FROM product_prices;

This query will return the following result:

product_name | price
-------------|-------
Product A | 19.99
Product B | 39.49
Product C | 12.75

Conclusion

The FLOAT data type is essential for handling numeric data with decimal values and various magnitudes. By understanding the basics of the FLOAT data type and its use cases, you can effectively use it in your database designs and operations, ensuring that your applications can handle a wide range of numerical values with precision.

- - + + \ No newline at end of file diff --git a/docs/dev/sql-syntax/data-types/inet/index.html b/docs/dev/sql-syntax/data-types/inet/index.html index d0d8c989..36d791a7 100644 --- a/docs/dev/sql-syntax/data-types/inet/index.html +++ b/docs/dev/sql-syntax/data-types/inet/index.html @@ -1,17 +1,17 @@ - + - + INET | GlueSQL - - - + + +

INET

The INET data type in SQL is used to store IPv4 and IPv6 addresses. These addresses can be compared, filtered, and sorted using standard SQL operations.

Here's an example of how to create a table, insert data, and query data using the INET data type:

Creating a table with an INET column

To create a table with an INET column, use the following SQL syntax:

CREATE TABLE computer (ip INET);

Inserting data into the INET column

To insert data into the INET column, provide the IP addresses as strings or integers:

INSERT INTO computer VALUES
('::1'),
('127.0.0.1'),
('0.0.0.0'),
(4294967295),
(9876543210);

Querying data from the INET column

To query data from the INET column, use standard SQL syntax:

SELECT * FROM computer;

This query will return the following result:

ip
-----------------
::1
127.0.0.1
0.0.0.0
255.255.255.255
::2:4cb0:16ea

Filtering data using the INET column

You can filter data using the INET column with standard SQL operators:

SELECT * FROM computer WHERE ip > '127.0.0.1';

This query will return the following result:

ip
-----------------
::1
255.255.255.255
::2:4cb0:16ea

Querying for specific IP addresses

To query for specific IP addresses, use the following syntax:

SELECT * FROM computer WHERE ip = '127.0.0.1';

This query will return the following result:

ip
---------
127.0.0.1
- - + + \ No newline at end of file diff --git a/docs/dev/sql-syntax/data-types/integers/index.html b/docs/dev/sql-syntax/data-types/integers/index.html index 0a522aa6..388fc0c8 100644 --- a/docs/dev/sql-syntax/data-types/integers/index.html +++ b/docs/dev/sql-syntax/data-types/integers/index.html @@ -1,17 +1,17 @@ - + - + Integer Types | GlueSQL - - - + + +

Integer Types

GlueSQL supports the following integer data types:

  • INT8: 8-bit signed integer
  • INT16: 16-bit signed integer
  • INT32: 32-bit signed integer
  • INT or INTEGER: 64-bit signed integer (default)
  • INT128: 128-bit signed integer
  • UINT8: 8-bit unsigned integer
  • UINT16: 16-bit unsigned integer
  • UINT32: 32-bit unsigned integer
  • UINT64: 64-bit unsigned integer
  • UINT128: 128-bit unsigned integer

For general purposes, you can use INTEGER to specify a 64-bit signed integer.

Here's an example of how to create a table with integer data types:

CREATE TABLE Item (
field_one INTEGER,
field_two INTEGER
);

You can insert data into the Item table as follows:

INSERT INTO Item VALUES (1, -1), (-2, 2), (3, 3), (-4, -4);

You can perform arithmetic operations such as addition, subtraction, multiplication, division, and modulo on integer columns. Note that if you perform arithmetic operations on columns with different integer types, GlueSQL will automatically convert the types of the operands to match the type of the left-hand operand. For example, if you perform UINT8 + INT64, GlueSQL will convert the INT64 operand to UINT8 and then perform the addition.

Integer types are an important part of SQL, and you can use them to store data ranging from small whole numbers to large integers. By understanding how to use integer types in your database, you can write efficient and effective SQL queries that work with a wide range of data.

- - + + \ No newline at end of file diff --git a/docs/dev/sql-syntax/data-types/interval/index.html b/docs/dev/sql-syntax/data-types/interval/index.html index e7dd651d..c0726bfc 100644 --- a/docs/dev/sql-syntax/data-types/interval/index.html +++ b/docs/dev/sql-syntax/data-types/interval/index.html @@ -1,17 +1,17 @@ - + - + INTERVAL | GlueSQL - - - + + +

INTERVAL

The INTERVAL data type in GlueSQL is used to represent a period of time. In accordance with the ANSI SQL standard, several subtypes of INTERVAL can be used to represent different units of time, such as years, months, days, hours, minutes, and seconds. These subtypes are:

  • YEAR
  • YEAR TO MONTH
  • MONTH
  • DAY
  • DAY TO HOUR
  • DAY TO MINUTE
  • DAY TO SECOND
  • HOUR
  • HOUR TO MINUTE
  • HOUR TO SECOND
  • MINUTE
  • MINUTE TO SECOND
  • SECOND

Creating a Table with INTERVAL Columns

To create a table with INTERVAL columns, simply use the INTERVAL keyword for the data type:

CREATE TABLE IntervalLog (
id INTEGER,
interval1 INTERVAL,
interval2 INTERVAL
);

Inserting INTERVAL Values

To insert INTERVAL values into a table, use the INTERVAL keyword followed by a string literal representing the interval value:

INSERT INTO IntervalLog VALUES
(1, INTERVAL '1-2' YEAR TO MONTH, INTERVAL 30 MONTH),
(2, INTERVAL 12 DAY, INTERVAL '35' HOUR),
(3, INTERVAL '12' MINUTE, INTERVAL 300 SECOND),
(4, INTERVAL '-3 14' DAY TO HOUR, INTERVAL '3 12:30' DAY TO MINUTE),
(5, INTERVAL '3 14:00:00' DAY TO SECOND, INTERVAL '3 12:30:12.1324' DAY TO SECOND),
(6, INTERVAL '12:00' HOUR TO MINUTE, INTERVAL '-12:30:12' HOUR TO SECOND),
(7, INTERVAL '-1000-11' YEAR TO MONTH, INTERVAL '-30:11' MINUTE TO SECOND);

INTERVAL Subtypes and Syntax

Here are some examples of how to use different INTERVAL subtypes:

  • YEAR: INTERVAL '5' YEAR
  • YEAR TO MONTH: INTERVAL '5-3' YEAR TO MONTH
  • MONTH: INTERVAL '6' MONTH
  • DAY: INTERVAL '7' DAY
  • DAY TO HOUR: INTERVAL '2 12' DAY TO HOUR
  • DAY TO MINUTE: INTERVAL '2 12:30' DAY TO MINUTE
  • DAY TO SECOND: INTERVAL '2 12:30:45' DAY TO SECOND
  • HOUR: INTERVAL '18' HOUR
  • HOUR TO MINUTE: INTERVAL '18:30' HOUR TO MINUTE
  • HOUR TO SECOND: INTERVAL '18:30:45' HOUR TO SECOND
  • MINUTE: INTERVAL '45' MINUTE
  • MINUTE TO SECOND: INTERVAL '45:30' MINUTE TO SECOND
  • SECOND: INTERVAL '30' SECOND

Unsupported Conversions

In GlueSQL, you cannot convert between different INTERVAL subtypes, such as converting 1 MONTH to DAYS or converting YEAR TO MONTH to DAY TO SECOND. These conversions are not supported.

Conclusion

The INTERVAL data type is a powerful way to represent time periods in GlueSQL. By following the ANSI SQL standard, you can use a combination of subtypes to represent complex periods of time. Use the INTERVAL keyword when creating tables and inserting values to make the most of this data type.

- - + + \ No newline at end of file diff --git a/docs/dev/sql-syntax/data-types/list/index.html b/docs/dev/sql-syntax/data-types/list/index.html index 4555f15c..03c2eecd 100644 --- a/docs/dev/sql-syntax/data-types/list/index.html +++ b/docs/dev/sql-syntax/data-types/list/index.html @@ -1,17 +1,17 @@ - + - + LIST | GlueSQL - - - + + +

LIST

The LIST data type in GlueSQL is used to store ordered collections of elements, similar to JSON arrays. The elements can be any valid data supported by GlueSQL, such as numbers, strings, booleans, null, MAP, or even other nested LIST values. Although the input is provided in a JSON array format for convenience, it can store more than just JSON data.

Here is an example of creating a table with a LIST data type:

CREATE TABLE ListType (
id INTEGER,
items LIST
);

You can insert data into the table using JSON-like syntax:

INSERT INTO ListType VALUES
(1, '[1, 2, 3]'),
(2, '["hello", "world", 30, true, [9,8]]'),
(3, '[{ "foo": 100, "bar": [true, 0, [10.5, false] ] }, 10, 20]');

To access the elements in a LIST, you can use the index operator []:

SELECT id, items[1] AS second FROM ListType;

This query would return the following result:

 id | second
----|--------
1 | 2
2 | world
3 | 10

You can also access nested elements using the index operator, like this:

SELECT id, items[3][0] AS hundred FROM ListType2;

This query would return the following result:

 id | hundred
----|--------
1 | null
2 | 100
3 | null

If a specified index is out of range or the element is not a MAP or LIST, the result will be null.

- - + + \ No newline at end of file diff --git a/docs/dev/sql-syntax/data-types/map/index.html b/docs/dev/sql-syntax/data-types/map/index.html index f33ee317..02f5a3d6 100644 --- a/docs/dev/sql-syntax/data-types/map/index.html +++ b/docs/dev/sql-syntax/data-types/map/index.html @@ -1,17 +1,17 @@ - + - + MAP | GlueSQL - - - + + +

MAP

The MAP data type in GlueSQL is used to store nested key-value pairs, similar to JSON objects. The object keys must be strings, and the values can be any valid data supported by GlueSQL, such as numbers, strings, booleans, null, or even other nested MAP values. Although the input is provided in a JSON object format for convenience, it can store more than just JSON data.

Here is an example of creating a table with a MAP data type:

CREATE TABLE MapType (
id INTEGER,
nested MAP
);

You can insert data into the table using JSON-like syntax:

INSERT INTO MapType VALUES
(1, '{"a": true, "b": 2}'),
(2, '{"a": {"foo": "ok", "b": "steak"}, "b": 30}'),
(3, '{"a": {"b": {"c": {"d": 10}}}}');

To access the nested values in a MAP, you can use the index operator []:

SELECT id, nested['a']['foo'] AS foo FROM MapType;

This query would return the following result:

 id | foo
----|-----
1 | null
2 | ok
3 | null

You can also perform arithmetic operations on nested values, like this:

SELECT id, nested['a']['b']['c']['d'] * 2 AS good2 FROM MapType;

This query would return the following result:

 id | good2
----|------
1 | null
2 | null
3 | 20

If a specified key does not exist in the MAP, the result will be null.

- - + + \ No newline at end of file diff --git a/docs/dev/sql-syntax/data-types/text/index.html b/docs/dev/sql-syntax/data-types/text/index.html index 5ce091c0..e75ef40f 100644 --- a/docs/dev/sql-syntax/data-types/text/index.html +++ b/docs/dev/sql-syntax/data-types/text/index.html @@ -1,17 +1,17 @@ - + - + TEXT | GlueSQL - - - + + +

TEXT

The TEXT data type in SQL is used to store variable-length character strings. In GlueSQL, the TEXT data type is the only supported string data type, providing the ability to store and manage strings of varying lengths.

Here's an example of how to create a table, insert data, and query data using the TEXT data type:

Creating a table with a TEXT column

To create a table with a TEXT column, use the following SQL syntax:

CREATE TABLE users (username TEXT, email TEXT);

Inserting data into the TEXT column

To insert data into the TEXT column, provide the string values:

INSERT INTO users (username, email) VALUES
('user1', 'user1@example.com'),
('user2', 'user2@example.com'),
('user3', 'user3@example.com');

Querying data from the TEXT column

To query data from the TEXT column, use standard SQL syntax:

SELECT username, email FROM users;

This query will return the following result:

username | email
---------|-------------------
user1 | user1@example.com
user2 | user2@example.com
user3 | user3@example.com

Conclusion

The TEXT data type is a versatile and essential data type for handling and storing character strings in SQL databases. By understanding the basics of the TEXT data type and its use cases, you can effectively use it in your database designs and operations, ensuring that your applications can manage a wide range of textual data with ease.

- - + + \ No newline at end of file diff --git a/docs/dev/sql-syntax/data-types/time/index.html b/docs/dev/sql-syntax/data-types/time/index.html index bc7edfd0..1f9f2508 100644 --- a/docs/dev/sql-syntax/data-types/time/index.html +++ b/docs/dev/sql-syntax/data-types/time/index.html @@ -1,17 +1,17 @@ - + - + TIME | GlueSQL - - - + + +

TIME

In GlueSQL, the TIME data type is used to store time values in the format 'HH:MM:SS.SSS'. The code snippet provided demonstrates how to create a table with TIME columns, insert data into it, and perform various queries and operations on the data.

Creating a table with TIME columns

To create a table with columns of type TIME, use the CREATE TABLE statement:

CREATE TABLE TimeLog (
id INTEGER,
time1 TIME,
time2 TIME
);

Inserting data into a table with TIME columns

To insert data into a table with TIME columns, use the INSERT INTO statement:

INSERT INTO TimeLog VALUES
(1, '12:30:00', '13:31:01.123'),
(2, '9:2:1', 'AM 08:02:01.001'),
(3, 'PM 2:59', '9:00:00 AM');

Querying data from a table with TIME columns

To query data from a table with TIME columns, use the SELECT statement:

SELECT id, time1, time2 FROM TimeLog;

Filtering data using TIME columns

You can use various comparison operators like >, <, <=, >=, and = to filter data based on TIME columns:

SELECT * FROM TimeLog WHERE time1 > time2;

SELECT * FROM TimeLog WHERE time1 <= time2;

SELECT * FROM TimeLog WHERE time1 = TIME '14:59:00';

SELECT * FROM TimeLog WHERE time1 < '1:00 PM';

Performing time arithmetic

You can perform arithmetic operations on TIME columns using INTERVAL:

SELECT
id,
time1 - time2 AS time_sub,
time1 + INTERVAL '1' HOUR AS add,
time2 - INTERVAL '250' MINUTE AS sub
FROM TimeLog;

You can also add a TIME column to a DATE value to get a TIMESTAMP result:

SELECT
id,
DATE '2021-01-05' + time2 AS timestamp
FROM TimeLog LIMIT 1;

Handling invalid time values

If you try to insert an invalid time value into a TIME column, GlueSQL will return an error:

INSERT INTO TimeLog VALUES (1, '12345-678', '20:05:01');

This will result in an error similar to the following:

failed to parse time 12345-678

Conclusion

In GlueSQL, the TIME data type is used to store time values in the format 'HH:MM:SS.SSS'. The provided code snippet demonstrates how to create a table with TIME columns, insert data into it, and perform various queries and operations on the data. GlueSQL supports arithmetic operations on TIME columns using INTERVAL, and you can also add a TIME column to a DATE value to get a TIMESTAMP result. Keep in mind that inserting invalid time values into a TIME column will result in an error.

- - + + \ No newline at end of file diff --git a/docs/dev/sql-syntax/data-types/timestamp/index.html b/docs/dev/sql-syntax/data-types/timestamp/index.html index 6f6a4457..69ad1794 100644 --- a/docs/dev/sql-syntax/data-types/timestamp/index.html +++ b/docs/dev/sql-syntax/data-types/timestamp/index.html @@ -1,17 +1,17 @@ - + - + TIMESTAMP | GlueSQL - - - + + +

TIMESTAMP

In GlueSQL, the TIMESTAMP data type is used to store date and time values in the format 'YYYY-MM-DD HH:MM:SS.SSSS'. Although timezone information can be included in the input string, GlueSQL stores all TIMESTAMP values in UTC, discarding the timezone information.

Creating a table with TIMESTAMP columns

To create a table with columns of type TIMESTAMP, use the CREATE TABLE statement:

CREATE TABLE TimestampLog (
id INTEGER,
t1 TIMESTAMP,
t2 TIMESTAMP
);

Inserting data into a table with TIMESTAMP columns

To insert data into a table with TIMESTAMP columns, use the INSERT INTO statement:

INSERT INTO TimestampLog VALUES
(1, '2020-06-11 11:23:11Z', '2021-03-01'),
(2, '2020-09-30 12:00:00 -07:00', '1989-01-01T00:01:00+09:00'),
(3, '2021-04-30T07:00:00.1234-17:00', '2021-05-01T09:00:00.1234+09:00');

The input strings include timezone information, but GlueSQL will convert and store them as UTC timestamps.

Querying data from a table with TIMESTAMP columns

To query data from a table with TIMESTAMP columns, use the SELECT statement:

SELECT id, t1, t2 FROM TimestampLog;

Filtering data using TIMESTAMP columns

You can use various comparison operators like >, <, <=, >=, and = to filter data based on TIMESTAMP columns:

SELECT * FROM TimestampLog WHERE t1 > t2;

SELECT * FROM TimestampLog WHERE t1 = t2;

SELECT * FROM TimestampLog WHERE t1 = '2020-06-11T14:23:11+0300';

SELECT * FROM TimestampLog WHERE t2 < TIMESTAMP '2000-01-01';

Performing timestamp arithmetic

You can perform arithmetic operations on TIMESTAMP columns using INTERVAL:

SELECT id, t1 - t2 AS timestamp_sub FROM TimestampLog;

SELECT
id,
t1 - INTERVAL '1' DAY AS sub,
t2 + INTERVAL '1' MONTH AS add
FROM TimestampLog;

Handling invalid timestamp values

If you try to insert an invalid timestamp value into a TIMESTAMP column, GlueSQL will return an error:

INSERT INTO TimestampLog VALUES (1, '12345-678', '2021-05-01');

This will result in an error similar to the following:

failed to parse timestamp: 12345-678

Conclusion

In GlueSQL, the TIMESTAMP data type allows you to store date and time values with precision up to milliseconds. The provided code snippet demonstrates how to create a table with TIMESTAMP columns, insert data into it, and perform various queries and operations on the data. When inserting a TIMESTAMP value, the timezone information is removed, and the data is stored in UTC. This ensures that all time values are consistent and can be easily converted to different time zones when needed.

- - + + \ No newline at end of file diff --git a/docs/dev/sql-syntax/data-types/uuid/index.html b/docs/dev/sql-syntax/data-types/uuid/index.html index e82d5452..1d463835 100644 --- a/docs/dev/sql-syntax/data-types/uuid/index.html +++ b/docs/dev/sql-syntax/data-types/uuid/index.html @@ -1,17 +1,17 @@ - + - + UUID | GlueSQL - - - + + +

UUID

The UUID data type in SQL is used to store universally unique identifiers (UUIDs). These identifiers can be compared, filtered, and sorted using standard SQL operations.

Here's an example of how to create a table, insert data, and query data using the UUID data type:

Creating a table with a UUID column

To create a table with a UUID column, use the following SQL syntax:

CREATE TABLE UUID (uuid_field UUID);

Inserting data into the UUID column

To insert data into the UUID column, provide the UUIDs as strings or in the format X'<hexadecimal_value>'. You can also use the urn:uuid: prefix. Note that providing a UUID as a plain number is not supported and will result in an error.

INSERT INTO UUID VALUES
(X'936DA01F9ABD4d9d80C702AF85C822A8'),
('550e8400-e29b-41d4-a716-446655440000'),
('urn:uuid:F9168C5E-CEB2-4faa-B6BF-329BF39FA1E4');

Generating a random UUID

To generate a random UUID (version 4), use the GENERATE_UUID function:

INSERT INTO UUID (uuid_field) VALUES (GENERATE_UUID());

Querying data from the UUID column

To query data from the UUID column, use standard SQL syntax:

SELECT uuid_field FROM UUID;

This query will return the following result:

uuid_field
------------------------------------
936DA01F-9ABD-4D9D-80C7-02AF85C822A8
550E8400-E29B-41D4-A716-446655440000
F9168C5E-CEB2-4FAA-B6BF-329BF39FA1E4

Filtering and manipulating data using the UUID column

You can filter, update, and delete data using the UUID column with standard SQL operations:

-- Filtering
SELECT uuid_field FROM UUID WHERE uuid_field = '550e8400-e29b-41d4-a716-446655440000';

-- Updating
UPDATE UUID SET uuid_field = 'urn:uuid:F9168C5E-CEB2-4faa-B6BF-329BF39FA1E4' WHERE uuid_field = '550e8400-e29b-41d4-a716-446655440000';

-- Deleting
DELETE FROM UUID WHERE uuid_field = '550e8400-e29b-41d4-a716-446655440000';
- - + + \ No newline at end of file diff --git a/docs/dev/sql-syntax/functions/datetime/extract/index.html b/docs/dev/sql-syntax/functions/datetime/extract/index.html index cafdfde4..ab9a44ea 100644 --- a/docs/dev/sql-syntax/functions/datetime/extract/index.html +++ b/docs/dev/sql-syntax/functions/datetime/extract/index.html @@ -1,17 +1,17 @@ - + - + EXTRACT | GlueSQL - - - + + +

EXTRACT

The EXTRACT function in SQL is used to retrieve a specific datetime field from a date, time, or interval.

Syntax

EXTRACT(field FROM source)
  • field: The datetime field to extract. Valid fields include YEAR, MONTH, DAY, HOUR, MINUTE, SECOND.
  • source: The date, time, or interval value from which the datetime field is to be extracted.

Usage

Here are examples of how EXTRACT can be used to pull specific datetime components from various types of datetime and interval data.

  1. Extracting the HOUR from a TIMESTAMP:

    SELECT EXTRACT(HOUR FROM TIMESTAMP '2016-12-31 13:30:15') as extract;

    This returns 13.

  2. Extracting the YEAR from a TIMESTAMP:

    SELECT EXTRACT(YEAR FROM TIMESTAMP '2016-12-31 13:30:15') as extract;

    This returns 2016.

  3. Extracting the SECOND from a TIME value:

    SELECT EXTRACT(SECOND FROM TIME '17:12:28') as extract;

    This returns 28.

  4. Extracting the DAY from a DATE value:

    SELECT EXTRACT(DAY FROM DATE '2021-10-06') as extract;

    This returns 6.

  5. Extracting from INTERVAL data:

    SELECT EXTRACT(YEAR FROM INTERVAL '3' YEAR) as extract;
    SELECT EXTRACT(MINUTE FROM INTERVAL '7' MINUTE) as extract;

    These return 3 and 7, respectively.

Note that the EXTRACT function expects the source to be of a compatible datetime or interval type. Using a value of an incompatible type, such as a number or a string that cannot be interpreted as a datetime, will result in an error.

- - + + \ No newline at end of file diff --git a/docs/dev/sql-syntax/functions/datetime/format/index.html b/docs/dev/sql-syntax/functions/datetime/format/index.html index 21255113..0f8bea4b 100644 --- a/docs/dev/sql-syntax/functions/datetime/format/index.html +++ b/docs/dev/sql-syntax/functions/datetime/format/index.html @@ -1,17 +1,17 @@ - + - + FORMAT | GlueSQL - - - + + +

FORMAT

The FORMAT function in SQL is used to format date, time, and timestamp values into a specified format.

Syntax

FORMAT(value, format)
  • value: The date, time, or timestamp value that is to be formatted.
  • format: The format in which the value is to be displayed. This is a string that contains format specifiers, such as %Y for four-digit year, %m for two-digit month, and so on.

Usage

Here are examples of how FORMAT can be used to display datetime components in various formats:

  1. Formatting a DATE value:

    SELECT FORMAT(DATE '2017-06-15','%Y-%m') AS date;

    This returns "2017-06".

  2. Formatting a TIMESTAMP value:

    SELECT FORMAT(TIMESTAMP '2015-09-05 23:56:04', '%Y-%m-%d %H:%M:%S') AS timestamp;

    This returns "2015-09-05 23:56:04".

  3. Formatting a TIME value:

    SELECT FORMAT(TIME '23:56:04','%H:%M') AS time;

    This returns "23:56".

  4. Formatting different components of a TIMESTAMP value separately:

    SELECT 
    FORMAT(TIMESTAMP '2015-09-05 23:56:04', '%Y') AS year,
    FORMAT(TIMESTAMP '2015-09-05 23:56:04', '%m') AS month,
    FORMAT(TIMESTAMP '2015-09-05 23:56:04', '%d') AS day;

    This returns:

    year | month | day
    -----+-------+-----
    2015 | 09 | 05

Please note that the FORMAT function only accepts date, time, or timestamp values. If you try to format a value with an incorrect type, you will encounter an error.

Error Example

SELECT FORMAT('2015-09-05 23:56:04', '%Y-%m-%d %H') AS timestamp;

This will throw an error because the input value is a string, not a date, time, or timestamp value:

EvaluateError::UnsupportedExprForFormatFunction("2015-09-05 23:56:04".to_owned())
- - + + \ No newline at end of file diff --git a/docs/dev/sql-syntax/functions/datetime/now/index.html b/docs/dev/sql-syntax/functions/datetime/now/index.html index 5ff27882..4cf76de3 100644 --- a/docs/dev/sql-syntax/functions/datetime/now/index.html +++ b/docs/dev/sql-syntax/functions/datetime/now/index.html @@ -1,17 +1,17 @@ - + - + NOW | GlueSQL - - - + + +

NOW

The NOW() function in SQL returns the current date and time in UTC. You can use it to retrieve the current UTC timestamp, or as a default value for a TIMESTAMP column in a table.

Syntax

NOW()

Examples

Creating a table with a TIMESTAMP column and setting the default value to NOW()

CREATE TABLE Item (time TIMESTAMP DEFAULT NOW());

This creates a table named Item with a column time of the type TIMESTAMP. The default value for this column is the current UTC timestamp.

Inserting data into the table

INSERT INTO Item (time) VALUES
('2021-10-13T06:42:40.364832862'),
('9999-12-31T23:59:40.364832862');

Here we're inserting two rows into the Item table with specific timestamps.

Selecting rows where the timestamp is greater than the current timestamp

SELECT time FROM Item WHERE time > NOW();

This query selects the time column from the Item table where the time is greater than the current UTC timestamp. In this case, the result will be:

9999-12-31T23:59:40.364832862
- - + + \ No newline at end of file diff --git a/docs/dev/sql-syntax/functions/datetime/to-date/index.html b/docs/dev/sql-syntax/functions/datetime/to-date/index.html index 64eef23d..e4d887a7 100644 --- a/docs/dev/sql-syntax/functions/datetime/to-date/index.html +++ b/docs/dev/sql-syntax/functions/datetime/to-date/index.html @@ -1,17 +1,17 @@ - + - + TO_DATE | GlueSQL - - - + + +

TO_DATE

The TO_DATE function in SQL is used to convert a string into a DATE. This function takes two arguments, the string to be converted and a format string that specifies the format of the input string.

Syntax

TO_DATE(string, format)

Examples

Converting a string to a DATE

VALUES(TO_DATE('2017-06-15', '%Y-%m-%d'));

In this example, the string '2017-06-15' is converted into a DATE using the format '%Y-%m-%d', where %Y is the four-digit year, %m is the two-digit month, and %d is the two-digit day.

Converting a string to a DATE with a different format

SELECT TO_DATE('2017-jun-15','%Y-%b-%d') AS date;

In this example, the string '2017-jun-15' is converted into a DATE using the format '%Y-%b-%d', where %Y is the four-digit year, %b is the abbreviated month name, and %d is the two-digit day.

Error Handling

The TO_DATE function requires a string value as its first argument. If a non-string value is provided, it will return an error.

SELECT TO_DATE(DATE '2017-06-15','%Y-%m-%d') AS date;

In this case, the DATE '2017-06-15' is not a string and will cause an error.

Additionally, if the format string does not match the format of the input string, an error will also be returned. For example:

SELECT TO_DATE('2015-09-05', '%Y-%m') AS date;

In this case, the format string '%Y-%m' does not match the input string '2015-09-05', so an error will be returned.

- - + + \ No newline at end of file diff --git a/docs/dev/sql-syntax/functions/datetime/to-time/index.html b/docs/dev/sql-syntax/functions/datetime/to-time/index.html index 681d0da8..ccd7a6e2 100644 --- a/docs/dev/sql-syntax/functions/datetime/to-time/index.html +++ b/docs/dev/sql-syntax/functions/datetime/to-time/index.html @@ -1,17 +1,17 @@ - + - + TO_TIME | GlueSQL - - - + + +

TO_TIME

The TO_TIME function in SQL is used to convert a string into a TIME. This function takes two arguments, the string to be converted and a format string that specifies the format of the input string.

Syntax

TO_TIME(string, format)

Examples

Converting a string to a TIME

VALUES(TO_TIME('23:56:04', '%H:%M:%S'));

In this example, the string '23:56:04' is converted into a TIME using the format '%H:%M:%S', where %H is the two-digit hour, %M is the two-digit minute, and %S is the two-digit second.

Selecting a converted string to a TIME

SELECT TO_TIME('23:56:04','%H:%M:%S') AS time;

In this example, the string '23:56:04' is converted into a TIME using the format '%H:%M:%S' and selected as 'time'.

Error Handling

The TO_TIME function requires a string value as its first argument. If a non-string value is provided, it will return an error.

SELECT TO_TIME(TIME '23:56:04','%H:%M:%S') AS time;

In this case, the TIME '23:56:04' is not a string and will cause an error.

Additionally, if the format string does not match the format of the input string, an error will also be returned. For example:

SELECT TO_TIME('23:56', '%H:%M:%S') AS time;

In this case, the format string '%H:%M:%S' does not match the input string '23:56', so an error will be returned.

- - + + \ No newline at end of file diff --git a/docs/dev/sql-syntax/functions/datetime/to-timestamp/index.html b/docs/dev/sql-syntax/functions/datetime/to-timestamp/index.html index 229f9d75..e1b98df7 100644 --- a/docs/dev/sql-syntax/functions/datetime/to-timestamp/index.html +++ b/docs/dev/sql-syntax/functions/datetime/to-timestamp/index.html @@ -1,17 +1,17 @@ - + - + TO_TIMESTAMP | GlueSQL - - - + + +

TO_TIMESTAMP

The TO_TIMESTAMP function in SQL is used to convert a string into a TIMESTAMP. This function takes two arguments, the string to be converted and a format string that specifies the format of the input string.

Syntax

TO_TIMESTAMP(string, format)

Examples

Converting a string to a TIMESTAMP

VALUES(TO_TIMESTAMP('2015-09-05 23:56:04', '%Y-%m-%d %H:%M:%S'));

In this example, the string '2015-09-05 23:56:04' is converted into a TIMESTAMP using the format '%Y-%m-%d %H:%M:%S', where %Y is the four-digit year, %m is the two-digit month, %d is the two-digit day, %H is the two-digit hour, %M is the two-digit minute, and %S is the two-digit second.

Selecting a converted string to a TIMESTAMP

SELECT TO_TIMESTAMP('2015-09-05 23:56:04', '%Y-%m-%d %H:%M:%S') AS timestamp;

In this example, the string '2015-09-05 23:56:04' is converted into a TIMESTAMP using the format '%Y-%m-%d %H:%M:%S' and selected as 'timestamp'.

Error Handling

The TO_TIMESTAMP function requires a string value as its first argument. If a non-string value is provided, it will return an error.

SELECT TO_TIMESTAMP(TIMESTAMP '2015-09-05 23:56:04','%Y-%m-%d') AS timestamp;

In this case, the TIMESTAMP '2015-09-05 23:56:04' is not a string and will cause an error.

Additionally, if the format string does not match the format of the input string, an error will also be returned. For example:

SELECT TO_TIMESTAMP('2015-09-05 23:56:04', '%Y-%m-%d %H:%M') AS timestamp;

In this case, the format string '%Y-%m-%d %H:%M' does not match the input string '2015-09-05 23:56:04', so an error will be returned.

- - + + \ No newline at end of file diff --git a/docs/dev/sql-syntax/functions/geometry/calc-distance/index.html b/docs/dev/sql-syntax/functions/geometry/calc-distance/index.html index 883d737d..74802987 100644 --- a/docs/dev/sql-syntax/functions/geometry/calc-distance/index.html +++ b/docs/dev/sql-syntax/functions/geometry/calc-distance/index.html @@ -1,17 +1,17 @@ - + - + CALC_DISTANCE | GlueSQL - - - + + +
-

CALC_DISTANCE

The CALC_DISTANCE function is used to calculate the Euclidean distance between two Point type geographical coordinates.

Syntax

CALC_DISTANCE(point1, point2)

Parameters:

  • point1: The first geographical coordinate of type Point.
  • point2: The second geographical coordinate of type Point.

Examples

Consider the following table Foo:

CREATE TABLE Foo (
geo1 Point,
geo2 Point,
bar Float
);

With the following data:

INSERT INTO Foo VALUES (POINT(0.3134, 3.156), POINT(1.415, 3.231), 3);

Example 1: Calculate the distance between two points

SELECT CALC_DISTANCE(geo1, geo2) AS georesult FROM Foo;

Result:

georesult
1.104150152832485

Errors

  1. If the number of arguments is not 2, a FunctionArgsLengthNotMatching error will be thrown.
  2. If any of the arguments are not of type Point, a FunctionRequiresPointValue error will be thrown.
  3. If any of the arguments are NULL, the result will be NULL.
- - +

CALC_DISTANCE

The CALC_DISTANCE function is used to calculate the Euclidean distance between two Point type geographical coordinates.

Syntax

CALC_DISTANCE(point1, point2)

Parameters:

  • point1: The first geographical coordinate of type Point.
  • point2: The second geographical coordinate of type Point.

Examples

Consider the following table Foo:

CREATE TABLE Foo (
geo1 Point,
geo2 Point,
bar Float
);

With the following data:

INSERT INTO Foo VALUES (POINT(0.3134, 3.156), POINT(1.415, 3.231), 3);

Example 1: Calculate the distance between two points

SELECT CALC_DISTANCE(geo1, geo2) AS georesult FROM Foo;

Result:

georesult
1.104150152832485

Errors

  1. If the number of arguments is not 2, a FunctionArgsLengthNotMatching error will be thrown.
  2. If any of the arguments are not of type Point, a FunctionRequiresPointValue error will be thrown.
  3. If any of the arguments are NULL, the result will be NULL.
+ + \ No newline at end of file diff --git a/docs/dev/sql-syntax/functions/geometry/get-x/index.html b/docs/dev/sql-syntax/functions/geometry/get-x/index.html index aeb1787d..38fba3bf 100644 --- a/docs/dev/sql-syntax/functions/geometry/get-x/index.html +++ b/docs/dev/sql-syntax/functions/geometry/get-x/index.html @@ -1,17 +1,17 @@ - + - + GET_X | GlueSQL - - - + + +

GET_X

The GET_X function returns the x-coordinate of a given POINT data type. It takes one POINT data type argument and returns a FLOAT value representing the x-coordinate.

Syntax

GET_X(point)

Parameters:

  • point: The geographical coordinate of type Point from which the X-coordinate will be extracted.

Examples

Consider the following table PointGroup:

CREATE TABLE PointGroup (
point_field POINT
);

With the following data:

INSERT INTO PointGroup VALUES (POINT(0.3134, 0.156));

Example 1: Get the X-coordinate from a point

SELECT GET_X(point_field) AS point_field FROM PointGroup;

Result:

point_field
0.3134

Example 2: Get the X-coordinate from a point using CAST

SELECT GET_X(CAST('POINT(0.1 -0.2)' AS POINT)) AS ptx;

Result:

ptx
0.1

Example 3: Get the X-coordinate from a point using POINT function

SELECT GET_X(POINT(0.1, -0.2)) AS ptx;

Result:

ptx
0.1

Errors

If the argument is not of type Point, a FunctionRequiresPointValue error will be thrown.

- - + + \ No newline at end of file diff --git a/docs/dev/sql-syntax/functions/geometry/get-y/index.html b/docs/dev/sql-syntax/functions/geometry/get-y/index.html index 89479c98..9b2ca8f4 100644 --- a/docs/dev/sql-syntax/functions/geometry/get-y/index.html +++ b/docs/dev/sql-syntax/functions/geometry/get-y/index.html @@ -1,17 +1,17 @@ - + - + GET_Y | GlueSQL - - - + + +

GET_Y

The GET_Y function returns the y-coordinate of a given POINT data type. It takes one POINT data type argument and returns a FLOAT value representing the y-coordinate.

Syntax

GET_Y(point)

Parameters:

  • point: The geographical coordinate of type Point from which the Y-coordinate will be extracted.

Examples

Consider the following table PointGroup:

CREATE TABLE PointGroup (
point_field POINT
);

With the following data:

INSERT INTO PointGroup VALUES (POINT(0.3134, 0.156));

Example 1: Get the Y-coordinate from a point

SELECT GET_Y(point_field) AS point_field FROM PointGroup;

Result:

point_field
0.156

Example 2: Get the Y-coordinate from a point using CAST

SELECT GET_Y(CAST('POINT(0.1 -0.2)' AS POINT)) AS ptx;

Result:

ptx
-0.2

Example 3: Get the Y-coordinate from a point using POINT function

SELECT GET_Y(POINT(0.1, -0.2)) AS ptx;

Result:

ptx
-0.2

Errors

If the argument is not of type Point, a FunctionRequiresPointValue error will be thrown.

- - + + \ No newline at end of file diff --git a/docs/dev/sql-syntax/functions/geometry/point/index.html b/docs/dev/sql-syntax/functions/geometry/point/index.html index 4eec59ef..eb282057 100644 --- a/docs/dev/sql-syntax/functions/geometry/point/index.html +++ b/docs/dev/sql-syntax/functions/geometry/point/index.html @@ -1,17 +1,17 @@ - + - + POINT | GlueSQL - - - + + +

POINT

The POINT function creates a point value using the provided x and y coordinates. A point value represents a two-dimensional geometric point with a pair of floating-point numbers, often used for storing spatial data.

Syntax

POINT(x, y)

Examples

Create a table with a POINT data type column:

CREATE TABLE Foo (point_field POINT);

Insert a record with a point value:

INSERT INTO Foo VALUES (POINT(0.3134, 0.156));

Select the point_field column:

SELECT point_field AS point_field FROM Foo;

Update the point_field column:

UPDATE Foo SET point_field = POINT(2.0, 1.0) WHERE point_field = POINT(0.3134, 0.156);

Select the updated point_field column:

SELECT point_field AS point_field FROM Foo;

Delete the record with the specified point value:

DELETE FROM Foo WHERE point_field = POINT(2.0, 1.0);

Casting a string to a POINT:

SELECT CAST('POINT(-71.064544 42.28787)' AS POINT) AS pt;
- - + + \ No newline at end of file diff --git a/docs/dev/sql-syntax/functions/list-map/append/index.html b/docs/dev/sql-syntax/functions/list-map/append/index.html index 0fa1ba87..9d78b63c 100644 --- a/docs/dev/sql-syntax/functions/list-map/append/index.html +++ b/docs/dev/sql-syntax/functions/list-map/append/index.html @@ -1,17 +1,17 @@ - + - + APPEND | GlueSQL - - - + + +
-

APPEND

The APPEND function in SQL is used to append an element to a list.

Syntax

APPEND(list, element)
  • list: The list to which you want to append the element.
  • element: The element that you want to append to the list.

Examples

First, create a table named Append with columns for the list, an integer element, and a text element:

CREATE TABLE Append (
id INTEGER,
items LIST,
element INTEGER,
element2 TEXT
);

Insert some data into the Append table:

INSERT INTO Append VALUES
(1, '[1, 2, 3]', 4, 'Foo');

Use the APPEND function to append the integer element to the list:

SELECT APPEND(items, element) AS myappend FROM Append;

Use the APPEND function to append the text element to the list:

SELECT APPEND(items, element2) AS myappend FROM Append;

The APPEND function requires a list as the first parameter. If you try to use it with a non-list value, an error will occur:

SELECT APPEND(element, element2) AS myappend FROM Append;

You can also use the APPEND function when inserting data into a table. First, create a table named Foo with a column for the list:

CREATE TABLE Foo (
elements LIST
);

Then, insert data into the Foo table using the APPEND function:

INSERT INTO Foo VALUES (APPEND(CAST('[1, 2, 3]' AS LIST), 4));

Finally, retrieve the list from the Foo table:

SELECT elements AS myappend FROM Foo;
- - +

APPEND

The APPEND function in SQL is used to append an element to a list.

Syntax

APPEND(list, element)
  • list: The list to which you want to append the element.
  • element: The element that you want to append to the list.

Examples

First, create a table named Append with columns for the list, an integer element, and a text element:

CREATE TABLE Append (
id INTEGER,
items LIST,
element INTEGER,
element2 TEXT
);

Insert some data into the Append table:

INSERT INTO Append VALUES
(1, '[1, 2, 3]', 4, 'Foo');

Use the APPEND function to append the integer element to the list:

SELECT APPEND(items, element) AS myappend FROM Append;

Use the APPEND function to append the text element to the list:

SELECT APPEND(items, element2) AS myappend FROM Append;

The APPEND function requires a list as the first parameter. If you try to use it with a non-list value, an error will occur:

SELECT APPEND(element, element2) AS myappend FROM Append;

You can also use the APPEND function when inserting data into a table. First, create a table named Foo with a column for the list:

CREATE TABLE Foo (
elements LIST
);

Then, insert data into the Foo table using the APPEND function:

INSERT INTO Foo VALUES (APPEND(CAST('[1, 2, 3]' AS LIST), 4));

Finally, retrieve the list from the Foo table:

SELECT elements AS myappend FROM Foo;
+ + \ No newline at end of file diff --git a/docs/dev/sql-syntax/functions/list-map/concat/index.html b/docs/dev/sql-syntax/functions/list-map/concat/index.html index 63c29fde..0c760b90 100644 --- a/docs/dev/sql-syntax/functions/list-map/concat/index.html +++ b/docs/dev/sql-syntax/functions/list-map/concat/index.html @@ -1,17 +1,17 @@ - + - + CONCAT | GlueSQL - - - + + +
-

CONCAT

The CONCAT function is used to concatenate two or more list values together.

Syntax

CONCAT(list_value1, list_value2, ...)

Parameters:

  • list_value1, list_value2, ...: List values that will be concatenated.

Examples

Consider the following table ListTypeConcat:

CREATE TABLE ListTypeConcat (
id INTEGER,
items LIST,
items2 LIST
);

With the following data:

INSERT INTO ListTypeConcat VALUES
(1, '[1, 2, 3]', '["one", "two", "three"]');

Example 1: CONCAT two lists

SELECT CONCAT(items, items2) AS myconcat FROM ListTypeConcat;

Result:

myconcat
[1, 2, 3, "one", "two", "three"]
- - +

CONCAT

The CONCAT function is used to concatenate two or more list values together.

Syntax

CONCAT(list_value1, list_value2, ...)

Parameters:

  • list_value1, list_value2, ...: List values that will be concatenated.

Examples

Consider the following table ListTypeConcat:

CREATE TABLE ListTypeConcat (
id INTEGER,
items LIST,
items2 LIST
);

With the following data:

INSERT INTO ListTypeConcat VALUES
(1, '[1, 2, 3]', '["one", "two", "three"]');

Example 1: CONCAT two lists

SELECT CONCAT(items, items2) AS myconcat FROM ListTypeConcat;

Result:

myconcat
[1, 2, 3, "one", "two", "three"]
+ + \ No newline at end of file diff --git a/docs/dev/sql-syntax/functions/list-map/prepend/index.html b/docs/dev/sql-syntax/functions/list-map/prepend/index.html index 812ebf9c..c4139bcd 100644 --- a/docs/dev/sql-syntax/functions/list-map/prepend/index.html +++ b/docs/dev/sql-syntax/functions/list-map/prepend/index.html @@ -1,17 +1,17 @@ - + - + PREPEND | GlueSQL - - - + + +
-

PREPEND

The PREPEND function in SQL is used to prepend an element to a list.

Syntax

PREPEND(list, element)
  • list: The list to which you want to prepend the element.
  • element: The element that you want to prepend to the list.

Examples

First, create a table named Prepend with columns for the list, an integer element, and a text element:

CREATE TABLE Prepend (
id INTEGER,
items LIST,
element INTEGER,
element2 TEXT
);

Insert some data into the Prepend table:

INSERT INTO Prepend VALUES
(1, '[1, 2, 3]', 0, 'Foo');

Use the PREPEND function to prepend the integer element to the list:

SELECT PREPEND(items, element) AS myprepend FROM Prepend;

Use the PREPEND function to prepend the text element to the list:

SELECT PREPEND(items, element2) AS myprepend FROM Prepend;

The PREPEND function requires a list as the first parameter. If you try to use it with a non-list value, an error will occur:

SELECT PREPEND(element, element2) AS myprepend FROM Prepend;

You can also use the PREPEND function when inserting data into a table. First, create a table named Foo with a column for the list:

CREATE TABLE Foo (
elements LIST
);

Then, insert data into the Foo table using the PREPEND function:

INSERT INTO Foo VALUES (PREPEND(CAST('[1, 2, 3]' AS LIST), 0));

Finally, retrieve the list from the Foo table:

SELECT elements AS myprepend FROM Foo;
- - +

PREPEND

The PREPEND function in SQL is used to prepend an element to a list.

Syntax

PREPEND(list, element)
  • list: The list to which you want to prepend the element.
  • element: The element that you want to prepend to the list.

Examples

First, create a table named Prepend with columns for the list, an integer element, and a text element:

CREATE TABLE Prepend (
id INTEGER,
items LIST,
element INTEGER,
element2 TEXT
);

Insert some data into the Prepend table:

INSERT INTO Prepend VALUES
(1, '[1, 2, 3]', 0, 'Foo');

Use the PREPEND function to prepend the integer element to the list:

SELECT PREPEND(items, element) AS myprepend FROM Prepend;

Use the PREPEND function to prepend the text element to the list:

SELECT PREPEND(items, element2) AS myprepend FROM Prepend;

The PREPEND function requires a list as the first parameter. If you try to use it with a non-list value, an error will occur:

SELECT PREPEND(element, element2) AS myprepend FROM Prepend;

You can also use the PREPEND function when inserting data into a table. First, create a table named Foo with a column for the list:

CREATE TABLE Foo (
elements LIST
);

Then, insert data into the Foo table using the PREPEND function:

INSERT INTO Foo VALUES (PREPEND(CAST('[1, 2, 3]' AS LIST), 0));

Finally, retrieve the list from the Foo table:

SELECT elements AS myprepend FROM Foo;
+ + \ No newline at end of file diff --git a/docs/dev/sql-syntax/functions/list-map/splice/index.html b/docs/dev/sql-syntax/functions/list-map/splice/index.html new file mode 100644 index 00000000..ad5adaff --- /dev/null +++ b/docs/dev/sql-syntax/functions/list-map/splice/index.html @@ -0,0 +1,17 @@ + + + + + +SQL Function - "SPLICE" | GlueSQL + + + + + +
+

SQL Function - "SPLICE"

The "SPLICE" function in GlueSQL is used to modify elements in a list. It allows you to remove or replace elements in a list. The syntax for the "SPLICE" function is as follows:

SPLICE(list1, start_index, end_index [, list2])
  • list1: The list you want to modify.
  • start_index: The position at which you want to start the modification.
  • end_index: The exclusive end position for the modification.
  • list2 (optional): A list of elements to insert in place of the removed elements.

Example

We can use the "SPLICE" function to modify the list in various ways:

  1. Remove elements from a list:
-- Remove elements at 1, 2 from the list '[1, 2, 3]'
SELECT SPLICE(CAST('[1, 2, 3, 4, 5]' AS List), 1, 3) AS result;
-- Output: '[1, 4, 5]'
  1. Replace elements in a list:
-- Replace elements at 1, 2, 3 with '[100, 99]' in the list '[1, 2, 3, 4, 5]'
SELECT SPLICE(CAST('[1, 2, 3, 4, 5]' AS List), 1, 4, CAST('[100, 99]' AS List)) AS result;
-- Output: '[1, 100, 99, 5]'
  1. 'start' is processed so that it is not less than 0 and 'end' is not greater than the length of the list.
SELECT SPLICE(CAST('[1, 2, 3]' AS List), -1, 2, CAST('[100, 99]' AS List)) AS result;
-- Output: '[100, 99, 3]'

Error

If you use the "SPLICE" function with invalid inputs, it will result in an error. For example:

-- Using SPLICE on a non-list value will result in an error.
SELECT SPLICE(3, 1, 2) AS result;
-- EvaluateError::ListTypeRequired
+ + + + \ No newline at end of file diff --git a/docs/dev/sql-syntax/functions/math/abs/index.html b/docs/dev/sql-syntax/functions/math/abs/index.html index f657f107..d45ad29e 100644 --- a/docs/dev/sql-syntax/functions/math/abs/index.html +++ b/docs/dev/sql-syntax/functions/math/abs/index.html @@ -1,17 +1,17 @@ - + - + ABS | GlueSQL - - - + + +

ABS

The ABS function is used to calculate the absolute value of a number. It takes a single numeric argument and returns the absolute value of that number. The argument can be an integer, decimal, or float value.

Syntax

ABS(value)
  • value: A numeric expression for which the absolute value is to be calculated.

Examples

Let's consider a table named SingleItem with the following schema:

CREATE TABLE SingleItem (id INTEGER, int8 INT8, dec DECIMAL);

Insert a row into the SingleItem table:

INSERT INTO SingleItem VALUES (0, -1, -2);

Example 1: Using ABS with integer values

SELECT ABS(1) AS ABS1, 
ABS(-1) AS ABS2,
ABS(+1) AS ABS3
FROM SingleItem;

Result:

 ABS1 | ABS2 | ABS3 
------+------+------
1 | 1 | 1

Example 2: Using ABS with float values

SELECT ABS(1.0) AS ABS1, 
ABS(-1.0) AS ABS2,
ABS(+1.0) AS ABS3
FROM SingleItem;

Result:

 ABS1 | ABS2 | ABS3 
------+------+------
1.0 | 1.0 | 1.0

Example 3: Using ABS with table columns

SELECT ABS(id) AS ABS1, 
ABS(int8) AS ABS2,
ABS(dec) AS ABS3
FROM SingleItem;

Result:

 ABS1 | ABS2 | ABS3 
------+------+------
0 | 1 | 2

Example 4: Using ABS with NULL values

SELECT ABS(NULL) AS ABS FROM SingleItem;

Result:

  ABS  
-------
(null)

Errors

The ABS function requires a numeric value as its argument. Using non-numeric values or more than one argument will result in an error.

Example 5: Using ABS with non-numeric values

SELECT ABS('string') AS ABS FROM SingleItem;

Error: Function requires a numeric value.

Example 6: Using ABS with multiple arguments

SELECT ABS('string', 'string2') AS ABS FROM SingleItem;

Error: Function expects 1 argument, but 2 were provided.

- - + + \ No newline at end of file diff --git a/docs/dev/sql-syntax/functions/math/acos/index.html b/docs/dev/sql-syntax/functions/math/acos/index.html index b6d878cb..358986cd 100644 --- a/docs/dev/sql-syntax/functions/math/acos/index.html +++ b/docs/dev/sql-syntax/functions/math/acos/index.html @@ -1,17 +1,17 @@ - + - + ACOS | GlueSQL - - - + + +

ACOS

The ACOS function is used to calculate the arccosine (inverse cosine) of a number. It takes a single numeric argument, which should be a float value in the range of -1 to 1, and returns the arccosine of that number in radians.

Syntax

ACOS(value)
  • value: A numeric expression for which the arccosine is to be calculated. The value should be in the range of -1 to 1.

Examples

Let's consider a table named SingleItem with the following schema:

CREATE TABLE SingleItem (id INTEGER);

Insert a row into the SingleItem table:

INSERT INTO SingleItem VALUES (0);

Example 1: Using ACOS with float values

SELECT ACOS(0.5) AS acos1, ACOS(1) AS acos2 FROM SingleItem;

Result:

     acos1      |     acos2
----------------+---------------
1.0471975511966 | 0.0

Example 2: Using ACOS with NULL values

SELECT ACOS(NULL) AS acos FROM SingleItem;

Result:

  acos
-------
(null)

Errors

The ACOS function requires a numeric value in the range of -1 to 1 as its argument. Using non-numeric values or more than one argument will result in an error.

Example 3: Using ACOS with non-numeric values

SELECT ACOS('string') AS acos FROM SingleItem;

Error: Function requires a numeric value.

Example 4: Using ACOS with multiple arguments

SELECT ACOS(1.0, 2.0) AS acos FROM SingleItem;

Error: Function expects 1 argument, but 2 were provided.

- - + + \ No newline at end of file diff --git a/docs/dev/sql-syntax/functions/math/asin/index.html b/docs/dev/sql-syntax/functions/math/asin/index.html index 4d21f180..0e14b919 100644 --- a/docs/dev/sql-syntax/functions/math/asin/index.html +++ b/docs/dev/sql-syntax/functions/math/asin/index.html @@ -1,17 +1,17 @@ - + - + ASIN | GlueSQL - - - + + +

ASIN

The ASIN function is used to calculate the arcsine (inverse sine) of a number. It takes a single numeric argument, which should be a float value in the range of -1 to 1, and returns the arcsine of that number in radians.

Syntax

ASIN(value)
  • value: A numeric expression for which the arcsine is to be calculated. The value should be in the range of -1 to 1.

Examples

Let's consider a table named SingleItem with the following schema:

CREATE TABLE SingleItem (id INTEGER);

Insert a row into the SingleItem table:

INSERT INTO SingleItem VALUES (0);

Example 1: Using ASIN with float values

SELECT ASIN(0.5) AS asin1, ASIN(1) AS asin2 FROM SingleItem;

Result:

     asin1      |     asin2
----------------+---------------
0.5235987755983 | 1.5707963267949

Example 2: Using ASIN with NULL values

SELECT ASIN(NULL) AS asin FROM SingleItem;

Result:

  asin
-------
(null)

Errors

The ASIN function requires a numeric value in the range of -1 to 1 as its argument. Using non-numeric values or more than one argument will result in an error.

Example 3: Using ASIN with non-numeric values

SELECT ASIN('string') AS asin FROM SingleItem;

Error: Function requires a numeric value.

Example 4: Using ASIN with multiple arguments

SELECT ASIN(1.0, 2.0) AS sin FROM SingleItem;

Error: Function expects 1 argument, but 2 were provided.

- - + + \ No newline at end of file diff --git a/docs/dev/sql-syntax/functions/math/atan/index.html b/docs/dev/sql-syntax/functions/math/atan/index.html index bdb539f3..9139334a 100644 --- a/docs/dev/sql-syntax/functions/math/atan/index.html +++ b/docs/dev/sql-syntax/functions/math/atan/index.html @@ -1,17 +1,17 @@ - + - + ATAN | GlueSQL - - - + + +

ATAN

The ATAN function is used to calculate the arctangent (inverse tangent) of a number. It takes a single numeric argument, and returns the arctangent of that number in radians.

Syntax

ATAN(value)
  • value: A numeric expression for which the arctangent is to be calculated.

Examples

Let's consider a table named SingleItem with the following schema:

CREATE TABLE SingleItem (id INTEGER);

Insert a row into the SingleItem table:

INSERT INTO SingleItem VALUES (0);

Example 1: Using ATAN with float values

SELECT ATAN(0.5) AS atan1, ATAN(1) AS atan2 FROM SingleItem;

Result:

    atan1     |    atan2
--------------+---------------
0.463647609 | 0.785398163

Example 2: Using ATAN with NULL values

SELECT ATAN(NULL) AS atan FROM SingleItem;

Result:

  atan
-------
(null)

Errors

The ATAN function requires a numeric value as its argument. Using non-numeric values or more than one argument will result in an error.

Example 3: Using ATAN with non-numeric values

SELECT ATAN('string') AS atan FROM SingleItem;

Error: Function requires a numeric value.

Example 4: Using ATAN with multiple arguments

SELECT ATAN(1.0, 2.0) AS atan FROM SingleItem;

Error: Function expects 1 argument, but 2 were provided.

- - + + \ No newline at end of file diff --git a/docs/dev/sql-syntax/functions/math/ceil/index.html b/docs/dev/sql-syntax/functions/math/ceil/index.html index e59bf8e1..ae426988 100644 --- a/docs/dev/sql-syntax/functions/math/ceil/index.html +++ b/docs/dev/sql-syntax/functions/math/ceil/index.html @@ -1,17 +1,17 @@ - + - + CEIL | GlueSQL - - - + + +

CEIL

The CEIL function is used to round a number up to the nearest integer value. It takes a single floating-point or integer value as its argument and returns a floating-point value.

Syntax

CEIL(value)

Examples

Let's consider a table named SingleItem with the following schema:

CREATE TABLE SingleItem (id INTEGER);

Insert a row into the SingleItem table:

INSERT INTO SingleItem VALUES (0);

Example 1: Using CEIL function

SELECT CEIL(0.3) AS ceil1,
CEIL(-0.8) AS ceil2,
CEIL(10) AS ceil3,
CEIL(6.87421) AS ceil4
FROM SingleItem;

Result:

ceil1 | ceil2 | ceil3 | ceil4
------+-------+-------+-------
1.0 | 0.0 | 10.0 | 7.0

Note that the returned values are floating-point numbers, even though they represent integer values.

Errors

The CEIL function expects a floating-point or integer value as its argument. Providing any other type, such as a string or boolean, will result in an error.

Example 2: Using CEIL with a string argument

SELECT CEIL('string') AS ceil FROM SingleItem;

Error: Function requires a floating-point or integer value.

Example 3: Using CEIL with a boolean argument

SELECT CEIL(TRUE) AS ceil FROM SingleItem;

Error: Function requires a floating-point or integer value.

- - + + \ No newline at end of file diff --git a/docs/dev/sql-syntax/functions/math/cos/index.html b/docs/dev/sql-syntax/functions/math/cos/index.html index 8dd7b3e9..5153f49b 100644 --- a/docs/dev/sql-syntax/functions/math/cos/index.html +++ b/docs/dev/sql-syntax/functions/math/cos/index.html @@ -1,17 +1,17 @@ - + - + COS | GlueSQL - - - + + +

COS

The COS function is used to calculate the cosine of a number. It takes a single numeric argument (angle in radians) and returns the cosine of that angle.

Syntax

COS(value)
  • value: A numeric expression (angle in radians) for which the cosine is to be calculated.

Examples

Let's consider a table named SingleItem with the following schema:

CREATE TABLE SingleItem (id INTEGER);

Insert a row into the SingleItem table:

INSERT INTO SingleItem VALUES (0);

Example 1: Using COS with float values

SELECT COS(0.5) AS cos1, COS(1) AS cos2 FROM SingleItem;

Result:

    cos1     |    cos2
-------------+--------------
0.877582562 | 0.540302306

Example 2: Using COS with NULL values

SELECT COS(NULL) AS cos FROM SingleItem;

Result:

  cos
-------
(null)

Errors

The COS function requires a numeric value as its argument. Using non-numeric values or more than one argument will result in an error.

Example 3: Using COS with non-numeric values

SELECT COS('string') AS cos FROM SingleItem;

Error: Function requires a numeric value.

Example 4: Using COS with multiple arguments

SELECT COS(1.0, 2.0) AS cos FROM SingleItem;

Error: Function expects 1 argument, but 2 were provided.

- - + + \ No newline at end of file diff --git a/docs/dev/sql-syntax/functions/math/degrees/index.html b/docs/dev/sql-syntax/functions/math/degrees/index.html index 0c35d827..007376b3 100644 --- a/docs/dev/sql-syntax/functions/math/degrees/index.html +++ b/docs/dev/sql-syntax/functions/math/degrees/index.html @@ -1,17 +1,17 @@ - + - + DEGREES | GlueSQL - - - + + +

DEGREES

The DEGREES function is used to convert a given angle value from radians to degrees. It takes a single numeric argument (angle in radians) and returns the angle in degrees.

Syntax

DEGREES(value)
  • value: A numeric expression (angle in radians) to be converted to degrees.

Examples

Let's consider a table named SingleItem with the following schema:

CREATE TABLE SingleItem (id FLOAT);

Insert a row into the SingleItem table:

INSERT INTO SingleItem VALUES (0);

Example 1: Using DEGREES with float values

SELECT
DEGREES(180.0) as degrees_1,
DEGREES(360.0) as degrees_2
FROM SingleItem;

Result:

   degrees_1 | degrees_2
-------------+-------------
10313.240312 | 20626.480624

Example 2: Using DEGREES with integer values

SELECT DEGREES(90) as degrees_with_int FROM SingleItem;

Result:

degrees_with_int
-----------------
5156.620156

Example 3: Using DEGREES with zero

SELECT DEGREES(0) as degrees_with_zero FROM SingleItem;

Result:

degrees_with_zero
------------------
0.0

Errors

The DEGREES function requires a numeric value as its argument. Using non-numeric values or more than one argument will result in an error.

Example 4: Using DEGREES with non-numeric values

SELECT DEGREES('string') AS degrees FROM SingleItem;

Error: Function requires a numeric value.

Example 5: Using DEGREES with multiple arguments

SELECT DEGREES(0, 0) as degrees_arg2 FROM SingleItem;

Error: Function expects 1 argument, but 2 were provided.

- - + + \ No newline at end of file diff --git a/docs/dev/sql-syntax/functions/math/div/index.html b/docs/dev/sql-syntax/functions/math/div/index.html index c9a5de7f..21c58f9f 100644 --- a/docs/dev/sql-syntax/functions/math/div/index.html +++ b/docs/dev/sql-syntax/functions/math/div/index.html @@ -1,17 +1,17 @@ - + - + DIV | GlueSQL - - - + + +

DIV

The DIV function is used to perform integer division. It takes two arguments (a dividend and a divisor) and returns the integer quotient of the division operation. Both dividend and divisor can be FLOAT or INTEGER type. The return type of the function is INTEGER.

Example

The following example demonstrates the usage of the DIV function in a SQL query:

CREATE TABLE FloatDiv (
dividend FLOAT DEFAULT DIV(30, 11),
divisor FLOAT DEFAULT DIV(3, 2)
);

INSERT INTO FloatDiv (dividend, divisor) VALUES (12.0, 3.0), (12.34, 56.78), (-12.3, 4.0);

SELECT DIV(dividend, divisor) FROM FloatDiv;

This will return the following result:

DIV(dividend, divisor)
4
0
-4

Errors

  1. If the divisor is zero, a DivisorShouldNotBeZero error will be raised.
  2. If either of the arguments is not of FLOAT or INTEGER type, a FunctionRequiresFloatOrIntegerValue error will be raised.
  3. If the number of arguments provided to the function is not equal to 2, a FunctionArgsLengthNotMatching error will be raised.
- - + + \ No newline at end of file diff --git a/docs/dev/sql-syntax/functions/math/exp/index.html b/docs/dev/sql-syntax/functions/math/exp/index.html index 5de97bab..03e0c44d 100644 --- a/docs/dev/sql-syntax/functions/math/exp/index.html +++ b/docs/dev/sql-syntax/functions/math/exp/index.html @@ -1,17 +1,17 @@ - + - + EXP | GlueSQL - - - + + +

EXP

The EXP function is used to calculate the exponential value of a number. It takes a single FLOAT or INTEGER argument and returns a FLOAT value representing the exponential value of the given number.

Example

The following example demonstrates the usage of the EXP function in a SQL query:

SELECT
EXP(2.0) as exp1,
EXP(5.5) as exp2;

This will return the following result:

exp1           | exp2
---------------+-------------------
2.0_f64.exp() | 5.5_f64.exp()

Errors

  1. If the argument is not of FLOAT or INTEGER type, a FunctionRequiresFloatValue error will be raised.
  2. If the number of arguments provided to the function is not equal to 1, a FunctionArgsLengthNotMatching error will be raised.
- - + + \ No newline at end of file diff --git a/docs/dev/sql-syntax/functions/math/floor/index.html b/docs/dev/sql-syntax/functions/math/floor/index.html index 3ef00080..dad65bd1 100644 --- a/docs/dev/sql-syntax/functions/math/floor/index.html +++ b/docs/dev/sql-syntax/functions/math/floor/index.html @@ -1,17 +1,17 @@ - + - + FLOOR | GlueSQL - - - + + +

FLOOR

The FLOOR function is used to round a number down to the nearest integer value. It takes a single floating-point or integer value as its argument and returns a floating-point value.

Syntax

FLOOR(value)

Examples

Let's consider a table named SingleItem with the following schema:

CREATE TABLE SingleItem (id INTEGER);

Insert a row into the SingleItem table:

INSERT INTO SingleItem VALUES (0);

Example 1: Using FLOOR function

SELECT
FLOOR(0.3) as floor1,
FLOOR(-0.8) as floor2,
FLOOR(10) as floor3,
FLOOR(6.87421) as floor4
FROM SingleItem;

Result:

floor1 | floor2 | floor3 | floor4
-------+--------+--------+--------
0.0 | -1.0 | 10.0 | 6.0

Note that the returned values are floating-point numbers, even though they represent integer values.

Errors

The FLOOR function expects a floating-point or integer value as its argument. Providing any other type, such as a string or boolean, will result in an error.

Example 2: Using FLOOR with a string argument

SELECT FLOOR('string') AS floor FROM SingleItem;

Error: Function requires a floating-point or integer value.

Example 3: Using FLOOR with a boolean argument

SELECT FLOOR(TRUE) AS floor FROM SingleItem;

Error: Function requires a floating-point or integer value.

- - + + \ No newline at end of file diff --git a/docs/dev/sql-syntax/functions/math/gcd/index.html b/docs/dev/sql-syntax/functions/math/gcd/index.html index f65a0faf..598e2c56 100644 --- a/docs/dev/sql-syntax/functions/math/gcd/index.html +++ b/docs/dev/sql-syntax/functions/math/gcd/index.html @@ -1,17 +1,17 @@ - + - + GCD | GlueSQL - - - + + +

GCD

The GCD function is used to find the greatest common divisor (GCD) of two integers. It takes two INTEGER arguments and returns an INTEGER value representing the greatest common divisor of the given integers.

Example

The following example demonstrates the usage of the GCD function in a SQL query:

CREATE TABLE GcdI64 (
left INTEGER NULL DEFAULT GCD(3, 4),
right INTEGER NULL
);

INSERT INTO GcdI64 VALUES (0, 3), (2, 4), (6, 8), (3, 5), (1, NULL), (NULL, 1);

SELECT GCD(left, right) AS test FROM GcdI64;

This will return the following result:

test
3
2
2
1
NULL
NULL

Errors

  1. If either of the arguments is not of INTEGER type, a FunctionRequiresIntegerValue error will be raised.
  2. If the number of arguments provided to the function is not equal to 2, a FunctionArgsLengthNotMatching error will be raised.
  3. If either of the arguments is the minimum i64 value (-9223372036854775808), an overflow occurs when attempting to take the absolute value. In this case, a GcdLcmOverflowError is raised.
- - + + \ No newline at end of file diff --git a/docs/dev/sql-syntax/functions/math/lcm/index.html b/docs/dev/sql-syntax/functions/math/lcm/index.html index f855d035..8b1514ce 100644 --- a/docs/dev/sql-syntax/functions/math/lcm/index.html +++ b/docs/dev/sql-syntax/functions/math/lcm/index.html @@ -1,17 +1,17 @@ - + - + LCM | GlueSQL - - - + + +

LCM

The LCM function is used to find the least common multiple (LCM) of two integers. It takes two INTEGER arguments and returns an INTEGER value representing the least common multiple of the given integers.

Example

The following example demonstrates the usage of the LCM function in a SQL query:

CREATE TABLE LcmI64 (
left INTEGER NULL,
right INTEGER NULL
);

INSERT INTO LcmI64 VALUES (0, 3), (2, 4), (6, 8), (3, 5), (1, NULL), (NULL, 1);

SELECT LCM(left, right) AS test FROM LcmI64;

This will return the following result:

test
0
4
24
15
NULL
NULL

Errors

  1. If either of the arguments is not of INTEGER type, a FunctionRequiresIntegerValue error will be raised.
  2. If the number of arguments provided to the function is not equal to 2, a FunctionArgsLengthNotMatching error will be raised.
  3. If either of the arguments is the minimum i64 value (-9223372036854775808), an overflow occurs when attempting to calculate the gcd, which is then used in the lcm calculation. In this case, an GcdLcmOverflowError is raised.
  4. If the calculated result of lcm is outside the valid range of i64 (-9223372036854775808 to 9223372036854775807), a LcmResultOutOfRange error is raised. This may occur with large prime numbers.
- - + + \ No newline at end of file diff --git a/docs/dev/sql-syntax/functions/math/ln/index.html b/docs/dev/sql-syntax/functions/math/ln/index.html index 307f9540..08d69bce 100644 --- a/docs/dev/sql-syntax/functions/math/ln/index.html +++ b/docs/dev/sql-syntax/functions/math/ln/index.html @@ -1,17 +1,17 @@ - + - + LN | GlueSQL - - - + + +

LN

The LN function is used to calculate the natural logarithm (base e) of a number. It takes a single FLOAT or INTEGER argument and returns a FLOAT value representing the natural logarithm of the given number.

Example

The following example demonstrates the usage of the LN function in a SQL query:

CREATE TABLE SingleItem (id INTEGER DEFAULT LN(10));

INSERT INTO SingleItem VALUES (0);

SELECT
LN(64.0) as ln1,
LN(0.04) as ln2
FROM SingleItem;

This will return the following result:

ln1     | ln2
--------+-------------------
4.1589 | -3.2189

Errors

  1. If the argument is not of FLOAT or INTEGER type, a FunctionRequiresFloatValue error will be raised.
  2. If the number of arguments provided to the function is not equal to 1, a FunctionArgsLengthNotMatching error will be raised.
- - + + \ No newline at end of file diff --git a/docs/dev/sql-syntax/functions/math/log/index.html b/docs/dev/sql-syntax/functions/math/log/index.html index 7be08508..e44b69e3 100644 --- a/docs/dev/sql-syntax/functions/math/log/index.html +++ b/docs/dev/sql-syntax/functions/math/log/index.html @@ -1,17 +1,17 @@ - + - + LOG | GlueSQL - - - + + +

LOG

The LOG function calculates the logarithm of a number with a specified base. It takes two FLOAT or INTEGER arguments and returns a FLOAT value representing the logarithm of the first argument with the base specified by the second argument.

Example

The following example demonstrates the usage of the LOG function in a SQL query:

CREATE TABLE SingleItem (id INTEGER DEFAULT LOG(2, 64));

INSERT INTO SingleItem VALUES (0);

SELECT
LOG(64.0, 2.0) as log_1,
LOG(0.04, 10.0) as log_2
FROM SingleItem;

This will return the following result:

log_1 | log_2
------+-------------------
6.0 | -1.39794

Errors

  1. If either of the arguments is not of FLOAT or INTEGER type, a FunctionRequiresFloatValue error will be raised.
  2. If the number of arguments provided to the function is not equal to 2, a FunctionArgsLengthNotMatching error will be raised.
- - + + \ No newline at end of file diff --git a/docs/dev/sql-syntax/functions/math/log10/index.html b/docs/dev/sql-syntax/functions/math/log10/index.html index ac77c8d6..c785b369 100644 --- a/docs/dev/sql-syntax/functions/math/log10/index.html +++ b/docs/dev/sql-syntax/functions/math/log10/index.html @@ -1,17 +1,17 @@ - + - + LOG10 | GlueSQL - - - + + +

LOG10

The LOG10 function is used to calculate the base-10 logarithm of a number. It takes a single FLOAT or INTEGER argument and returns a FLOAT value representing the base-10 logarithm of the given number.

Example

The following example demonstrates the usage of the LOG10 function in a SQL query:

CREATE TABLE SingleItem (id INTEGER DEFAULT LOG10(100));

INSERT INTO SingleItem VALUES (0);

SELECT
LOG10(64.0) as log10_1,
LOG10(0.04) as log10_2
FROM SingleItem;

This will return the following result:

log10_1 | log10_2
--------+-------------------
1.8062 | -1.3979

Errors

  1. If the argument is not of FLOAT or INTEGER type, a FunctionRequiresFloatValue error will be raised.
  2. If the number of arguments provided to the function is not equal to 1, a FunctionArgsLengthNotMatching error will be raised.
- - + + \ No newline at end of file diff --git a/docs/dev/sql-syntax/functions/math/log2/index.html b/docs/dev/sql-syntax/functions/math/log2/index.html index 31f303a7..50005a86 100644 --- a/docs/dev/sql-syntax/functions/math/log2/index.html +++ b/docs/dev/sql-syntax/functions/math/log2/index.html @@ -1,17 +1,17 @@ - + - + LOG2 | GlueSQL - - - + + +

LOG2

The LOG2 function is used to calculate the base-2 logarithm of a number. It takes a single FLOAT or INTEGER argument and returns a FLOAT value representing the base-2 logarithm of the given number.

Example

The following example demonstrates the usage of the LOG2 function in a SQL query:

CREATE TABLE SingleItem (id INTEGER DEFAULT LOG2(1024));

INSERT INTO SingleItem VALUES (0);

SELECT
LOG2(64.0) as log2_1,
LOG2(0.04) as log2_2
FROM SingleItem;

This will return the following result:

log2_1 | log2_2
-------+-------------------
6.0 | -4.5850

Errors

  1. If the argument is not of FLOAT or INTEGER type, a FunctionRequiresFloatValue error will be raised.
  2. If the number of arguments provided to the function is not equal to 1, a FunctionArgsLengthNotMatching error will be raised.
- - + + \ No newline at end of file diff --git a/docs/dev/sql-syntax/functions/math/mod/index.html b/docs/dev/sql-syntax/functions/math/mod/index.html index 71c194cb..357c9493 100644 --- a/docs/dev/sql-syntax/functions/math/mod/index.html +++ b/docs/dev/sql-syntax/functions/math/mod/index.html @@ -1,17 +1,17 @@ - + - + MOD | GlueSQL - - - + + +

MOD

The MOD function is used to calculate the remainder of a division operation. It takes two arguments (a dividend and a divisor) and returns the remainder of the division operation. Both dividend and divisor can be FLOAT or INTEGER type. The return type of the function is FLOAT.

Example

The following example demonstrates the usage of the MOD function in a SQL query:

CREATE TABLE FloatDiv (
dividend FLOAT DEFAULT MOD(30, 11),
divisor FLOAT DEFAULT DIV(3, 2)
);

INSERT INTO FloatDiv (dividend, divisor) VALUES (12.0, 3.0), (12.34, 56.78), (-12.3, 4.0);

SELECT MOD(dividend, divisor) FROM FloatDiv;

This will return the following result:

MOD(dividend, divisor)
0.0
12.34
-0.3

Errors

  1. If the divisor is zero, a DivisorShouldNotBeZero error will be raised.
  2. If either of the arguments is not of FLOAT or INTEGER type, a FunctionRequiresFloatOrIntegerValue error will be raised.
  3. If the number of arguments provided to the function is not equal to 2, a FunctionArgsLengthNotMatching error will be raised.
- - + + \ No newline at end of file diff --git a/docs/dev/sql-syntax/functions/math/pi/index.html b/docs/dev/sql-syntax/functions/math/pi/index.html index d2ba6289..c016301a 100644 --- a/docs/dev/sql-syntax/functions/math/pi/index.html +++ b/docs/dev/sql-syntax/functions/math/pi/index.html @@ -1,17 +1,17 @@ - + - + PI | GlueSQL - - - + + +

PI

The PI function is used to retrieve the mathematical constant π (pi), which is approximately 3.141592653589793. The function takes no arguments.

Syntax

PI()

Examples

Let's consider a table named SingleItem with the following schema:

CREATE TABLE SingleItem (id FLOAT);

Insert a row into the SingleItem table:

INSERT INTO SingleItem VALUES (0);

Example 1: Using PI function

SELECT PI() as pi FROM SingleItem;

Result:

        pi
----------------
3.141592653589793

Errors

The PI function expects no arguments. Providing any arguments will result in an error.

Example 2: Using PI with an argument

SELECT PI(0) as pi FROM SingleItem;

Error: Function expects 0 arguments, but 1 was provided.

- - + + \ No newline at end of file diff --git a/docs/dev/sql-syntax/functions/math/power/index.html b/docs/dev/sql-syntax/functions/math/power/index.html index 12329841..63643467 100644 --- a/docs/dev/sql-syntax/functions/math/power/index.html +++ b/docs/dev/sql-syntax/functions/math/power/index.html @@ -1,17 +1,17 @@ - + - + POWER | GlueSQL - - - + + +

POWER

The POWER function is used to raise a number to the power of another number. It takes two arguments, the base and the exponent, both of which must be of the FLOAT type. The result will also be of the FLOAT type.

Syntax

POWER(base, exponent)

Examples

  1. Using the POWER function:
SELECT POWER(2.0, 4) as power_1;
-- Result: 16.0
  1. Using the POWER function with a decimal:
SELECT POWER(0.07, 3) as power_2;
-- Result: 0.000343
  1. Using the POWER function with zero:
SELECT POWER(0, 4) as power_with_zero;
-- Result: 0.0

SELECT POWER(3, 0) as power_to_zero;
-- Result: 1.0

Error Cases

  1. The POWER function requires both arguments to be of FLOAT type:
SELECT POWER('string', 'string') AS power;
-- Error: FunctionRequiresFloatValue("POWER")
  1. The POWER function requires the base to be of FLOAT type:
SELECT POWER('string', 2.0) AS power;
-- Error: FunctionRequiresFloatValue("POWER")
  1. The POWER function requires the exponent to be of FLOAT type:
SELECT POWER(2.0, 'string') AS power;
-- Error: FunctionRequiresFloatValue("POWER")
- - + + \ No newline at end of file diff --git a/docs/dev/sql-syntax/functions/math/radians/index.html b/docs/dev/sql-syntax/functions/math/radians/index.html index faf304a9..2ff45079 100644 --- a/docs/dev/sql-syntax/functions/math/radians/index.html +++ b/docs/dev/sql-syntax/functions/math/radians/index.html @@ -1,17 +1,17 @@ - + - + RADIANS | GlueSQL - - - + + +

RADIANS

The RADIANS function is used to convert a given angle value from degrees to radians. It takes a single numeric argument (angle in degrees) and returns the angle in radians.

Syntax

RADIANS(value)
  • value: A numeric expression (angle in degrees) to be converted to radians.

Examples

Let's consider a table named SingleItem with the following schema:

CREATE TABLE SingleItem (id FLOAT);

Insert a row into the SingleItem table:

INSERT INTO SingleItem VALUES (0);

Example 1: Using RADIANS with float values

SELECT
RADIANS(180.0) as radians_1,
RADIANS(360.0) as radians_2
FROM SingleItem;

Result:

    radians_1 | radians_2
-------------+-------------
3.141593 | 6.283185

Example 2: Using RADIANS with integer values

SELECT RADIANS(90) as radians_with_int FROM SingleItem;

Result:

radians_with_int
-----------------
1.570796

Example 3: Using RADIANS with zero

SELECT RADIANS(0) as radians_with_zero FROM SingleItem;

Result:

radians_with_zero
------------------
0.0

Errors

The RADIANS function requires a numeric value as its argument. Using non-numeric values or more than one argument will result in an error.

Example 4: Using RADIANS with non-numeric values

SELECT RADIANS('string') AS radians FROM SingleItem;

Error: Function requires a numeric value.

Example 5: Using RADIANS with multiple arguments

SELECT RADIANS(0, 0) as radians_arg2 FROM SingleItem;

Error: Function expects 1 argument, but 2 were provided.

- - + + \ No newline at end of file diff --git a/docs/dev/sql-syntax/functions/math/rand/index.html b/docs/dev/sql-syntax/functions/math/rand/index.html index 528407c7..5f1dc3d9 100644 --- a/docs/dev/sql-syntax/functions/math/rand/index.html +++ b/docs/dev/sql-syntax/functions/math/rand/index.html @@ -1,17 +1,17 @@ - + - + RAND | GlueSQL - - - + + +

RAND

The RAND function is used to generate a random float value between 0 (inclusive) and 1 (exclusive). The function takes an optional seed value, which must be of the FLOAT type. If a seed value is provided, the random number generator will be initialized with that seed, producing a deterministic sequence of random numbers.

Syntax

RAND([seed])

Examples

  1. Using the RAND function without a seed:
SELECT RAND() AS rand;
-- Result: A random float between 0 and 1
  1. Using the RAND function with a seed:
SELECT RAND(123) AS rand1, RAND(789.0) AS rand2;
-- Result: 0.17325464426155657, 0.9635218234007941
  1. Using the RAND function with NULL:
SELECT RAND(NULL) AS rand;
-- Result: NULL

Error Cases

  1. The RAND function requires the argument to be of FLOAT type, if provided:
SELECT RAND('string') AS rand;
-- Error: FunctionRequiresFloatValue("RAND")

SELECT RAND(TRUE) AS rand;
-- Error: FunctionRequiresFloatValue("RAND")

SELECT RAND(FALSE) AS rand;
-- Error: FunctionRequiresFloatValue("RAND")
  1. The RAND function takes at most one argument:
SELECT RAND('string', 'string2') AS rand;
-- Error: FunctionArgsLengthNotWithinRange("RAND", 0, 1, 2)
- - + + \ No newline at end of file diff --git a/docs/dev/sql-syntax/functions/math/round/index.html b/docs/dev/sql-syntax/functions/math/round/index.html index 1d29cc0d..6ac581a2 100644 --- a/docs/dev/sql-syntax/functions/math/round/index.html +++ b/docs/dev/sql-syntax/functions/math/round/index.html @@ -1,17 +1,17 @@ - + - + ROUND | GlueSQL - - - + + +

ROUND

The ROUND function is used to round a number to the nearest integer value. It takes a single floating-point or integer value as its argument and returns a floating-point value.

Syntax

ROUND(value)

Examples

Let's consider a table named SingleItem with the following schema:

CREATE TABLE SingleItem (id INTEGER);

Insert a row into the SingleItem table:

INSERT INTO SingleItem VALUES (0);

Example 1: Using ROUND function

SELECT ROUND(0.3) AS round1,
ROUND(-0.8) AS round2,
ROUND(10) AS round3,
ROUND(6.87421) AS round4
FROM SingleItem;

Result:

round1 | round2 | round3 | round4
-------+--------+--------+--------
0.0 | -1.0 | 10.0 | 7.0

Note that the returned values are floating-point numbers, even though they represent integer values.

Errors

The ROUND function expects a floating-point or integer value as its argument. Providing any other type, such as a string or boolean, will result in an error.

Example 2: Using ROUND with a string argument

SELECT ROUND('string') AS round FROM SingleItem;

Error: Function requires a floating-point or integer value.

Example 3: Using ROUND with a boolean argument

SELECT ROUND(TRUE) AS round FROM SingleItem;

Error: Function requires a floating-point or integer value.

- - + + \ No newline at end of file diff --git a/docs/dev/sql-syntax/functions/math/sign/index.html b/docs/dev/sql-syntax/functions/math/sign/index.html index bc9d7c3f..65dec510 100644 --- a/docs/dev/sql-syntax/functions/math/sign/index.html +++ b/docs/dev/sql-syntax/functions/math/sign/index.html @@ -1,17 +1,17 @@ - + - + SIGN | GlueSQL - - - + + +

SIGN

The SIGN function is used to determine the sign of a number. It takes one argument, which must be of the FLOAT type. The result will be of the INTEGER type and can be -1, 0, or 1.

Syntax

SIGN(number)

Examples

  1. Using the SIGN function with integers:
SELECT SIGN(2) AS SIGN1, 
SIGN(-2) AS SIGN2,
SIGN(+2) AS SIGN3;
-- Result: 1, -1, 1
  1. Using the SIGN function with floats:
SELECT SIGN(2.0) AS SIGN1, 
SIGN(-2.0) AS SIGN2,
SIGN(+2.0) AS SIGN3;
-- Result: 1, -1, 1
  1. Using the SIGN function with zero:
SELECT SIGN(0.0) AS SIGN1, 
SIGN(-0.0) AS SIGN2,
SIGN(+0.0) AS SIGN3;
-- Result: 0, 0, 0
  1. Using the SIGN function with NULL:
SELECT SIGN(NULL) AS sign;
-- Result: NULL

Error Cases

  1. The SIGN function requires the argument to be of FLOAT type:
SELECT SIGN('string') AS SIGN;
-- Error: FunctionRequiresFloatValue("SIGN")

SELECT SIGN(TRUE) AS sign;
-- Error: FunctionRequiresFloatValue("SIGN")

SELECT SIGN(FALSE) AS sign;
-- Error: FunctionRequiresFloatValue("SIGN")
  1. The SIGN function takes exactly one argument:
SELECT SIGN('string', 'string2') AS SIGN;
-- Error: FunctionArgsLengthNotMatching("SIGN", 1, 2)
- - + + \ No newline at end of file diff --git a/docs/dev/sql-syntax/functions/math/sin/index.html b/docs/dev/sql-syntax/functions/math/sin/index.html index ac0d17d0..2683d4a0 100644 --- a/docs/dev/sql-syntax/functions/math/sin/index.html +++ b/docs/dev/sql-syntax/functions/math/sin/index.html @@ -1,17 +1,17 @@ - + - + SIN | GlueSQL - - - + + +

SIN

The SIN function is used to calculate the sine of a number. It takes a single numeric argument (angle in radians) and returns the sine of that angle.

Syntax

SIN(value)
  • value: A numeric expression (angle in radians) for which the sine is to be calculated.

Examples

Let's consider a table named SingleItem with the following schema:

CREATE TABLE SingleItem (id INTEGER);

Insert a row into the SingleItem table:

INSERT INTO SingleItem VALUES (0);

Example 1: Using SIN with float values

SELECT SIN(0.5) AS sin1, SIN(1) AS sin2 FROM SingleItem;

Result:

    sin1     |    sin2
-------------+--------------
0.479425539 | 0.841470984

Example 2: Using SIN with NULL values

SELECT SIN(NULL) AS sin FROM SingleItem;

Result:

  sin
-------
(null)

Errors

The SIN function requires a numeric value as its argument. Using non-numeric values or more than one argument will result in an error.

Example 3: Using SIN with non-numeric values

SELECT SIN('string') AS sin FROM SingleItem;

Error: Function requires a numeric value.

Example 4: Using SIN with multiple arguments

SELECT SIN(1.0, 2.0) AS sin FROM SingleItem;

Error: Function expects 1 argument, but 2 were provided.

- - + + \ No newline at end of file diff --git a/docs/dev/sql-syntax/functions/math/sqrt/index.html b/docs/dev/sql-syntax/functions/math/sqrt/index.html index 42d99573..cdcbb0cf 100644 --- a/docs/dev/sql-syntax/functions/math/sqrt/index.html +++ b/docs/dev/sql-syntax/functions/math/sqrt/index.html @@ -1,17 +1,17 @@ - + - + SQRT | GlueSQL - - - + + +

SQRT

The SQRT function is used to calculate the square root of a number. It takes one argument, which must be of the FLOAT type. The result will also be of the FLOAT type.

Syntax

SQRT(number)

Examples

  1. Using the SQRT function:
SELECT SQRT(2.0) as sqrt_1;
-- Result: 1.4142135623730951
  1. Using the SQRT function with a decimal:
SELECT SQRT(0.07) as sqrt_2;
-- Result: 0.2645751311064591
  1. Using the SQRT function with an integer:
SELECT SQRT(32) as sqrt_with_int;
-- Result: 5.656854249492381
  1. Using the SQRT function with zero:
SELECT SQRT(0) as sqrt_with_zero;
-- Result: 0.0
  1. Using the SQRT function with NULL:
SELECT SQRT(NULL) AS sqrt;
-- Result: NULL

Error Cases

  1. The SQRT function requires the argument to be of FLOAT type:
SELECT SQRT('string') AS sqrt;
-- Error: SqrtOnNonNumeric("string")
- - + + \ No newline at end of file diff --git a/docs/dev/sql-syntax/functions/math/tan/index.html b/docs/dev/sql-syntax/functions/math/tan/index.html index 5f77ea19..2eae2223 100644 --- a/docs/dev/sql-syntax/functions/math/tan/index.html +++ b/docs/dev/sql-syntax/functions/math/tan/index.html @@ -1,17 +1,17 @@ - + - + TAN | GlueSQL - - - + + +

TAN

The TAN function is used to calculate the tangent of a number. It takes a single numeric argument (angle in radians) and returns the tangent of that angle.

Syntax

TAN(value)
  • value: A numeric expression (angle in radians) for which the tangent is to be calculated.

Examples

Let's consider a table named SingleItem with the following schema:

CREATE TABLE SingleItem (id INTEGER);

Insert a row into the SingleItem table:

INSERT INTO SingleItem VALUES (0);

Example 1: Using TAN with float values

SELECT TAN(0.5) AS tan1, TAN(1) AS tan2 FROM SingleItem;

Result:

    tan1    |    tan2
------------+---------------
0.54630249 | 1.557407725

Example 2: Using TAN with NULL values

SELECT TAN(NULL) AS tan FROM SingleItem;

Result:

  tan
-------
(null)

Errors

The TAN function requires a numeric value as its argument. Using non-numeric values or more than one argument will result in an error.

Example 3: Using TAN with non-numeric values

SELECT TAN('string') AS tan FROM SingleItem;

Error: Function requires a numeric value.

Example 4: Using TAN with multiple arguments

SELECT TAN(1.0, 2.0) AS tan FROM SingleItem;

Error: Function expects 1 argument, but 2 were provided.

- - + + \ No newline at end of file diff --git a/docs/dev/sql-syntax/functions/others/cast/index.html b/docs/dev/sql-syntax/functions/others/cast/index.html index d51c299b..b366732d 100644 --- a/docs/dev/sql-syntax/functions/others/cast/index.html +++ b/docs/dev/sql-syntax/functions/others/cast/index.html @@ -1,17 +1,17 @@ - + - + CAST | GlueSQL - - - + + +

CAST

The CAST function is used to convert a value from one data type to another. It is commonly used when you need to change the data type of a value or a column to perform a specific operation, such as arithmetic or string concatenation.

Syntax

CAST(expression AS data_type)
  • expression: The value or column you want to convert.
  • data_type: The target data type to which you want to convert the expression.

Examples

Converting a value to a different data type

SELECT CAST('TRUE' AS BOOLEAN) AS cast;

In this example, the CAST function is used to convert the string 'TRUE' to a boolean value.

Converting a column to a different data type

Suppose you have a table called employees with the following structure:

CREATE TABLE employees (id INT, name TEXT, salary TEXT);

To calculate the total salary of all employees, you can use the CAST function to convert the salary column to a DECIMAL data type:

SELECT SUM(CAST(salary AS DECIMAL)) AS total_salary FROM employees;

Handling NULL values

The CAST function can handle NULL values as well. If the expression is NULL, the result will be NULL:

SELECT CAST(NULL AS INTEGER) AS cast;

This query will return a NULL value.

Converting a value to a DATE or TIME data type

The CAST function can also be used to convert strings to DATE or TIME data types:

SELECT CAST('2023-05-04' AS DATE) AS cast_date;
SELECT CAST('14:30:00' AS TIME) AS cast_time;

These queries will return a date and time value, respectively.

Limitations and Errors

Some conversions may be impossible or result in an error. For example, trying to convert a non-numeric string to an integer will result in an error:

SELECT CAST('foo' AS INTEGER) AS cast;

This query will produce an error because the string 'foo' cannot be converted to an integer.

- - + + \ No newline at end of file diff --git a/docs/dev/sql-syntax/functions/others/generate-uuid/index.html b/docs/dev/sql-syntax/functions/others/generate-uuid/index.html index 559141fb..a7d39f98 100644 --- a/docs/dev/sql-syntax/functions/others/generate-uuid/index.html +++ b/docs/dev/sql-syntax/functions/others/generate-uuid/index.html @@ -1,17 +1,17 @@ - + - + GENERATE_UUID | GlueSQL - - - + + +

GENERATE_UUID

The GENERATE_UUID function is an SQL function provided by GlueSQL that generates a new UUID (Universally Unique Identifier) using the version 4 UUID algorithm. A UUID is a 128-bit value used to uniquely identify items in various computing systems. Version 4 UUIDs are randomly generated and have 122 bits of randomness, which ensures a very low probability of collisions.

Syntax

GENERATE_UUID()

Usage

Creating a table with a UUID column

You can use the GENERATE_UUID function as the default value for a UUID column in a table.

CREATE TABLE SingleItem (id UUID DEFAULT GENERATE_UUID());

This SQL statement creates a table called SingleItem with a column named id of data type UUID. The default value for the id column is generated using the GENERATE_UUID function.

Inserting data with a UUID column

You can also use the GENERATE_UUID function directly when inserting data into a table.

INSERT INTO SingleItem VALUES (GENERATE_UUID());

This SQL statement inserts a new row into the SingleItem table with a UUID value generated using the GENERATE_UUID function.

Selecting data with a UUID column

You can use the GENERATE_UUID function in a SELECT statement to generate UUIDs on the fly.

SELECT GENERATE_UUID() as uuid FROM SingleItem;

This SQL statement selects a new UUID for each row in the SingleItem table.

Error Handling

The GENERATE_UUID function does not accept any arguments. If you provide any arguments to the function, an error will be raised.

SELECT generate_uuid(0) as uuid FROM SingleItem;

This SQL statement will result in an error, as the GENERATE_UUID function does not accept any arguments.

- - + + \ No newline at end of file diff --git a/docs/dev/sql-syntax/functions/others/ifnull/index.html b/docs/dev/sql-syntax/functions/others/ifnull/index.html index b218a75c..2a69469f 100644 --- a/docs/dev/sql-syntax/functions/others/ifnull/index.html +++ b/docs/dev/sql-syntax/functions/others/ifnull/index.html @@ -1,17 +1,17 @@ - + - + IFNULL | GlueSQL - - - + + +

IFNULL

The IFNULL function is used to return the first non-null value among the provided expressions. It takes two arguments and checks if the first argument is NULL. If the first argument is NULL, it returns the second argument; otherwise, it returns the first argument.

Syntax

IFNULL(expression1, expression2)

Examples

Consider the following SingleItem table:

CREATE TABLE SingleItem (
id INTEGER NULL,
int8 INT8 NULL,
dec DECIMAL NULL,
dt DATE NULL,
mystring TEXT NULL,
mybool BOOLEAN NULL,
myfloat FLOAT NULL,
mytime TIME NULL,
mytimestamp TIMESTAMP NULL
);

Insert two records into the SingleItem table:

INSERT INTO SingleItem VALUES (0, 1, 2, '2022-05-23', 'this is a string', true, 3.15, '01:02:03', '1970-01-01 00:00:00 -00:00');
INSERT INTO SingleItem VALUES (null, null, null, null, null, null, null, null, null);

Example 1: Using IFNULL with integer values:

SELECT IFNULL(id, 1) AS myid, IFNULL(int8, 2) AS int8, IFNULL(dec, 3)
FROM SingleItem WHERE id IS NOT NULL;

Example 2: Using IFNULL with date and text values:

SELECT IFNULL(dt, '2000-01-01') AS mydate, IFNULL(mystring, 'blah') AS name
FROM SingleItem WHERE id IS NOT NULL;

Example 3: Using IFNULL with boolean and float values:

SELECT IFNULL(mybool, 'YES') AS mybool, IFNULL(myfloat, 'NO') AS myfloat
FROM SingleItem WHERE id IS NOT NULL;

Example 4: Using IFNULL with time and timestamp values:

SELECT IFNULL(mytime, 'YES') AS mybool, IFNULL(mytimestamp, 'NO') AS myfloat
FROM SingleItem WHERE id IS NOT NULL;
- - + + \ No newline at end of file diff --git a/docs/dev/sql-syntax/functions/text/ascii/index.html b/docs/dev/sql-syntax/functions/text/ascii/index.html index 3face52b..72ff7577 100644 --- a/docs/dev/sql-syntax/functions/text/ascii/index.html +++ b/docs/dev/sql-syntax/functions/text/ascii/index.html @@ -1,17 +1,17 @@ - + - + ASCII | GlueSQL - - - + + +

ASCII

The ASCII function in SQL returns the ASCII value for the first character of the specified string.

Syntax

The syntax for the ASCII function in SQL is:

ASCII ( single_character_text )

Parameters

  • single_character_text: This is the string that the ASCII value should be returned for. It should be a single character string.

Examples

Let's consider a few examples to understand how to use the ASCII function.

To get the ASCII value of a character:

VALUES(ASCII('A'));

This will return 65, which is the ASCII value for 'A'.

Please note that the ASCII function expects a single character value. If a string with more than one character is passed, it will throw an error. For instance:

VALUES(ASCII('AB'));

This will throw an error because 'AB' contains more than one character.

You can also use the ASCII function in a SELECT statement. Consider the following table named 'Ascii':

idtext
1'F'
CREATE TABLE Ascii (
id INTEGER,
text TEXT
);
INSERT INTO Ascii VALUES (1, 'F');

You can select the ASCII value of the 'text' column:

SELECT ASCII(text) AS ascii FROM Ascii;

This will return 70, which is the ASCII value for 'F'.

The ASCII function can also take a string directly:

SELECT ASCII('a') AS ascii FROM Ascii;

This will return 97, which is the ASCII value for 'a'.

If a non-ASCII character is passed to the function, it will throw an error. For instance:

SELECT ASCII('ㄱ') AS ascii FROM Ascii;

This will throw an error because 'ㄱ' is not an ASCII character.

If no argument is passed to the ASCII function, it will also throw an error:

SELECT ASCII() AS ascii FROM Ascii;

This will throw an error because the ASCII function expects one argument.

Remember, the ASCII function expects a single character. If the column value contains more than one character, it will throw an error:

INSERT INTO Ascii VALUES (1, 'Foo');
SELECT ASCII(text) AS ascii FROM Ascii;

This will throw an error because 'Foo' contains more than one character.

- - + + \ No newline at end of file diff --git a/docs/dev/sql-syntax/functions/text/chr/index.html b/docs/dev/sql-syntax/functions/text/chr/index.html index 30dc8046..94033ac8 100644 --- a/docs/dev/sql-syntax/functions/text/chr/index.html +++ b/docs/dev/sql-syntax/functions/text/chr/index.html @@ -1,17 +1,17 @@ - + - + CHR | GlueSQL - - - + + +

CHR

The CHR function in SQL returns the character represented by the specified ASCII value.

Syntax

The syntax for the CHR function in SQL is:

CHR ( ascii_value )

Parameters

  • ascii_value: This is the ASCII value for which the character should be returned. It should be an integer value between 0 and 255.

Examples

Let's consider a few examples to understand how to use the CHR function.

To get the character for an ASCII value:

VALUES(CHR(70));

This will return 'F', which is the character for the ASCII value 70.

Please note that the CHR function expects an integer value between 0 and 255. If a value outside this range is passed, it will throw an error. For instance:

VALUES(CHR(7070));

This will throw an error because 7070 is not a valid ASCII value.

You can also use the CHR function in a SELECT statement. Consider the following table named 'Chr':

idnum
170
CREATE TABLE Chr (
id INTEGER,
num INTEGER
);
INSERT INTO Chr VALUES (1, 70);

You can select the character for the 'num' column:

SELECT CHR(num) AS chr FROM Chr;

This will return 'F', which is the character for the ASCII value 70.

The CHR function can also take an integer value directly:

SELECT CHR(65) AS chr FROM Chr;

This will return 'A', which is the character for the ASCII value 65.

If a non-integer value is passed to the function, it will throw an error. For instance:

SELECT CHR('ukjhg') AS chr FROM Chr;

This will throw an error because 'ukjhg' is not an integer value.

Remember, the CHR function expects an integer value between 0 and 255. If the column value is outside this range, it will throw an error:

INSERT INTO Chr VALUES (1, 4345);
SELECT CHR(num) AS chr FROM Chr;

This will throw an error because 4345 is not a valid ASCII value.

- - + + \ No newline at end of file diff --git a/docs/dev/sql-syntax/functions/text/concat-ws/index.html b/docs/dev/sql-syntax/functions/text/concat-ws/index.html index 35a562c3..2050409c 100644 --- a/docs/dev/sql-syntax/functions/text/concat-ws/index.html +++ b/docs/dev/sql-syntax/functions/text/concat-ws/index.html @@ -1,17 +1,17 @@ - + - + CONCAT_WS | GlueSQL - - - + + +

CONCAT_WS

The CONCAT_WS function in SQL concatenates two or more strings into one string with a separator.

Syntax

The syntax for the CONCAT_WS function in SQL is:

CONCAT_WS ( separator, string1, string2, ..., stringN )

Parameters

  • separator: This is the string that will be placed between each string to be concatenated.
  • string1, string2, ..., stringN: These are the strings that you wish to concatenate together.

Examples

Let's consider a few examples to understand how to use the CONCAT_WS function.

To concatenate strings with a comma separator:

VALUES(CONCAT_WS(',', 'AB', 'CD', 'EF'));

This will return 'AB,CD,EF'.

You can also concatenate more than two strings:

SELECT CONCAT_WS('/', 'ab', 'cd', 'ef') AS myconcat;

This will return 'ab/cd/ef'.

The CONCAT_WS function will skip any NULL values:

SELECT CONCAT_WS('', 'ab', 'cd', NULL, 'ef') AS myconcat;

This will return 'abcdef'.

The CONCAT_WS function can also take non-string arguments:

SELECT CONCAT_WS('', 123, 456, 3.14) AS myconcat;

This will return '1234563.14'. In this case, the integers and float values are implicitly converted to strings before concatenation.

However, the CONCAT_WS function expects at least two arguments. If fewer than two arguments are passed to the CONCAT_WS function, it will throw an error:

SELECT CONCAT_WS() AS myconcat;

This will throw an error because the CONCAT_WS function expects at least two arguments.

- - + + \ No newline at end of file diff --git a/docs/dev/sql-syntax/functions/text/concat/index.html b/docs/dev/sql-syntax/functions/text/concat/index.html index 127025e3..35e4d4d7 100644 --- a/docs/dev/sql-syntax/functions/text/concat/index.html +++ b/docs/dev/sql-syntax/functions/text/concat/index.html @@ -1,17 +1,17 @@ - + - + CONCAT | GlueSQL - - - + + +

CONCAT

The CONCAT function in SQL concatenates two or more strings into one string.

Syntax

The syntax for the CONCAT function in SQL is:

CONCAT ( string1, string2, ..., stringN )

Parameters

  • string1, string2, ..., stringN: These are the strings that you wish to concatenate together.

Examples

Let's consider a few examples to understand how to use the CONCAT function.

To concatenate two strings:

SELECT CONCAT('ab', 'cd') AS myconcat;

This will return 'abcd'.

You can also concatenate more than two strings:

SELECT CONCAT('ab', 'cd', 'ef') AS myconcat;

This will return 'abcdef'.

If any string in the CONCAT function is NULL, the function will return NULL:

SELECT CONCAT('ab', 'cd', NULL, 'ef') AS myconcat;

This will return NULL.

The CONCAT function can also take non-string arguments:

SELECT CONCAT(123, 456, 3.14) AS myconcat;

This will return '1234563.14'. In this case, the integers and float values are implicitly converted to strings before concatenation.

However, the CONCAT function expects at least one argument. If no arguments are passed to the CONCAT function, it will throw an error:

SELECT CONCAT() AS myconcat;

This will throw an error because the CONCAT function expects at least one argument.

- - + + \ No newline at end of file diff --git a/docs/dev/sql-syntax/functions/text/find-idx/index.html b/docs/dev/sql-syntax/functions/text/find-idx/index.html index 28aa86f4..2ac25aaa 100644 --- a/docs/dev/sql-syntax/functions/text/find-idx/index.html +++ b/docs/dev/sql-syntax/functions/text/find-idx/index.html @@ -1,17 +1,17 @@ - + - + FIND_IDX | GlueSQL - - - + + +

FIND_IDX

The FIND_IDX function in SQL is used to return the position of the first occurrence of a substring in a string, optionally after a specified position.

Syntax

The syntax for the FIND_IDX function in SQL is:

FIND_IDX ( string, substring, [ start_position ] )

Parameters

  • string: The string where the search will take place.
  • substring: The substring to find.
  • start_position (optional): The position at which to start the search. The first position in the string is 0. If the start_position is not specified, the search starts from the beginning of the string.

Examples

Let's consider a few examples to understand how to use the FIND_IDX function.

Find the position of 'rg' in 'pork':

SELECT FIND_IDX('pork', 'rg') AS test;

This will return 0, as 'rg' is not found in 'pork'.

Find the position of 'rg' in 'burger':

SELECT FIND_IDX('burger', 'rg') AS test;

This will return 3, as the first occurrence of 'rg' in 'burger' is at position 3.

Find the position of 'r' in 'pork', starting from position 4:

SELECT FIND_IDX('pork', 'r', 4) AS test;

This will return 0, as 'r' is not found in 'pork' after position 4.

Find the position of 'r' in 'burger', starting from position 4:

SELECT FIND_IDX('burger', 'r', 4) AS test;

This will return 6, as the first occurrence of 'r' in 'burger' after position 4 is at position 6.

Find the position of an empty string in 'cheese':

SELECT FIND_IDX('cheese', '') AS test;

This will return 0, because the search starts at the first position by default and the empty string is considered to be found at the start of any string.

Find the position of 's' in 'cheese':

SELECT FIND_IDX('cheese', 's') AS test;

This will return 5, as the first occurrence of 's' in 'cheese' is at position 5.

Find the position of 'e' in 'cheese burger', starting from position 5:

SELECT FIND_IDX('cheese burger', 'e', 5) AS test;

This will return 6, because the search starts from position 5 and the next 'e' is at position 6.

Using a NULL value as the substring will return NULL:

SELECT FIND_IDX('cheese', NULL) AS test;
- - + + \ No newline at end of file diff --git a/docs/dev/sql-syntax/functions/text/initcap/index.html b/docs/dev/sql-syntax/functions/text/initcap/index.html index 0a2c29f1..b6b827e1 100644 --- a/docs/dev/sql-syntax/functions/text/initcap/index.html +++ b/docs/dev/sql-syntax/functions/text/initcap/index.html @@ -1,17 +1,17 @@ - + - + INITCAP | GlueSQL - - - + + +

INITCAP

The INITCAP function in SQL is used to capitalize the first letter of each word in a string and convert the rest of the characters to lowercase.

Syntax

The syntax for the INITCAP function in SQL is:

INITCAP( string )

Parameters

  • string: The input string on which the capitalization will be applied.

Examples

Let's consider a few examples to understand how to use the INITCAP function.

Create a table named Item with a column name:

CREATE TABLE Item (
name TEXT DEFAULT 'abcd',
);

Insert some data into the Item table:

INSERT INTO Item VALUES
('h/i jk'),
(NULL),
('H/I JK');

Select rows where the INITCAP(name) is equal to 'H/I Jk':

SELECT name FROM Item WHERE INITCAP(name) = 'H/I Jk';

This will return the rows with 'h/i jk' and 'H/I JK', as both have the same result after applying the INITCAP function.

Apply the INITCAP function to the name column and return the result:

SELECT INITCAP(name) FROM Item;

This will return 'H/I Jk', NULL, and 'H/I Jk' for the three rows, respectively.

The INITCAP function expects a string value as the input. If a non-string value is passed as the input, it will throw an error:

SELECT INITCAP(1) FROM Item;

This will throw an error because the INITCAP function expects a string value as the input.

The INITCAP function expects a single argument. If no arguments are provided, it will throw an error:

SELECT INITCAP() FROM Item;

This will throw an error because the INITCAP function expects a single argument.

The INITCAP function does not support named arguments. If a named argument is provided, it will throw an error:

SELECT INITCAP(a => 2) FROM Item;

This will throw an error because the INITCAP function does not support named arguments.

- - + + \ No newline at end of file diff --git a/docs/dev/sql-syntax/functions/text/left/index.html b/docs/dev/sql-syntax/functions/text/left/index.html index 09b0928e..d016f995 100644 --- a/docs/dev/sql-syntax/functions/text/left/index.html +++ b/docs/dev/sql-syntax/functions/text/left/index.html @@ -1,17 +1,17 @@ - + - + LEFT | GlueSQL - - - + + +

LEFT

The LEFT function in SQL returns the specified number of characters from the start (left side) of a given string.

Syntax

LEFT(string, number)

Parameters

  • string: The original string from which to extract characters.
  • number: The number of characters to extract from the start of the string. This must be an integer.

Return Value

The function returns a string, which consists of the specified number of characters from the start of the original string. If the original string is shorter than the specified number, the function returns the whole string.

Errors

  • If the number argument is not an integer, a FunctionRequiresIntegerValue error will be returned.
  • If the string argument is not a string, a FunctionRequiresStringValue error will be returned.

Examples

Consider a table Item created and filled with the following data:

CREATE TABLE Item (
name TEXT DEFAULT LEFT('abc', 1)
);
INSERT INTO Item VALUES ('Blop mc blee'), ('B'), ('Steven the &long named$ folken!');

You can use the LEFT function to extract the first three characters of each name:

SELECT LEFT(name, 3) AS test FROM Item;

This will return:

Blo
B
Ste

Note that when the string length is less than the specified number (as with 'B'), the function will return the whole string.

- - + + \ No newline at end of file diff --git a/docs/dev/sql-syntax/functions/text/lower/index.html b/docs/dev/sql-syntax/functions/text/lower/index.html index 43b703aa..1ad5ddd7 100644 --- a/docs/dev/sql-syntax/functions/text/lower/index.html +++ b/docs/dev/sql-syntax/functions/text/lower/index.html @@ -1,17 +1,17 @@ - + - + LOWER | GlueSQL - - - + + +

LOWER

The LOWER function in SQL returns a string in which all alphabetic characters in a specified string are converted to lowercase.

Syntax

LOWER(string)

Parameters

  • string: The original string to convert.

Return Value

The function returns a new string that is the same as the original string, but with all uppercase characters converted to lowercase. Non-alphabetic characters in the string are unaffected.

Errors

  • If the string argument is not a string, a FunctionRequiresStringValue error will be returned.

Examples

Consider a table Item created and filled with the following data:

CREATE TABLE Item (
name TEXT
);
INSERT INTO Item VALUES ('ABCD'), ('Abcd'), ('abcd');

You can use the LOWER function to convert all name values to lowercase:

SELECT LOWER(name) AS lower_name FROM Item;

This will return:

abcd
abcd
abcd

Note that the LOWER function affects only alphabetic characters. Non-alphabetic characters in the string remain unchanged.

- - + + \ No newline at end of file diff --git a/docs/dev/sql-syntax/functions/text/lpad/index.html b/docs/dev/sql-syntax/functions/text/lpad/index.html index 52c5b66b..97e89ae1 100644 --- a/docs/dev/sql-syntax/functions/text/lpad/index.html +++ b/docs/dev/sql-syntax/functions/text/lpad/index.html @@ -1,17 +1,17 @@ - + - + LPAD | GlueSQL - - - + + +

LPAD

The LPAD function in SQL pads the left side of a string with a specific set of characters.

Syntax

LPAD(string, length, pad_string)

Parameters

  • string: The original string to pad.
  • length: The length of the resulting string after padding. If this is less than the length of the original string, the result is truncated.
  • pad_string (optional): The string to use for padding. If not supplied, spaces are used.

Return Value

The function returns a new string that is the same as the original string, but with additional padding on the left side to achieve the specified length.

Errors

  • If the string argument is not a string, a FunctionRequiresStringValue error will be returned.
  • If the length argument is not a positive integer, a FunctionRequiresUSizeValue error will be returned.

Examples

Consider a table Item created and filled with the following data:

CREATE TABLE Item (
name TEXT
);
INSERT INTO Item VALUES ('hello');

You can use the LPAD function to pad the name values to a length of 10 with the character 'a':

SELECT LPAD(name, 10, 'a') AS padded_name FROM Item;

This will return:

aaaaahello

If the length argument is less than the length of the string, the original string will be truncated:

SELECT LPAD(name, 3, 'a') AS padded_name FROM Item;

This will return:

hel
- - + + \ No newline at end of file diff --git a/docs/dev/sql-syntax/functions/text/ltrim/index.html b/docs/dev/sql-syntax/functions/text/ltrim/index.html index ae25a62c..527596c2 100644 --- a/docs/dev/sql-syntax/functions/text/ltrim/index.html +++ b/docs/dev/sql-syntax/functions/text/ltrim/index.html @@ -1,17 +1,17 @@ - + - + LTRIM | GlueSQL - - - + + +

LTRIM

The LTRIM function in SQL removes characters from the left (leading side) of a string.

Syntax

LTRIM(string, trim_string)

Parameters

  • string: The original string to trim.
  • trim_string (optional): The characters to remove from the string. If not supplied, spaces are removed.

Return Value

The function returns a new string that is the same as the original string, but without the specified leading characters.

Errors

  • If the string or trim_string argument is not a string, a FunctionRequiresStringValue error will be returned.

Examples

Consider a table Item created and filled with the following data:

CREATE TABLE Item (
name TEXT
);
INSERT INTO Item VALUES (' zzzytest');

You can use the LTRIM function to remove leading spaces from the name values:

SELECT LTRIM(name) AS trimmed_name FROM Item;

This will return:

zzzytest

You can also specify a string of characters to remove. The function will remove any character in this string from the start of the original string:

SELECT LTRIM(name, ' z') AS trimmed_name FROM Item;

This will return:

ytest
- - + + \ No newline at end of file diff --git a/docs/dev/sql-syntax/functions/text/position/index.html b/docs/dev/sql-syntax/functions/text/position/index.html index 71f2e2eb..723fdb15 100644 --- a/docs/dev/sql-syntax/functions/text/position/index.html +++ b/docs/dev/sql-syntax/functions/text/position/index.html @@ -1,17 +1,17 @@ - + - + POSITION | GlueSQL - - - + + +

POSITION

The POSITION function in SQL is used to find the position of a substring in a string. The position of the first occurrence of the substring is returned. If the substring is not found, this function returns 0.

Syntax

POSITION(substring IN string)

Parameters

  • substring: The substring to search for.
  • string: The string in which to search.

Return Value

The function returns an integer representing the position of the first occurrence of the substring in the string, starting from 1. If the substring is not found, the function returns 0.

Errors

  • If either substring or string are not string values, a ValueError::NonStringParameterInPosition error will be returned.

Examples

Consider a table Food created and filled with the following data:

CREATE TABLE Food (
name TEXT
);
INSERT INTO Food VALUES ('pork');
INSERT INTO Food VALUES ('burger');

You can use the POSITION function to find the position of a substring within the name values:

SELECT POSITION('e' IN name) AS test FROM Food;

This will return:

0
5

The first 'e' in 'burger' is at position 5, so the function returns 5 for 'burger'. There is no 'e' in 'pork', so the function returns 0 for 'pork'.

- - + + \ No newline at end of file diff --git a/docs/dev/sql-syntax/functions/text/repeat/index.html b/docs/dev/sql-syntax/functions/text/repeat/index.html index df8e086e..a4af3e5b 100644 --- a/docs/dev/sql-syntax/functions/text/repeat/index.html +++ b/docs/dev/sql-syntax/functions/text/repeat/index.html @@ -1,17 +1,17 @@ - + - + REPEAT | GlueSQL - - - + + +

REPEAT

The REPEAT function in SQL is used to repeat a string for a specified number of times.

Syntax

REPEAT(string, number)

Parameters

  • string: The string to be repeated.
  • number: The number of times to repeat the string.

Return Value

The function returns a string which is the concatenation of the input string repeated the specified number of times.

Errors

  • If the parameters are not in the correct format, a TranslateError::FunctionArgsLengthNotMatching error will be returned. This function requires exactly two arguments.
  • If either string or number are not string values, a EvaluateError::FunctionRequiresStringValue error will be returned.

Examples

Consider a table Item created and filled with the following data:

CREATE TABLE Item (name TEXT);
INSERT INTO Item VALUES ('hello');

You can use the REPEAT function to repeat the name values:

SELECT REPEAT(name, 2) AS test FROM Item;

This will return:

hellohello

The 'hello' string is repeated twice as specified by the second parameter to the REPEAT function.

- - + + \ No newline at end of file diff --git a/docs/dev/sql-syntax/functions/text/reverse/index.html b/docs/dev/sql-syntax/functions/text/reverse/index.html index 3d18e1e7..410fa673 100644 --- a/docs/dev/sql-syntax/functions/text/reverse/index.html +++ b/docs/dev/sql-syntax/functions/text/reverse/index.html @@ -1,17 +1,17 @@ - + - + REVERSE | GlueSQL - - - + + +

REVERSE

The REVERSE function in SQL is used to reverse a string.

Syntax

REVERSE(string)

Parameters

  • string: The string to be reversed.

Return Value

The function returns a string which is the reverse of the input string.

Errors

If the parameter is not a string value, a EvaluateError::FunctionRequiresStringValue error will be returned.

Examples

Consider a table Item created and filled with the following data:

CREATE TABLE Item (name TEXT);
INSERT INTO Item VALUES ('Let''s meet');

You can use the REVERSE function to reverse the name values:

SELECT REVERSE(name) AS test FROM Item;

This will return:

teem s'teL

The 'Let''s meet' string is reversed as 'teem s'teL'.

- - + + \ No newline at end of file diff --git a/docs/dev/sql-syntax/functions/text/right/index.html b/docs/dev/sql-syntax/functions/text/right/index.html index 0ba49513..e4aa395f 100644 --- a/docs/dev/sql-syntax/functions/text/right/index.html +++ b/docs/dev/sql-syntax/functions/text/right/index.html @@ -1,17 +1,17 @@ - + - + RIGHT | GlueSQL - - - + + +

RIGHT

The RIGHT function in SQL returns the specified number of characters from the end (right side) of a given string.

Syntax

RIGHT(string, number)

Parameters

  • string: The original string from which to extract characters.
  • number: The number of characters to extract from the end of the string. This must be an integer.

Return Value

The function returns a string, which consists of the specified number of characters from the end of the original string. If the original string is shorter than the specified number, the function returns the whole string.

Errors

  • If the number argument is not an integer, a FunctionRequiresIntegerValue error will be returned.
  • If the string argument is not a string, a FunctionRequiresStringValue error will be returned.
  • If the number argument is negative, a FunctionRequiresUSizeValue error will be returned.

Examples

Consider a table Item created and filled with the following data:

CREATE TABLE Item (
name TEXT
);
INSERT INTO Item VALUES ('Blop mc blee'), ('B'), ('Steven the &long named$ folken!');

You can use the RIGHT function to extract the last three characters of each name:

SELECT RIGHT(name, 3) AS test FROM Item;

This will return:

lee
B
en!

Note that when the string length is less than the specified number (as with 'B'), the function will return the whole string.

- - + + \ No newline at end of file diff --git a/docs/dev/sql-syntax/functions/text/rpad/index.html b/docs/dev/sql-syntax/functions/text/rpad/index.html index c038a2a4..d95cd7fd 100644 --- a/docs/dev/sql-syntax/functions/text/rpad/index.html +++ b/docs/dev/sql-syntax/functions/text/rpad/index.html @@ -1,17 +1,17 @@ - + - + RPAD | GlueSQL - - - + + +

RPAD

The RPAD function in SQL pads the right side of a string with a specific set of characters.

Syntax

RPAD(string, length, pad_string)

Parameters

  • string: The original string to pad.
  • length: The length of the resulting string after padding. If this is less than the length of the original string, the result is truncated.
  • pad_string (optional): The string to use for padding. If not supplied, spaces are used.

Return Value

The function returns a new string that is the same as the original string, but with additional padding on the right side to achieve the specified length.

Errors

  • If the string argument is not a string, a FunctionRequiresStringValue error will be returned.
  • If the length argument is not a positive integer, a FunctionRequiresUSizeValue error will be returned.

Examples

Consider a table Item created and filled with the following data:

CREATE TABLE Item (
name TEXT
);
INSERT INTO Item VALUES ('hello');

You can use the RPAD function to pad the name values to a length of 10 with the character 'b':

SELECT RPAD(name, 10, 'b') AS padded_name FROM Item;

This will return:

hellobbbbb

If the length argument is less than the length of the string, the original string will be truncated:

SELECT RPAD(name, 3, 'b') AS padded_name FROM Item;

This will return:

hel
- - + + \ No newline at end of file diff --git a/docs/dev/sql-syntax/functions/text/rtrim/index.html b/docs/dev/sql-syntax/functions/text/rtrim/index.html index 3f521221..e9186abe 100644 --- a/docs/dev/sql-syntax/functions/text/rtrim/index.html +++ b/docs/dev/sql-syntax/functions/text/rtrim/index.html @@ -1,17 +1,17 @@ - + - + RTRIM | GlueSQL - - - + + +

RTRIM

The RTRIM function in SQL removes characters from the right (trailing side) of a string.

Syntax

RTRIM(string, trim_string)

Parameters

  • string: The original string to trim.
  • trim_string (optional): The characters to remove from the string. If not supplied, spaces are removed.

Return Value

The function returns a new string that is the same as the original string, but without the specified trailing characters.

Errors

  • If the string or trim_string argument is not a string, a FunctionRequiresStringValue error will be returned.

Examples

Consider a table Item created and filled with the following data:

CREATE TABLE Item (
name TEXT
);
INSERT INTO Item VALUES ('testxxzx ');

You can use the RTRIM function to remove trailing spaces from the name values:

SELECT RTRIM(name) AS trimmed_name FROM Item;

This will return:

testxxzx

You can also specify a string of characters to remove. The function will remove any character in this string from the end of the original string:

SELECT RTRIM(name, 'zx ') AS trimmed_name FROM Item;

This will return:

test
- - + + \ No newline at end of file diff --git a/docs/dev/sql-syntax/functions/text/substr/index.html b/docs/dev/sql-syntax/functions/text/substr/index.html index e9f3f813..8224f98d 100644 --- a/docs/dev/sql-syntax/functions/text/substr/index.html +++ b/docs/dev/sql-syntax/functions/text/substr/index.html @@ -1,17 +1,17 @@ - + - + SUBSTR | GlueSQL - - - + + +

SUBSTR

The SUBSTR function in SQL is used to extract a substring from a string.

Syntax

SUBSTR(string, start_position, length)

Parameters

  • string: The original string.
  • start_position: The position in the string where the extraction of the substring will begin. The position of the first character is 1. If start_position is 0 or negative, the function treats it as 1.
  • length (optional): The number of characters to extract. If length is not included, the function will return all characters starting from start_position.

Return Value

The function returns a string which is a substring of the original string. The substring starts at start_position and has length number of characters.

Errors

  • If the string parameter is not a string value, a EvaluateError::FunctionRequiresStringValue error will be returned.
  • If the start_position or length parameters are not integer values, a EvaluateError::FunctionRequiresIntegerValue error will be returned.
  • If the length parameter is negative, a EvaluateError::NegativeSubstrLenNotAllowed error will be returned.

Examples

Consider a table Item created and filled with the following data:

CREATE TABLE Item (name TEXT);
INSERT INTO Item VALUES ('Blop mc blee'), ('B'), ('Steven the &long named$ folken!');

You can use the SUBSTR function to get a substring from the name values:

SELECT SUBSTR(name, 2) AS test FROM Item;

This will return:

lop mc blee
(empty string)
teven the &long named$ folken!

The function takes the substring starting from the second character until the end for each name value.

- - + + \ No newline at end of file diff --git a/docs/dev/sql-syntax/functions/text/trim/index.html b/docs/dev/sql-syntax/functions/text/trim/index.html index f39c5125..fc1c5eee 100644 --- a/docs/dev/sql-syntax/functions/text/trim/index.html +++ b/docs/dev/sql-syntax/functions/text/trim/index.html @@ -1,17 +1,17 @@ - + - + TRIM | GlueSQL - - - + + +

TRIM

The TRIM function in SQL is used to remove leading, trailing, or both leading and trailing unwanted characters (often whitespace) from a string.

Syntax

TRIM([LEADING | TRAILING | BOTH] [removal_string] FROM target_string)

If LEADING, TRAILING, or BOTH is not specified, TRIM function will remove both leading and trailing spaces.

Examples

Here we are creating a table named Item with a default value for the name column. The default value is obtained by concatenating two strings. The first string is the result of trimming leading 'a' from 'aabc' and the second string is the result of trimming spaces from ' good '.

CREATE TABLE Item (
name TEXT DEFAULT TRIM(LEADING 'a' FROM 'aabc') || TRIM(' good ')
)

We insert some data into the Item table:

INSERT INTO Item VALUES
(' Left blank'),
('Right blank '),
(' Blank! '),
('Not Blank');

The TRIM function is used in a SELECT statement to remove leading and trailing spaces from the name column in the Item table:

SELECT TRIM(name) FROM Item;

The TRIM function can also be used with NULL values. If the value is NULL, the TRIM function will return NULL.

CREATE TABLE NullName (name TEXT NULL);
INSERT INTO NullName VALUES (NULL);
SELECT TRIM(name) AS test FROM NullName;

You can also specify a specific character to remove from the string. The following example removes 'xyz' from the string:

CREATE TABLE Test (name TEXT);
INSERT INTO Test VALUES
(' blank '),
('xxxyzblankxyzxx'),
('xxxyzblank '),
(' blankxyzxx'),
(' xyzblankxyzxx'),
('xxxyzblankxyz ');
SELECT TRIM(BOTH 'xyz' FROM name) FROM Test;

The LEADING and TRAILING keywords can be used to remove characters from the beginning or the end of the string, respectively:

SELECT TRIM(LEADING 'xyz' FROM name) FROM Test;
SELECT TRIM(TRAILING 'xyz' FROM name) FROM Test;

You can also nest TRIM functions:

SELECT TRIM(BOTH TRIM(BOTH ' potato ')) AS Case1;

The TRIM function requires string values. If you try to use it with a non-string value, an error will occur:

SELECT TRIM('1' FROM 1) AS test FROM Test;
- - + + \ No newline at end of file diff --git a/docs/dev/sql-syntax/functions/text/upper/index.html b/docs/dev/sql-syntax/functions/text/upper/index.html index 11915bbb..c2886ff6 100644 --- a/docs/dev/sql-syntax/functions/text/upper/index.html +++ b/docs/dev/sql-syntax/functions/text/upper/index.html @@ -1,17 +1,17 @@ - + - + UPPER | GlueSQL - - - + + +

UPPER

The UPPER function in SQL converts all lowercase alphabetic characters in a specified string to uppercase.

Syntax

UPPER(string)

Parameters

  • string: The original string to convert.

Return Value

The function returns a new string that is the same as the original string, but with all lowercase characters converted to uppercase. Non-alphabetic characters in the string are unaffected.

Errors

  • If the string argument is not a string, a FunctionRequiresStringValue error will be returned.

Examples

Consider a table Item created and filled with the following data:

CREATE TABLE Item (
name TEXT
);
INSERT INTO Item VALUES ('abcd'), ('Abcd'), ('ABCD');

You can use the UPPER function to convert all name values to uppercase:

SELECT UPPER(name) AS upper_name FROM Item;

This will return:

ABCD
ABCD
ABCD

Note that the UPPER function affects only alphabetic characters. Non-alphabetic characters in the string remain unchanged.

- - + + \ No newline at end of file diff --git a/docs/dev/sql-syntax/intro/index.html b/docs/dev/sql-syntax/intro/index.html index 89e96900..a0865f07 100644 --- a/docs/dev/sql-syntax/intro/index.html +++ b/docs/dev/sql-syntax/intro/index.html @@ -1,18 +1,18 @@ - + - + Introduction | GlueSQL - - - + + +

SQL Syntax

Welcome to the Introduction page for the SQL Syntax category in GlueSQL! In this section, we'll provide a brief overview of the SQL syntax supported by GlueSQL. You can find more in-depth examples and details by browsing the other pages in this category.

GlueSQL is a SQL database engine written in Rust, designed to be lightweight, fast, and easy to integrate with various data storage systems. It supports a wide range of SQL features, including creating and managing tables, inserting and updating data, and performing various types of queries.

Here's a list of some basic SQL statements you can use with GlueSQL:

Creating Tables

CREATE TABLE table_name (
column_name1 data_type1,
column_name2 data_type2,
...
);

Inserting Data

INSERT INTO table_name (column1, column2, ...) VALUES (value1, value2, ...);

Selecting Data

SELECT column1, column2, ... FROM table_name WHERE conditions;

Updating Data

UPDATE table_name SET column1 = value1, column2 = value2, ... WHERE conditions;

Deleting Data

DELETE FROM table_name WHERE conditions;

For a complete list of supported SQL features, you can visit the GlueSQL GitHub repository's test suite folder, even if you're not familiar with Rust code: https://github.com/gluesql/gluesql/tree/main/test-suite/src

This folder contains tests for all the functionalities supported by GlueSQL, providing you with an extensive reference for syntax and usage.

Feel free to explore the other pages in this category to dive deeper into GlueSQL's SQL syntax and capabilities!

- - + + \ No newline at end of file diff --git a/docs/dev/sql-syntax/statements/data-definition/alter-table/index.html b/docs/dev/sql-syntax/statements/data-definition/alter-table/index.html index f438c1e3..2f3948aa 100644 --- a/docs/dev/sql-syntax/statements/data-definition/alter-table/index.html +++ b/docs/dev/sql-syntax/statements/data-definition/alter-table/index.html @@ -1,17 +1,17 @@ - + - + ALTER TABLE | GlueSQL - - - + + +

ALTER TABLE

The ALTER TABLE statement is an SQL command used to modify the structure of an existing table in a database. This operation is useful when you need to add, remove, or modify columns or constraints in a table. In this document, we'll explain the syntax and usage of the ALTER TABLE statement, including the RENAME, ADD COLUMN, and DROP COLUMN clauses.

Syntax

The basic syntax for the ALTER TABLE statement is as follows:

ALTER TABLE table_name action;
  • table_name: The name of the table you want to alter.
  • action: The action you want to perform on the table, such as renaming the table, adding a new column, or dropping an existing column.

RENAME

To rename a table or a column, use the following syntax:

ALTER TABLE table_name RENAME [TO new_table_name | COLUMN column_name TO new_column_name];

ADD COLUMN

To add a new column to a table, use the following syntax:

ALTER TABLE table_name ADD COLUMN column_name datatype [DEFAULT default_value] [NOT NULL] [UNIQUE];

DROP COLUMN

To drop an existing column from a table, use the following syntax:

ALTER TABLE table_name DROP COLUMN column_name;

Examples

  1. Renaming a table:
ALTER TABLE employees RENAME TO staff;

This command will rename the employees table to staff.

  1. Renaming a column:
ALTER TABLE employees RENAME COLUMN first_name TO given_name;

This command will rename the first_name column to given_name in the employees table.

  1. Adding a new column:
ALTER TABLE employees ADD COLUMN department TEXT;

This command will add a new department column with the TEXT datatype to the employees table.

  1. Adding a new column with a default value:
ALTER TABLE employees ADD COLUMN active BOOLEAN DEFAULT true;

This command will add a new active column with the BOOLEAN datatype and a default value of true to the employees table.

  1. Dropping a column:
ALTER TABLE employees DROP COLUMN department;

This command will remove the department column from the employees table.

Summary

The ALTER TABLE statement is an essential SQL command that allows you to modify the structure of an existing table in a database. It supports renaming tables and columns, adding new columns with optional default values and constraints, and dropping existing columns. By understanding the ALTER TABLE syntax, you can efficiently manage your database schema and make necessary changes to your tables as your data requirements evolve.

- - + + \ No newline at end of file diff --git a/docs/dev/sql-syntax/statements/data-definition/create-index/index.html b/docs/dev/sql-syntax/statements/data-definition/create-index/index.html index 053d07d7..d9e07469 100644 --- a/docs/dev/sql-syntax/statements/data-definition/create-index/index.html +++ b/docs/dev/sql-syntax/statements/data-definition/create-index/index.html @@ -1,17 +1,17 @@ - + - + CREATE INDEX | GlueSQL - - - + + +

CREATE INDEX

CREATE INDEX statement is used to create an index on one or more columns of a table. Indexes can improve query performance by allowing the database to quickly locate rows with specific column values. They can also be used with the ORDER BY clause to improve sorting performance. An index can be thought of as a data structure that maps the values of a specific column or columns to the corresponding rows in a table. This mapping allows the database to perform lookups and sorting operations more efficiently, as it does not have to scan the entire table.

Syntax

CREATE INDEX index_name ON table_name (column_name_expression);
  • index_name: The name of the index. It is recommended to use a descriptive name that indicates the purpose of the index, such as the column(s) it is based on.
  • table_name: The name of the table on which the index is to be created.
  • column_name_expression: The column name or expression on which the index is based. Only single column indexes are supported. If a column expression is used, it should be a simple arithmetic operation, such as addition or multiplication.

Example

Consider the following table called Students:

CREATE TABLE Students (
id INTEGER,
age INTEGER,
name TEXT
);

You can create an index on the id column with the following statement:

CREATE INDEX idx_id ON Students (id);

You can also create an index on a column expression, such as age * 2:

CREATE INDEX idx_age ON Students (age * 2);

Note that composite indexes (indexes on multiple columns) are not supported. These types of indexes can provide additional performance benefits in certain situations, but they also come with added complexity and increased storage requirements.

Using Index with ORDER BY

Indexes can improve the performance of the ORDER BY clause. When an index exists on the column specified in the ORDER BY clause, the database can use the index to sort the data more efficiently. This is because the index already provides a sorted view of the data, allowing the database to avoid the cost of sorting the entire table during query execution.

For example, if you have the following query:

SELECT * FROM Students ORDER BY id ASC;

The database can use the idx_id index created earlier to sort the data more quickly than without an index. Keep in mind that the performance gains from using an index with the ORDER BY clause will depend on the size of the table, the distribution of the data, and the specific database implementation.

- - + + \ No newline at end of file diff --git a/docs/dev/sql-syntax/statements/data-definition/create-table/index.html b/docs/dev/sql-syntax/statements/data-definition/create-table/index.html index 790080b0..74ae6e14 100644 --- a/docs/dev/sql-syntax/statements/data-definition/create-table/index.html +++ b/docs/dev/sql-syntax/statements/data-definition/create-table/index.html @@ -1,17 +1,17 @@ - + - + CREATE TABLE | GlueSQL - - - + + +

CREATE TABLE

The CREATE TABLE statement is a fundamental SQL command used to create a new table in a database. Tables are the primary structure in databases, as they hold the data organized in rows and columns. In this document, we'll explain the syntax and usage of the CREATE TABLE statement, including the IF NOT EXISTS clause.

Syntax

The basic syntax for the CREATE TABLE statement is as follows:

CREATE TABLE [IF NOT EXISTS] table_name (
column1 datatype constraint,
column2 datatype constraint,
column3 datatype constraint,
...
);
  • IF NOT EXISTS: This optional clause allows you to check if a table with the same name already exists in the database. If it exists, the command does nothing; otherwise, it creates a new table.
  • table_name: The name of the table you want to create.
  • column: Each column in the table is defined by its name, datatype, and optional constraints.
  • datatype: The type of data that the column will store (e.g., INTEGER, TEXT, DATE, etc.).
  • constraint: Optional constraints to enforce rules on the data stored in the column (e.g., PRIMARY KEY, NOT NULL, UNIQUE, etc.).

CREATE TABLE AS SELECT (CTAS)

You can also create a new table based on the result of a SELECT statement using the CTAS syntax:

CREATE TABLE table_name AS SELECT * FROM other_table;
  • table_name: The name of the new table to be created.
  • other_table: The existing table from which the data will be selected.

This command creates a new table with the same column structure as the source table and populates it with the data returned by the SELECT statement. The SELECT statement in this example uses the wildcard *, meaning that all columns from the source table will be included in the new table.

Example

Let's create a simple table called employees with the following columns:

  • id: A unique identifier for each employee (integer, primary key).
  • first_name: The employee's first name (text, not null).
  • last_name: The employee's last name (text, not null).
  • email: The employee's email address (text, unique).
  • hire_date: The date the employee was hired (date).

The SQL statement to create this table, using the IF NOT EXISTS clause, would look like this:

CREATE TABLE IF NOT EXISTS employees (
id INTEGER PRIMARY KEY,
first_name TEXT NOT NULL,
last_name TEXT NOT NULL,
email TEXT UNIQUE,
hire_date DATE
);

Example with CTAS

Assuming there is an existing table named employees_backup, you can create a new table called employees_copy with the same structure and data using CTAS:

CREATE TABLE employees_copy AS SELECT * FROM employees_backup;

Constraints

Constraints are rules that you can apply to columns in a table to control the data being stored. Some common constraints are:

  • PRIMARY KEY: Uniquely identifies each row in the table.
  • NOT NULL: Ensures the column cannot store a NULL value.
  • UNIQUE: Ensures all values in the column are unique.
  • DEFAULT: Sets a default value for the column when no value is specified.

Summary

The CREATE TABLE statement is an essential SQL command that allows you to create tables in a database. It requires a table name and one or more column definitions with their respective datatypes and optional constraints. The IF NOT EXISTS clause can be used to prevent creating duplicate tables. By understanding the CREATE TABLE syntax, you can define the structure of your tables and ensure the data stored in them is accurate and reliable.

- - + + \ No newline at end of file diff --git a/docs/dev/sql-syntax/statements/data-definition/drop-index/index.html b/docs/dev/sql-syntax/statements/data-definition/drop-index/index.html index c50ce58c..1b9cf37c 100644 --- a/docs/dev/sql-syntax/statements/data-definition/drop-index/index.html +++ b/docs/dev/sql-syntax/statements/data-definition/drop-index/index.html @@ -1,17 +1,17 @@ - + - + DROP INDEX | GlueSQL - - - + + +

DROP INDEX

DROP INDEX statement is used to remove an existing index from a table. This can be useful when an index is no longer needed, or if you want to free up storage space and reduce maintenance overhead associated with maintaining the index.

Syntax

DROP INDEX table_name.index_name;
  • table_name: The name of the table containing the index to be dropped.
  • index_name: The name of the index to be dropped.

Note that only one index can be dropped at a time using the DROP INDEX statement. If you want to drop multiple indexes, you need to execute multiple DROP INDEX statements.

Example

Consider the following table called Students with an index on the id column:

CREATE TABLE Students (
id INTEGER,
age INTEGER,
name TEXT
);

CREATE INDEX idx_id ON Students (id);

You can drop the idx_id index with the following statement:

DROP INDEX Students.idx_id;

If you attempt to drop multiple indexes in a single statement, an error will be raised:

DROP INDEX Students.idx_id, Students.idx_age;

This will result in an error, as only one index can be dropped at a time. To drop both indexes, execute two separate DROP INDEX statements:

DROP INDEX Students.idx_id;
DROP INDEX Students.idx_age;
- - + + \ No newline at end of file diff --git a/docs/dev/sql-syntax/statements/data-definition/drop-table/index.html b/docs/dev/sql-syntax/statements/data-definition/drop-table/index.html index 4ae0353c..f6ce8d3a 100644 --- a/docs/dev/sql-syntax/statements/data-definition/drop-table/index.html +++ b/docs/dev/sql-syntax/statements/data-definition/drop-table/index.html @@ -1,17 +1,17 @@ - + - + DROP TABLE | GlueSQL - - - + + +

DROP TABLE

The DROP TABLE statement is an SQL command used to remove one or more tables from a database. This operation is useful when you no longer need a table or want to clear out old data structures. In this document, we'll explain the syntax and usage of the DROP TABLE statement, including the IF EXISTS clause and dropping multiple tables at once.

Syntax

The basic syntax for the DROP TABLE statement is as follows:

DROP TABLE [IF EXISTS] table_name [, table_name2, ...];
  • IF EXISTS: This optional clause allows you to check if a table exists in the database before attempting to drop it. If the table does not exist, the command does nothing; otherwise, it drops the specified table.
  • table_name: The name of the table you want to drop. You can also drop multiple tables by separating their names with commas.

Examples

  1. Dropping a single table:
DROP TABLE employees;

This command will drop the employees table from the database.

  1. Dropping a table using the IF EXISTS clause:
DROP TABLE IF EXISTS employees;

This command will drop the employees table if it exists in the database. If the table does not exist, the command does nothing.

  1. Dropping multiple tables at once:
DROP TABLE employees, table_name;

This command will drop both the employees and table_name tables from the database.

Warning

When using the DROP TABLE statement, be cautious, as this operation will permanently remove the table and all its data from the database. Always make sure to backup your data before performing this operation.

Summary

The DROP TABLE statement is an essential SQL command that allows you to remove tables from a database. It supports an optional IF EXISTS clause to prevent errors if a table does not exist, and you can drop multiple tables at once by separating their names with commas. By understanding the DROP TABLE syntax, you can efficiently manage your database schema and remove unnecessary tables when needed.

- - + + \ No newline at end of file diff --git a/docs/dev/sql-syntax/statements/data-manipulation/delete/index.html b/docs/dev/sql-syntax/statements/data-manipulation/delete/index.html index c5850af4..4bf2eeff 100644 --- a/docs/dev/sql-syntax/statements/data-manipulation/delete/index.html +++ b/docs/dev/sql-syntax/statements/data-manipulation/delete/index.html @@ -1,17 +1,17 @@ - + - + DELETE | GlueSQL - - - + + +

DELETE

The DELETE statement is used to remove records from a table. You can delete a single row, multiple rows, or all rows at once based on specific conditions.

Basic DELETE Syntax

To delete records from a table, use the following syntax:

DELETE FROM table_name
WHERE condition;

If you want to delete all records from a table, you can omit the WHERE clause:

DELETE FROM table_name;

Examples

Consider the following Foo table:

CREATE TABLE Foo (
id INTEGER PRIMARY KEY,
score INTEGER,
flag BOOLEAN
);

With the following records:

INSERT INTO Foo VALUES
(1, 100, TRUE),
(2, 300, FALSE),
(3, 700, TRUE);

Deleting Records with a WHERE Clause

To delete records that meet a specific condition, use the WHERE clause:

DELETE FROM Foo WHERE flag = FALSE;

After executing the above query, the remaining records in the Foo table will be:

id | score | flag
---+-------+------
1 | 100 | true
3 | 700 | true

Deleting All Records

To delete all records from a table, omit the WHERE clause:

DELETE FROM Foo;

After executing the above query, the Foo table will be empty:

id | score | flag
(no rows)
- - + + \ No newline at end of file diff --git a/docs/dev/sql-syntax/statements/data-manipulation/insert/index.html b/docs/dev/sql-syntax/statements/data-manipulation/insert/index.html index e7e881dc..0a924951 100644 --- a/docs/dev/sql-syntax/statements/data-manipulation/insert/index.html +++ b/docs/dev/sql-syntax/statements/data-manipulation/insert/index.html @@ -1,17 +1,17 @@ - + - + INSERT | GlueSQL - - - + + +

INSERT

The INSERT statement is used to insert new records into a table. You can insert a single row or multiple rows at once, and you can also use the NULL, NOT NULL, and DEFAULT constraints to define how values are inserted.

Basic INSERT Syntax

INSERT INTO table_name (column1, column2, column3, ...)
VALUES
(value1, value2, value3, ...),
(value4, value5, value6, ...),
...
;

Handling NULL, NOT NULL, and DEFAULT Constraints

When inserting data into a table, the database handles NULL, NOT NULL, and DEFAULT constraints as follows:

  • NULL: If a column is defined with the NULL constraint (or no constraint is provided), you can insert a NULL value or omit the column in the INSERT statement. The database will store a NULL value for the omitted column.

  • NOT NULL: If a column is defined with the NOT NULL constraint, you must provide a value for the column in the INSERT statement. If you try to insert a NULL value or omit the column, the database will return an error.

  • DEFAULT: If a column is defined with a DEFAULT value, you can omit the column in the INSERT statement. The database will automatically use the default value for the omitted column.

Examples

Consider the following Test table:

CREATE TABLE Test (
id INTEGER DEFAULT 1,
num INTEGER NULL,
name TEXT NOT NULL,
);

Basic INSERT

To insert a single row:

INSERT INTO Test (id, num, name) VALUES (1, 2, 'Hi boo');

Inserting Multiple Rows

To insert multiple rows at once:

INSERT INTO Test (id, num, name)
VALUES
(3, 9, 'Kitty!'),
(2, 7, 'Monsters');

Inserting with Omitted Columns

If you want to insert a row without specifying a value for a column with a DEFAULT constraint, you can simply omit the column:

INSERT INTO Test (num, name) VALUES (28, 'Wazowski');

For columns with NULL constraint, you can either omit the column or explicitly insert a NULL value:

INSERT INTO Test (name) VALUES ('The end');

Handling NOT NULL Constraint

If you try to insert a row without specifying a value for a column with the NOT NULL constraint, the database will return an error:

INSERT INTO Test (id, num) VALUES (1, 10);
-- Error: LackOfRequiredColumn("name")
- - + + \ No newline at end of file diff --git a/docs/dev/sql-syntax/statements/data-manipulation/update/index.html b/docs/dev/sql-syntax/statements/data-manipulation/update/index.html index 6e88308a..1caa5eab 100644 --- a/docs/dev/sql-syntax/statements/data-manipulation/update/index.html +++ b/docs/dev/sql-syntax/statements/data-manipulation/update/index.html @@ -1,17 +1,17 @@ - + - + UPDATE | GlueSQL - - - + + +

UPDATE

The UPDATE statement is used to modify existing records in a table. You can update one or more columns with new values, or even use subqueries to update values based on other tables.

Basic UPDATE Syntax

UPDATE table_name
SET column1 = value1, column2 = value2, ...
WHERE condition;

Examples

Updating a Single Column

Consider the following TableA:

idnumnum2name
124Hello
195World
347Great
4710Job

To update the id column for all rows in TableA, you can use the following query:

UPDATE TableA SET id = 2;

The resulting TableA would look like this:

idnumnum2name
224Hello
295World
247Great
2710Job

Updating with a Condition

If you want to update only specific rows that meet a certain condition, you can use the WHERE clause. For example, to update the id column only for the row with num = 9:

UPDATE TableA SET id = 4 WHERE num = 9;

Updating with a Subquery

You can also use a subquery in the UPDATE statement to update a column based on other table's values. For example, to update the num2 column in TableA with the rank column value from TableB where the num column values match, and the num = 7:

UPDATE TableA SET num2 = (SELECT rank FROM TableB WHERE num = TableA.num) WHERE num = 7;

Updating Based on the Result of Another Query

You can update a column based on the result of another query. For example, to update the num2 column in TableA with the rank column value from TableB where the num column values match, and the num is the minimum num in TableA:

UPDATE TableA SET num2 = (SELECT rank FROM TableB WHERE num = TableA.num) WHERE num = (SELECT MIN(num) FROM TableA);

Not Supported Features

  • Using JOIN in an UPDATE statement is not supported.
  • Updating a table using compound identifiers (e.g., ErrTestTable.id = 1) is not supported.
  • Updating a non-existent table will result in a TableNotFound error.
  • Updating a non-existent column will result in a ColumnNotFound error.
- - + + \ No newline at end of file diff --git a/docs/dev/sql-syntax/statements/metadata/data-dictionary/index.html b/docs/dev/sql-syntax/statements/metadata/data-dictionary/index.html index 60b6e08f..608df568 100644 --- a/docs/dev/sql-syntax/statements/metadata/data-dictionary/index.html +++ b/docs/dev/sql-syntax/statements/metadata/data-dictionary/index.html @@ -1,17 +1,17 @@ - + - + Data Dictionary | GlueSQL - - - + + +

Data Dictionary

In GlueSQL, there are predefined tables, also known as Data Dictionary tables, which store metadata about the database objects like tables, columns, and indexes. These tables can be queried like any other table in the database, and they provide useful information about the database schema.

The Data Dictionary tables in GlueSQL include:

  1. GLUE_TABLES
  2. GLUE_TABLE_COLUMNS
  3. GLUE_INDEXES

Please note that the columns provided in these tables are the default columns. Storage implementations may provide additional information in these tables.

GLUE_TABLES

The GLUE_TABLES table contains a list of all tables in the database.

Columns:

  • TABLE_NAME: The name of the table.

GLUE_TABLE_COLUMNS

The GLUE_TABLE_COLUMNS table contains information about the columns in each table.

Columns:

  • TABLE_NAME: The name of the table that the column belongs to.
  • COLUMN_NAME: The name of the column.
  • COLUMN_ID: The column's unique identifier.

GLUE_INDEXES

The GLUE_INDEXES table contains information about the indexes defined in the database.

Columns:

  • TABLE_NAME: The name of the table that the index belongs to.
  • INDEX_NAME: The name of the index.
  • ORDER: The order in which the index is sorted (e.g., "ASC", "DESC", or "BOTH").
  • EXPRESSION: The expression used for the indexed column (e.g., "id" or "id + 2").
  • UNIQUENESS: A boolean value indicating whether the index enforces uniqueness.

Examples

To query the GLUE_TABLES table and get a list of all tables in the database:

SELECT * FROM GLUE_TABLES;

To query the GLUE_TABLE_COLUMNS table and get information about the columns in each table:

SELECT * FROM GLUE_TABLE_COLUMNS;

To query the GLUE_INDEXES table and get information about the indexes defined in the database:

SELECT * FROM GLUE_INDEXES;
- - + + \ No newline at end of file diff --git a/docs/dev/sql-syntax/statements/metadata/show-tables/index.html b/docs/dev/sql-syntax/statements/metadata/show-tables/index.html index f8cf76c0..8bddb7be 100644 --- a/docs/dev/sql-syntax/statements/metadata/show-tables/index.html +++ b/docs/dev/sql-syntax/statements/metadata/show-tables/index.html @@ -1,17 +1,17 @@ - + - + SHOW TABLES | GlueSQL - - - + + +

SHOW TABLES

The SHOW TABLES statement in GlueSQL is used to display a list of tables available in the database. This statement is useful when you want to inspect the current structure of your database or when you want to manage multiple tables.

Syntax

SHOW TABLES;

Example

Consider the following example where we create a few tables and then use the SHOW TABLES statement to list them:

CREATE TABLE Foo (id INTEGER, name TEXT NULL, type TEXT NULL);
CREATE TABLE Zoo (id INTEGER);
CREATE TABLE Bar (id INTEGER, name TEXT NULL);

SHOW TABLES;

The output of the SHOW TABLES statement will be:

Bar
Foo
Zoo

The tables are listed in alphabetical order.

- - + + \ No newline at end of file diff --git a/docs/dev/sql-syntax/statements/querying/aggregation/index.html b/docs/dev/sql-syntax/statements/querying/aggregation/index.html index 577a0989..95f09f1e 100644 --- a/docs/dev/sql-syntax/statements/querying/aggregation/index.html +++ b/docs/dev/sql-syntax/statements/querying/aggregation/index.html @@ -1,17 +1,17 @@ - + - + Aggregation | GlueSQL - - - + + +

Aggregation

GlueSQL supports several aggregate functions to perform calculations on a set of values. Below is a list of supported aggregate functions along with a brief explanation of each:

  • COUNT: Counts the number of non-NULL values in the specified column.
  • AVG: Calculates the average of non-NULL values in the specified column.
  • SUM: Calculates the sum of non-NULL values in the specified column.
  • MAX: Returns the maximum value in the specified column.
  • MIN: Returns the minimum value in the specified column.
  • STDEV: Calculates the population standard deviation of non-NULL values in the specified column.
  • VARIANCE: Calculates the population variance of non-NULL values in the specified column.

In addition to the aggregate functions, you can use GROUP BY and HAVING clauses to group and filter the results based on specific conditions.

GROUP BY

The GROUP BY clause is used to group rows with the same values in specified columns into a set of summary rows. It is often used with aggregate functions to perform calculations on each group of rows.

Here's an example that groups the items by city and calculates the sum of quantity and the count of items for each city:

SELECT SUM(quantity), COUNT(*), city FROM Item GROUP BY city;

HAVING

The HAVING clause is used to filter the results of a GROUP BY query based on a condition that applies to the summary rows. It is similar to the WHERE clause but operates on the results of the grouping.

Here's an example that groups the items by city and calculates the sum of quantity and the count of items for each city, but only includes cities with a count greater than 1:

SELECT SUM(quantity), COUNT(*), city FROM Item GROUP BY city HAVING COUNT(*) > 1;

In the examples provided, you can see the usage of GROUP BY and HAVING clauses in combination with aggregate functions to retrieve data from the Item table.

- - + + \ No newline at end of file diff --git a/docs/dev/sql-syntax/statements/querying/join/index.html b/docs/dev/sql-syntax/statements/querying/join/index.html index c1871e86..ea0a4007 100644 --- a/docs/dev/sql-syntax/statements/querying/join/index.html +++ b/docs/dev/sql-syntax/statements/querying/join/index.html @@ -1,17 +1,17 @@ - + - + JOIN | GlueSQL - - - + + +

JOIN

GlueSQL supports two types of JOIN operations:

  • (INNER) JOIN
  • LEFT (OUTER) JOIN

Please note that FULL OUTER JOIN and RIGHT JOIN are currently not supported.

(INNER) JOIN

An INNER JOIN combines rows from two tables based on a specified condition. Rows that do not satisfy the condition are excluded from the result.

Here's an example using the provided test code:

SELECT * FROM Item INNER JOIN Player ON Player.id = Item.player_id WHERE Player.id = 1;

This query retrieves all rows from the Item and Player tables where the id in the Player table matches the player_id in the Item table, and the Player.id is equal to 1.

LEFT (OUTER) JOIN

A LEFT JOIN (also known as LEFT OUTER JOIN) combines rows from two tables based on a specified condition. For each row in the left table that does not have a matching row in the right table, the result will contain NULL values.

Here's an example using the provided test code:

SELECT * FROM Item LEFT JOIN Player ON Player.id = Item.player_id WHERE quantity = 1;

This query retrieves all rows from the Item table and any matching rows from the Player table where the id in the Player table matches the player_id in the Item table. If there's no match, NULL values are returned for the Player table columns. The result is then filtered by the quantity column in the Item table with a value of 1.

Remember to replace the table names, column names, and data types as needed for your specific use case.

- - + + \ No newline at end of file diff --git a/docs/dev/sql-syntax/statements/querying/limit/index.html b/docs/dev/sql-syntax/statements/querying/limit/index.html index d95430dd..8ed92381 100644 --- a/docs/dev/sql-syntax/statements/querying/limit/index.html +++ b/docs/dev/sql-syntax/statements/querying/limit/index.html @@ -1,17 +1,17 @@ - + - + LIMIT & OFFSET | GlueSQL - - - + + +

LIMIT & OFFSET

LIMIT and OFFSET are SQL clauses that allow you to control the number of rows returned by a SELECT statement. They are particularly useful when you need to paginate or retrieve a specific portion of the result set.

LIMIT

The LIMIT clause restricts the number of rows returned by a query. The syntax for using LIMIT is:

SELECT columns FROM table_name
LIMIT number_of_rows;

OFFSET

The OFFSET clause is used in combination with LIMIT to skip a specific number of rows before starting to return the rows. The syntax for using OFFSET is:

SELECT columns FROM table_name
LIMIT number_of_rows
OFFSET number_of_rows_to_skip;

You can also use OFFSET without LIMIT:

SELECT columns FROM table_name
OFFSET number_of_rows_to_skip;

Examples

Consider the following Test table:

CREATE TABLE Test (
id INTEGER
);

With the following records:

INSERT INTO Test VALUES (1), (2), (3), (4), (5), (6), (7), (8);

Using LIMIT

Retrieve the first 3 rows from the Test table:

SELECT * FROM Test LIMIT 3;

Result:

id
---
1
2
3

Using LIMIT and OFFSET

Retrieve the next 4 rows after the first 3 rows from the Test table:

SELECT * FROM Test LIMIT 4 OFFSET 3;

Result:

id
---
4
5
6
7

Using OFFSET without LIMIT

Retrieve all rows after the first 2 rows from the Test table:

SELECT * FROM Test OFFSET 2;

Result:

id
---
3
4
5
6
7
8
- - + + \ No newline at end of file diff --git a/docs/dev/sql-syntax/statements/querying/schemaless/index.html b/docs/dev/sql-syntax/statements/querying/schemaless/index.html index cdb560b8..7aa11284 100644 --- a/docs/dev/sql-syntax/statements/querying/schemaless/index.html +++ b/docs/dev/sql-syntax/statements/querying/schemaless/index.html @@ -1,17 +1,17 @@ - + - + Schemaless Data | GlueSQL - - - + + +

Querying Schemaless Data

GlueSQL is an SQL database that provides a unique feature: it allows you to work with schemaless data, similar to NoSQL databases. Please note this point in the documentation.

Creating a Schemaless Table

To create a schemaless table, you don't need to specify columns when creating the table. For example:

CREATE TABLE Sample;

This creates a schemaless table. You can now insert data freely into each row, like a NoSQL database. Nested data is also supported.

Example SQL Queries

Here are some example SQL queries that demonstrate how to use GlueSQL with schemaless data:

Creating Tables

CREATE TABLE Player;
CREATE TABLE Item;

Inserting Data

INSERT INTO Player VALUES ('{"id": 1001, "name": "Beam", "flag": 1}'), ('{"id": 1002, "name": "Seo"}');
INSERT INTO Item VALUES ('{"id": 100, "name": "Test 001", "dex": 324, "rare": false, "obj": {"cost": 3000}}'), ('{"id": 200}');

Selecting Data

SELECT name, dex, rare FROM Item WHERE id = 100;
SELECT name, dex, rare FROM Item;
SELECT * FROM Item;

Updating Data

DELETE FROM Item WHERE id > 100;
UPDATE Item SET id = id + 1, rare = NOT rare;
UPDATE Item SET new_field = 'Hello';

Selecting with Aliases and Joins

SELECT
Player.id AS player_id,
Player.name AS player_name,
Item.obj['cost'] AS item_cost
FROM Item
JOIN Player
WHERE flag IS NOT NULL;

Notable Exception Cases

Here are some example SQL queries that will raise errors, along with explanations of the issues:

Inserting Invalid Data

  • Inserting multiple values for a schemaless row:

    INSERT INTO Item VALUES ('{"a": 10}', '{"b": true}');

    Schemaless rows accept only single values.

  • Inserting data from a SELECT statement:

    INSERT INTO Item SELECT id, name FROM Item LIMIT 1;

    Schemaless rows cannot be inserted using a SELECT statement.

  • Inserting a JSON array:

    INSERT INTO Item VALUES ('[1, 2, 3]');

    Only JSON objects are allowed for schemaless rows.

  • Inserting a boolean value:

    INSERT INTO Item VALUES (true);

    Text literals are required for schemaless rows.

  • Inserting an expression result:

    INSERT INTO Item VALUES (CAST(1 AS INTEGER) + 4);

    Map or string values are required for schemaless rows.

  • Inserting data from a SELECT statement with LIMIT:

    INSERT INTO Item SELECT id FROM Item LIMIT 1;

    Map type values are required for schemaless rows.

Selecting Invalid Data

  • Using IN with a schemaless subquery:

    SELECT id FROM Item WHERE id IN (SELECT * FROM Item);

    Schemaless projections are not allowed for IN subqueries.

  • Using a comparison with a schemaless subquery:

    SELECT id FROM Item WHERE id = (SELECT * FROM Item LIMIT 1);

    Schemaless projections are not allowed for subqueries.

- - + + \ No newline at end of file diff --git a/docs/dev/sql-syntax/statements/querying/where/index.html b/docs/dev/sql-syntax/statements/querying/where/index.html index 3454e297..2c3b0dea 100644 --- a/docs/dev/sql-syntax/statements/querying/where/index.html +++ b/docs/dev/sql-syntax/statements/querying/where/index.html @@ -1,17 +1,17 @@ - + - + WHERE | GlueSQL - - - + + +

WHERE

In GlueSQL, the WHERE clause is used to filter the results of a SELECT query based on specific conditions. The WHERE clause can be used with various operators and functions to create complex filtering conditions.

Here are some examples based on the provided Rust test code and SQL queries:

Comparison Operators

You can use comparison operators such as =, <>, <, >, <=, and >= to compare values in the WHERE clause.

SELECT name FROM Boss WHERE id <= 2;
SELECT name FROM Boss WHERE +id <= 2;

BETWEEN Operator

The BETWEEN operator allows you to filter results within a specific range.

SELECT id, name FROM Boss WHERE id BETWEEN 2 AND 4;
SELECT id, name FROM Boss WHERE name BETWEEN 'Doll' AND 'Gehrman';

To exclude the specified range, use the NOT BETWEEN operator.

SELECT name FROM Boss WHERE name NOT BETWEEN 'Doll' AND 'Gehrman';

EXISTS and NOT EXISTS

EXISTS and NOT EXISTS operators are used to filter results based on the existence of records in a subquery.

SELECT name
FROM Boss
WHERE EXISTS (
SELECT * FROM Hunter WHERE Hunter.name = Boss.name
);

SELECT name
FROM Boss
WHERE NOT EXISTS (
SELECT * FROM Hunter WHERE Hunter.name = Boss.name
);

IN Operator

The IN operator allows you to filter results based on a list of values or a subquery.

SELECT * FROM Player WHERE id IN (SELECT user_id FROM Request WHERE quantity IN (6, 7, 8, 9));

LIKE and ILIKE Operators

LIKE and ILIKE operators are used to filter results based on pattern matching. Use the % wildcard to match any number of characters and the _ wildcard to match a single character.

SELECT name FROM Item WHERE name LIKE '_a%';
SELECT name FROM Item WHERE name LIKE '%r%';

ILIKE is a case-insensitive version of LIKE.

SELECT name FROM Item WHERE name ILIKE '%%';
SELECT name FROM Item WHERE name NOT ILIKE '%A%';
- - + + \ No newline at end of file diff --git a/docs/dev/sql-syntax/statements/transaction/index.html b/docs/dev/sql-syntax/statements/transaction/index.html index 48daf19f..bb9a761e 100644 --- a/docs/dev/sql-syntax/statements/transaction/index.html +++ b/docs/dev/sql-syntax/statements/transaction/index.html @@ -1,17 +1,17 @@ - + - + Transaction | GlueSQL - - - + + +

Transaction

Transactions in SQL are a series of queries that are executed as a single unit of work. In GlueSQL, transactions help to ensure the consistency and integrity of the database. They follow the ACID properties: Atomicity, Consistency, Isolation, and Durability.

Note: In GlueSQL, transactions are an optional feature. Support for transactions depends on the storage engine being used. Currently, only SledStorage supports transactions, but there are plans to add support for other storage engines in the future. Transaction isolation levels may also vary depending on the storage engine. For example, the current transaction isolation level for SledStorage is SNAPSHOT ISOLATION.

BEGIN TRANSACTION

To start a new transaction, use the BEGIN keyword:

BEGIN;

COMMIT TRANSACTION

To permanently save the changes made during the transaction, use the COMMIT keyword:

COMMIT;

ROLLBACK TRANSACTION

To undo the changes made during the transaction and revert the database to its state before the transaction started, use the ROLLBACK keyword:

ROLLBACK;

Example

Consider the following table TxTest with columns id (INTEGER) and name (TEXT):

CREATE TABLE TxTest (
id INTEGER,
name TEXT
);

Insert sample data into the table:

INSERT INTO TxTest VALUES
(1, 'Friday'),
(2, 'Phone');

Inserting Data

Start a new transaction and insert a new row:

BEGIN;
INSERT INTO TxTest VALUES (3, 'New one');

Rollback the transaction to undo the insertion:

ROLLBACK;

Now, start a new transaction and insert a new row with different data:

BEGIN;
INSERT INTO TxTest VALUES (3, 'Vienna');
COMMIT;

Deleting Data

Start a new transaction and delete a row:

BEGIN;
DELETE FROM TxTest WHERE id = 3;
ROLLBACK;

The deletion will be undone due to the rollback. To permanently delete the row, commit the transaction:

BEGIN;
DELETE FROM TxTest WHERE id = 3;
COMMIT;

Updating Data

Start a new transaction and update a row:

BEGIN;
UPDATE TxTest SET name = 'Sunday' WHERE id = 1;
ROLLBACK;

The update will be undone due to the rollback. To permanently update the row, commit the transaction:

BEGIN;
UPDATE TxTest SET name = 'Sunday' WHERE id = 1;
COMMIT;
- - + + \ No newline at end of file diff --git a/docs/dev/storages/developing-custom-storages/intro/index.html b/docs/dev/storages/developing-custom-storages/intro/index.html index 70ce9647..61e56c79 100644 --- a/docs/dev/storages/developing-custom-storages/intro/index.html +++ b/docs/dev/storages/developing-custom-storages/intro/index.html @@ -1,17 +1,17 @@ - + - + Introduction | GlueSQL - - - + + +

Introduction

With GlueSQL, you can adapt SQL and the AST Builder to a wide variety of environments. This includes file systems, key-value databases, complex NoSQL databases, and even remote APIs. As long as a system supports reading, it can support SELECT queries. If it supports both reading and writing, it can support most SQL operations, including UPDATE and DELETE.

To implement GlueSQL, you only need to know two things:

  1. Understanding Store traits
  2. Using the Test Suite

These topics are covered in more detail in their respective pages, but here we will provide a brief overview.

Understanding Store Traits

GlueSQL is available in both Rust and JavaScript environments, with plans to expand its support to other languages. Since the GlueSQL project itself is written in Rust, using Rust is essential for developing custom storages. To create a custom storage, you need to implement the Store traits provided by GlueSQL. There are currently 9 traits:

  • Store - A trait for read operations to support SELECT queries.
  • StoreMut - A trait for modifying data, such as INSERT, UPDATE, and DELETE.
  • AlterTable - A trait for supporting schema changes.
  • Transaction - A trait for supporting transactions.
  • CustomFunction - A trait for supporting user-level custom functions.
  • CustomFunctionMut - A trait for creating or deleting user-level custom functions.
  • Index - A trait for supporting non-clustered indexes. This trait allows you to process pre-registered indexes.
  • IndexMut - A trait for creating or deleting non-clustered indexes.
  • Metadata - A trait for querying metadata.

To develop a custom storage, you can implement these 9 traits. Although this may seem like a lot of work, don't worry. All traits except for Store and StoreMut are optional. In other words, you don't have to implement them. If you don't want to support the AlterTable trait, simply don't implement it. It's that simple.

Furthermore, if you only want to support SELECT queries, you don't need to implement StoreMut. By implementing only the Store trait, you can create a custom storage that supports SQL SELECT queries.

Using the Test Suite

The minimum requirement for developing a custom storage is implementing the Store traits. However, you may want to verify that your implementation is correct. That's where the Test Suite comes in.

GlueSQL provides a test case library to make it easy to validate custom storage development. Developers can implement the desired Store traits and use the Test Suite to verify that their implementation is correct. The line coverage of GlueSQL's core project is almost 99%, which means that passing the Test Suite alone can complete most of the feature verification. All you need to do is ensure your custom storage passes the Test Suite and write additional tests for any specialized features specific to your storage.

- - + + \ No newline at end of file diff --git a/docs/dev/storages/developing-custom-storages/store-traits/alter-table/index.html b/docs/dev/storages/developing-custom-storages/store-traits/alter-table/index.html index 947e6c2f..6717b31e 100644 --- a/docs/dev/storages/developing-custom-storages/store-traits/alter-table/index.html +++ b/docs/dev/storages/developing-custom-storages/store-traits/alter-table/index.html @@ -1,17 +1,17 @@ - + - + AlterTable | GlueSQL - - - + + +

AlterTable

The AlterTable trait corresponds to the SQL ALTER TABLE statement and is used for modifying existing schemas. It is not necessary to implement the AlterTable trait. If you are dealing with data that is difficult to modify schema-wise or schemaless data, there is no need to implement the AlterTable trait. It is an optional trait that custom storage developers can choose to implement.

Similar to the Store & StoreMut combination, if you implement the AlterTable trait, you can use additional tests in the Test Suite to verify your implementation. There are currently four types of methods supported by AlterTable:

  1. rename_schema: Corresponds to the SQL statement ALTER TABLE {table-name} RENAME TO {other-name};. This method renames a schema.

  2. rename_column: Corresponds to the SQL statement ALTER TABLE {table-name} RENAME COLUMN {col1} TO {col2};. This method renames a column within a table.

  3. add_column: Corresponds to the SQL statement ALTER TABLE {table-name} ADD COLUMN {col} {data-type} {constraints}. This method adds a new column to a table with specified data type and constraints.

  4. drop_column: Corresponds to the SQL statement ALTER TABLE {table-name} DROP COLUMN {col}. This method removes a column from a table.

#[async_trait(?Send)]
pub trait AlterTable {
async fn rename_schema(&mut self, _table_name: &str, _new_table_name: &str) -> Result<()>;

async fn rename_column(&mut self,
_table_name: &str,
_old_column_name: &str,
_new_column_name: &str,
) -> Result<()>;

async fn add_column(&mut self, _table_name: &str, _column_def: &ColumnDef) -> Result<()>;

async fn drop_column(
&mut self,
_table_name: &str,
_column_name: &str,
_if_exists: bool,
) -> Result<()>;
}
- - + + \ No newline at end of file diff --git a/docs/dev/storages/developing-custom-storages/store-traits/custom-function-mut/index.html b/docs/dev/storages/developing-custom-storages/store-traits/custom-function-mut/index.html index 1bb60c93..6f7d96ab 100644 --- a/docs/dev/storages/developing-custom-storages/store-traits/custom-function-mut/index.html +++ b/docs/dev/storages/developing-custom-storages/store-traits/custom-function-mut/index.html @@ -1,17 +1,17 @@ - + - + CustomFunctionMut | GlueSQL - - - + + +

CustomFunctionMut

By implementing both the CustomFunction and CustomFunctionMut traits, users can create, use, and delete user-level custom functions. Although GlueSQL plans to continuously add various functions, users may still find them insufficient. In such cases, users can create their own user-level custom functions to supplement the built-in functions. Additionally, if there are repetitive business logic codes, they can be stored as custom functions.

Example:

CREATE FUNCTION ADD_ONE (n INT, x INT DEFAULT 1) RETURN n + x;

SELECT ADD_ONE(10) AS test;

DROP FUNCTION ADD_ONE;

There are two methods available:

  1. insert_function: This method inserts a new custom function into the storage system.

  2. delete_function: This method deletes a custom function from the storage system using the provided function name.

#[async_trait(?Send)]
pub trait CustomFunctionMut {
async fn insert_function(&mut self, _func: StructCustomFunction) -> Result<()>;

async fn delete_function(&mut self, _func_name: &str) -> Result<()>;
}
- - + + \ No newline at end of file diff --git a/docs/dev/storages/developing-custom-storages/store-traits/custom-function/index.html b/docs/dev/storages/developing-custom-storages/store-traits/custom-function/index.html index c5ee7e55..4ccbafba 100644 --- a/docs/dev/storages/developing-custom-storages/store-traits/custom-function/index.html +++ b/docs/dev/storages/developing-custom-storages/store-traits/custom-function/index.html @@ -1,17 +1,17 @@ - + - + CustomFunction | GlueSQL - - - + + +

CustomFunction

The CustomFunction trait is an optional trait for supporting user-level custom functions. Through the CustomFunction trait, you can retrieve custom functions stored in the storage system. You can choose to implement the CustomFunction trait alone or together with the CustomFunctionMut trait.

In some cases, you might want to provide storage-specific functions pre-built and separately available for each storage system. In such cases, you can implement the CustomFunction trait and create additional functions stored in advance when using it. To achieve this, the CustomFunction and CustomFunctionMut traits are provided separately for implementation.

There are two methods available:

  1. fetch_function: This method retrieves a custom function from the storage system using the provided function name.

  2. fetch_all_functions: This method retrieves all custom functions stored in the storage system.

#[async_trait(?Send)]
pub trait CustomFunction {
async fn fetch_function(&self, _func_name: &str) -> Result<Option<&StructCustomFunction>>;

async fn fetch_all_functions(&self) -> Result<Vec<&StructCustomFunction>>;
}
- - + + \ No newline at end of file diff --git a/docs/dev/storages/developing-custom-storages/store-traits/index-mut/index.html b/docs/dev/storages/developing-custom-storages/store-traits/index-mut/index.html index 6dbd0305..a53eab84 100644 --- a/docs/dev/storages/developing-custom-storages/store-traits/index-mut/index.html +++ b/docs/dev/storages/developing-custom-storages/store-traits/index-mut/index.html @@ -1,17 +1,17 @@ - + - + IndexMut | GlueSQL - - - + + +

IndexMut

The IndexMut trait, when implemented along with the Index trait, allows custom storage developers to provide users with the ability to create, use, and delete non-clustered indexes. Implementing the IndexMut trait enhances the storage system's capabilities by providing support for dynamic index management.

Non-clustered indexes can improve query performance by reducing the amount of data that needs to be read during search operations. Users can create multiple non-clustered indexes tailored to their specific use cases, providing a more efficient and optimized experience when working with large datasets.

The IndexMut trait requires the implementation of two methods:

  1. create_index: This method creates a new non-clustered index on the specified column with a given index name for the provided table. The index can be used to speed up queries involving the indexed column.

  2. drop_index: This method removes a non-clustered index by the specified index name from the provided table. This can be useful when the index is no longer needed or needs to be updated to reflect changes in the data.

#[async_trait(?Send)]
pub trait IndexMut {
async fn create_index(
&mut self,
_table_name: &str,
_index_name: &str,
_column: &OrderByExpr,
) -> Result<()>;

async fn drop_index(&mut self, _table_name: &str, _index_name: &str) -> Result<()>;
}

By implementing both the Index and IndexMut traits, custom storage developers can provide users with the ability to manage non-clustered indexes according to their specific needs, improving overall query performance and providing a more tailored experience.

- - + + \ No newline at end of file diff --git a/docs/dev/storages/developing-custom-storages/store-traits/index-trait/index.html b/docs/dev/storages/developing-custom-storages/store-traits/index-trait/index.html index b3c9edd3..f2ab2421 100644 --- a/docs/dev/storages/developing-custom-storages/store-traits/index-trait/index.html +++ b/docs/dev/storages/developing-custom-storages/store-traits/index-trait/index.html @@ -1,17 +1,17 @@ - + - + Index | GlueSQL - - - + + +

Index

The Index trait is designed to support non-clustered indexes. If you only need to support pre-built non-clustered indexes, implementing the Index trait without the IndexMut trait is sufficient. Note that clustered indexes (PRIMARY KEY) are automatically supported by the Store & StoreMut implementations. The Index trait is specifically for non-clustered index support.

Currently, GlueSQL's query planner only supports a logical planner, so the performance of finding non-clustered indexes is not optimal yet, but it is being improved. If you want to use non-clustered indexes more precisely, using the AST Builder to directly specify the index you want to use can be a good approach.

A brief explanation of non-clustered and clustered indexes:

  • Non-clustered index: A non-clustered index is an index that doesn't affect the physical ordering of the data rows in the table. Instead, it maintains a separate data structure that contains a reference to the actual data rows, allowing for faster search operations without rearranging the data itself.

  • Clustered index: A clustered index determines the physical order of the data in the table. In other words, the data rows are stored on disk in the same order as the index. There can be only one clustered index per table, which is usually defined by the PRIMARY KEY constraint.

There is one method to implement for the Index trait:

  1. scan_indexed_data: This method retrieves indexed data from the storage system using the provided table name, index name, sorting order, and comparison value.
#[async_trait(?Send)]
pub trait Index {
async fn scan_indexed_data(
&self,
_table_name: &str,
_index_name: &str,
_asc: Option<bool>,
_cmp_value: Option<(&IndexOperator, Value)>,
) -> Result<RowIter>;
}
- - + + \ No newline at end of file diff --git a/docs/dev/storages/developing-custom-storages/store-traits/metadata/index.html b/docs/dev/storages/developing-custom-storages/store-traits/metadata/index.html index fb4e7828..ff67695b 100644 --- a/docs/dev/storages/developing-custom-storages/store-traits/metadata/index.html +++ b/docs/dev/storages/developing-custom-storages/store-traits/metadata/index.html @@ -1,17 +1,17 @@ - + - + Metadata | GlueSQL - - - + + +

Metadata

The Metadata trait is an optional implementation for providing additional metadata support in GlueSQL. GlueSQL does not enforce any specific metadata implementation, allowing custom storage developers to decide which type of metadata, such as create time, modify time, etc., they want to provide.

Implementing the Metadata trait can be beneficial in cases where users need to access and manage metadata related to tables, columns, or other database objects. This can help users understand the structure and properties of their data, ensuring proper management and organization.

Currently, the Metadata trait supports the scan_table_meta method for retrieving table metadata. The metadata provided by the storage can be queried using the data dictionary table GLUE_TABLES.

type ObjectName = String;
pub type MetaIter = Box<dyn Iterator<Item = Result<(ObjectName, HashMap<String, Value>)>>>;

#[async_trait(?Send)]
pub trait Metadata {
async fn scan_table_meta(&self) -> Result<MetaIter> {
Ok(Box::new(empty()))
}
}

By implementing the Metadata trait, custom storage developers can provide users with a way to access and manage metadata related to various database objects. This can be particularly useful in situations where users need to understand the properties of their data or maintain a well-organized database structure.

- - + + \ No newline at end of file diff --git a/docs/dev/storages/developing-custom-storages/store-traits/store-mut/index.html b/docs/dev/storages/developing-custom-storages/store-traits/store-mut/index.html index 79fbbe3e..94a455c8 100644 --- a/docs/dev/storages/developing-custom-storages/store-traits/store-mut/index.html +++ b/docs/dev/storages/developing-custom-storages/store-traits/store-mut/index.html @@ -1,17 +1,17 @@ - + - + StoreMut | GlueSQL - - - + + +

StoreMut

While the Store trait is for supporting SELECT queries and reading data, the StoreMut trait is for modifying data. Implementing the StoreMut trait requires the implementation of the Store trait as well. By implementing both the Store and StoreMut traits, you can support most of the commonly used SQL statements. Additionally, you can use the Test Suite to utilize the integration test set provided by GlueSQL. Custom storage developers can verify their own Store & StoreMut implementations by checking if they pass all the tests provided in the Test Suite.

Here are the five methods required to implement the StoreMut trait:

  1. insert_schema: This method is responsible for inserting a new schema into the storage system.

  2. delete_schema: This method is for deleting a schema from the storage system using the provided table name.

  3. append_data: This method appends a list of data rows to an existing table in the storage system.

  4. insert_data: This method inserts a list of key-data row pairs into an existing table in the storage system.

  5. delete_data: This method deletes a list of keys and their corresponding data rows from an existing table in the storage system.

/// By implementing `StoreMut` trait,
/// you can run `INSERT`, `CREATE TABLE`, `DELETE`, `UPDATE` and `DROP TABLE` queries.
#[async_trait(?Send)]
pub trait StoreMut {
async fn insert_schema(&mut self, schema: &Schema) -> Result<()>;

async fn delete_schema(&mut self, table_name: &str) -> Result<()>;

async fn append_data(&mut self, table_name: &str, rows: Vec<DataRow>) -> Result<()>;

async fn insert_data(&mut self, table_name: &str, rows: Vec<(Key, DataRow)>) -> Result<()>;

async fn delete_data(&mut self, table_name: &str, keys: Vec<Key>) -> Result<()>;
}
- - + + \ No newline at end of file diff --git a/docs/dev/storages/developing-custom-storages/store-traits/store/index.html b/docs/dev/storages/developing-custom-storages/store-traits/store/index.html index fc142ddb..a4d8f5cc 100644 --- a/docs/dev/storages/developing-custom-storages/store-traits/store/index.html +++ b/docs/dev/storages/developing-custom-storages/store-traits/store/index.html @@ -1,17 +1,17 @@ - + - + Store | GlueSQL - - - + + +

Store

The Store trait is the most essential trait to implement for custom storage. Simply by implementing the Store trait, you can support SELECT queries in SQL. You may want to analyze and retrieve data from log files or external APIs using SQL. In this case, having only SELECT queries available is sufficient, and there might not be any need for data modification. In such scenarios, implementing GlueSQL's Store trait alone would be adequate.

Here are the four methods required to implement the Store trait:

  1. fetch_schema: This method is responsible for fetching a schema for a given table name. It returns an optional schema if the table exists.

  2. fetch_all_schemas: This method fetches all the schemas from the storage system. It returns a vector of schemas.

  3. fetch_data: This method fetches a specific data row from the storage system using the provided table name and key. It returns an optional data row if the key exists in the table.

  4. scan_data: This method is used to scan all the data rows in a table. It returns an iterator over the rows in the specified table.

pub type RowIter = Box<dyn Iterator<Item = Result<(Key, DataRow)>>>;

/// By implementing `Store` trait, you can run `SELECT` query.
#[async_trait(?Send)]
pub trait Store {
async fn fetch_schema(&self, table_name: &str) -> Result<Option<Schema>>;

async fn fetch_all_schemas(&self) -> Result<Vec<Schema>>;

async fn fetch_data(&self, table_name: &str, key: &Key) -> Result<Option<DataRow>>;

async fn scan_data(&self, table_name: &str) -> Result<RowIter>;
}
- - + + \ No newline at end of file diff --git a/docs/dev/storages/developing-custom-storages/store-traits/transaction/index.html b/docs/dev/storages/developing-custom-storages/store-traits/transaction/index.html index b185af23..fc7142dd 100644 --- a/docs/dev/storages/developing-custom-storages/store-traits/transaction/index.html +++ b/docs/dev/storages/developing-custom-storages/store-traits/transaction/index.html @@ -1,17 +1,17 @@ - + - + Transaction | GlueSQL - - - + + +

Transaction

While transactions are often considered an essential feature for databases, GlueSQL treats transactions as an optional trait. Custom storage developers can choose whether or not to support transactions in their storage implementation. Transactions can be quite heavy and expensive in terms of performance.

If you're building a general-purpose OLTP database, transactions are a necessary feature. However, if you want to handle JSONL log files using SQL, transactions may be desirable, but not strictly necessary at the cost of significant performance degradation.

You can verify your Transaction trait implementation using the Test Suite. However, the Test Suite only provides logical tests for single-threaded environments. If you intend to support transactions in a concurrent environment, you'll need to write additional tests to verify your implementation. This allows different storage implementations to support various transaction isolation levels.

Currently, the SAVEPOINT feature is not supported, and only three methods are available: BEGIN (or START TRANSACTION), ROLLBACK, and COMMIT.

#[async_trait(?Send)]
pub trait Transaction {
async fn begin(&mut self, autocommit: bool) -> Result<bool>;

async fn rollback(&mut self) -> Result<()>;

async fn commit(&mut self) -> Result<()>;
}
- - + + \ No newline at end of file diff --git a/docs/dev/storages/developing-custom-storages/using-test-suite/index.html b/docs/dev/storages/developing-custom-storages/using-test-suite/index.html index 95a63923..581dc38b 100644 --- a/docs/dev/storages/developing-custom-storages/using-test-suite/index.html +++ b/docs/dev/storages/developing-custom-storages/using-test-suite/index.html @@ -1,17 +1,17 @@ - + - + Using the Test Suite | GlueSQL - - - + + +

Using the Test Suite

The GlueSQL Test Suite is a valuable tool for validating your custom storage implementation. By using the provided test sets, you can ensure that your storage implementation adheres to the required specifications and works as expected with GlueSQL.

To use the Test Suite, you will need to implement the Tester trait for your custom storage. A great reference for this process is the MemoryStorage implementation in the GlueSQL source code. Here's an example of how the MemoryStorage implementation looks like:

use {
async_trait::async_trait, gluesql_core::prelude::Glue, gluesql_memory_storage::MemoryStorage,
test_suite::*,
};

struct MemoryTester {
glue: Glue<MemoryStorage>,
}

#[async_trait(?Send)]
impl Tester<MemoryStorage> for MemoryTester {
async fn new(_: &str) -> Self {
let storage = MemoryStorage::default();
let glue = Glue::new(storage);

MemoryTester { glue }
}

fn get_glue(&mut self) -> &mut Glue<MemoryStorage> {
&mut self.glue
}
}

Once you have implemented the Tester trait, you can easily add the relevant test sets for the traits you have implemented in your custom storage. Here's how the MemoryStorage implementation adds the test sets:

generate_store_tests!(tokio::test, MemoryTester);

generate_alter_table_tests!(tokio::test, MemoryTester);

generate_metadata_table_tests!(tokio::test, MemoryTester);

generate_custom_function_tests!(tokio::test, MemoryTester);

The MemoryStorage example demonstrates the use of the four test sets from the Test Suite, indicating that it has implemented the Store, StoreMut, AlterTable, CustomFunction, CustomFunctionMut, and Metadata traits. However, you don't need to implement all Store traits for your custom storage. Instead, you can choose to implement only the traits that are relevant to your use case, and use the corresponding test sets from the Test Suite for validation.

The Test Suite provides test sets for the following traits:

  • generate_store_tests! - Tests for Store and StoreMut implementations. (Note that Store and StoreMut are required for all other test sets.)
  • generate_alter_table_tests! - Tests for the AlterTable trait implementation.
  • generate_custom_function_tests! - Tests for the CustomFunction and CustomFunctionMut trait implementations.
  • generate_index_tests! - Tests for the Index and IndexMut trait implementations.
  • generate_transaction_tests! - Tests for the Transaction trait implementation.
  • generate_metadata_table_tests! - Tests for the Metadata trait implementation.

Additionally, the Test Suite provides combined test sets for cases where you have implemented multiple optional traits:

  • generate_alter_table_index_tests! - Tests for the AlterTable, Index, and IndexMut trait implementations.
  • generate_transaction_alter_table_tests! - Tests for the Transaction and AlterTable trait implementations.
  • generate_transaction_index_tests! - Tests for the Transaction, Index, and IndexMut trait implementations.
  • generate_metadata_index_tests! - Tests for the Metadata, Index, and IndexMut trait implementations.

In summary, the GlueSQL Test Suite is an essential tool for validating your custom storage implementation. By using the provided test sets and the MemoryStorage implementation as an example, you can ensure your storage works correctly with GlueSQL and adheres to the necessary specifications.

- - + + \ No newline at end of file diff --git a/docs/dev/storages/intro/index.html b/docs/dev/storages/intro/index.html index bf39296e..f5d1f321 100644 --- a/docs/dev/storages/intro/index.html +++ b/docs/dev/storages/intro/index.html @@ -1,17 +1,17 @@ - + - + Introduction | GlueSQL - - - + + +

Introduction

GlueSQL is not only suitable for use as a conventional database, but one of its key features is the ability for anyone to easily adapt SQL and the AST Builder to their desired file or storage system. This adaptability is achieved through the following topics covered in this section:

Supported Storages

GlueSQL provides a variety of reference storages out of the box, ranging from simple in-memory storage to key-value databases, log file-based storage like JSON & JSONL, and even Web Storage and IndexedDB supported by web browsers.

Developing Custom Storages

GlueSQL offers an easy-to-understand and implement interface for custom storage development. By implementing the corresponding interface, developers can have SQL and the AST Builder automatically support their custom storage.

Verification of custom storage implementation is also straightforward using GlueSQL's test-suite, which allows developers to easily test their implementation and fix any issues found during the process. With a line coverage of nearly 99% in the GlueSQL project's core code, custom storage developers can complete the development and verification process simply by passing all the test-suite cases.

Exploring the Storages Section

In the Storages section, you will find detailed information about the reference storages currently supported by GlueSQL, as well as guidelines for developing custom storages and what needs to be done to implement them.

Together, these resources make it easy to utilize and adapt GlueSQL for a variety of storage systems.

- - + + \ No newline at end of file diff --git a/docs/dev/storages/supported-storages/composite-storage/index.html b/docs/dev/storages/supported-storages/composite-storage/index.html index 87c1455c..cba6d55d 100644 --- a/docs/dev/storages/supported-storages/composite-storage/index.html +++ b/docs/dev/storages/supported-storages/composite-storage/index.html @@ -1,17 +1,17 @@ - + - + Composite Storage | GlueSQL - - - + + +

Composite Storage

Introduction

CompositeStorage is a special type of Storage. It does not possess any real storage implementation itself. Instead, it offers a powerful capability - the ability to bundle together multiple existing storages. For instance, with CompositeStorage, you can bundle JsonStorage and SledStorage together for simultaneous use. This means you can perform JOIN operations across two distinct storages. You can even read and analyze JSON log files, and directly insert the data into SledStorage.

Unified Interface across Different Storages

In fact, the Javascript (Web) GlueSQL interface already utilizes CompositeStorage. Take a look at this:

CREATE TABLE Mem (mid INTEGER) ENGINE = memory;
CREATE TABLE Loc (lid INTEGER) ENGINE = localStorage;
CREATE TABLE Ses (sid INTEGER) ENGINE = sessionStorage;
CREATE TABLE Idb (iid INTEGER) ENGINE = indexedDB;

SELECT
mid, lid, sid, iid
FROM Mem
JOIN Loc
JOIN Ses
JOIN Idb;

You can create tables using four different storages and perform operations like JOIN using SQL! All you have to do is specify the ENGINE during CREATE TABLE. That's all it takes.

Potential and Future Plans

CompositeStorage can be immensely useful in various applications. At present, GlueSQL might not offer a plethora of reference storages. However, plans are in place to support a diverse range of storages in the future. These include log files like CSV and Parquet, and even NoSQL databases like Redis and MongoDB. They're not exceptions; they can fully provide an SQL interface via GlueSQL.

In addition, just as you would use an ORM to handle multiple different SQL databases with the same interface, plans are in place to use existing SQL databases in a similar way as storages in GlueSQL. Once all these plans come to fruition, you will be able to implement your data pipelines very simply.

Moving data from Redis to MongoDB, or from MySQL to Redis will be a breeze - just by specifying the ENGINE using the same GlueSQL SQL or AST Builder.

Limitations and Considerations

CompositeStorage might sound like a cure-all solution, but it does have its limitations. As it combines different data storages, certain boundaries exist. Transactions, for instance, are a major one. Each storage may have different transaction support and methods. Therefore, it is not advisable to use CompositeStorage for operations that require transactions. It's more suitable for moving or analyzing data across different storages.

Summary

In conclusion, CompositeStorage is an exciting and powerful feature of GlueSQL, enabling users to combine and use different storage types seamlessly. However, users should also be aware of its limitations, such as transaction handling. Despite these constraints, the potential and flexibility offered by CompositeStorage make it a compelling choice for a variety of data manipulation tasks, especially when working with diverse storage types.

- - + + \ No newline at end of file diff --git a/docs/dev/storages/supported-storages/idb-storage/index.html b/docs/dev/storages/supported-storages/idb-storage/index.html index 3e085e46..68034c1f 100644 --- a/docs/dev/storages/supported-storages/idb-storage/index.html +++ b/docs/dev/storages/supported-storages/idb-storage/index.html @@ -1,17 +1,17 @@ - + - + IndexedDB Storage | GlueSQL - - - + + +

IndexedDB Storage

Introduction

IndexedDB, now easily handled just like SQL with GlueSQL - this is truly magical! For those who have directly used IndexedDB before, it's well known that it's not the most intuitive type of database to interact with. Even the MDN IndexedDB introduction page acknowledges this complexity, stating:

Note: IndexedDB API is powerful, but may seem too complicated for simple cases. If you'd prefer a simple API, try libraries in See also section that make IndexedDB more programmer-friendly.

In particular, version management in IndexedDB might be a somewhat unfamiliar concept for regular database users. But worry not, GlueSQL has innovatively handled these intricacies, freeing you from the need to grapple with such complexities. You can just use SQL, and everything will work as expected.

Behind the Scenes

When there are schema changes, like a CREATE TABLE query, GlueSQL increases the IndexedDB version and handles it internally. The data to be stored is also converted into a JSON format for storage. Thanks to this, you can easily check how GlueSQL is handling data by using the IndexedDB viewer in the web browser's developer console.

Compatibility and Use

Currently, only the Store and StoreMut traits are implemented and supported. You can use it in both JavaScript (Web) and Rust WebAssembly environments.

When using it in a web environment, just set the ENGINE to indexedDB in the CREATE TABLE query.

CREATE TABLE Item (id INTEGER, name TEXT) ENGINE = indexedDB;

Just by using it like this, GlueSQL will operate based on the IndexedDB storage.

Summary

In conclusion, if you are seeking for a way to interact with IndexedDB without the usual complexity, GlueSQL is a fantastic choice. It provides a clear, SQL-based approach to managing data, making IndexedDB much more accessible and user-friendly.

- - + + \ No newline at end of file diff --git a/docs/dev/storages/supported-storages/json-storage/index.html b/docs/dev/storages/supported-storages/json-storage/index.html index 15aff5c6..b7091939 100644 --- a/docs/dev/storages/supported-storages/json-storage/index.html +++ b/docs/dev/storages/supported-storages/json-storage/index.html @@ -1,19 +1,19 @@ - + - + JSON Storage | GlueSQL - - - + + +

JSON Storage

Introduction

The JSON Storage system is comprised of two types of files: Schema file(optional) and Data file. The Schema file is written in Standard SQL and is responsible for storing the structure of the table. The Data file contains the actual data and supports two file formats: *.json and *.jsonl. This document provides detailed examples of how to create schema and read/write data using the Json Storage system. While it supports all DML features, it is particularly specialized for SELECT and APPEND INSERT. For further information, please refer to the Limitations section.

Structure

JSON Storage is based on two types of files: Schema and Data. The Schema file contains the definition of the structure of the data, while the Data file contains the actual data.

gluesql> CREATE TABLE User (
id INT,
name TEXT
)
$ ls -l

User.sql # Schema file
User.jsonl # Data file

Schema File

The schema definition is saved in a file named {TABLE_NAME}.sql using standard SQL. For example, if the table name is User, then the schema file will be named User.sql.

--! User.sql
CREATE TABLE User (
id INT,
name TEXT,
);

Schemaless Table

A schemaless table is optional, and if there is no corresponding {TABLE_NAME}.sql file, the table is schemaless. A schemaless table can save any data regardless of column name and data type.

gluesql> CREATE Table User;
$ ls -l

User.jsonl

Data File

JSON Storage saves data in two types of data files: *.jsonl (default) and *.json.

*.jsonl File Format

The *.jsonl file format is a file containing one JSON object per line. For example:

{"id": 1, "name": "Glue"}
{"id": 2, "name": "SQL"}

*.json File Format

The *.json file format supports two different formats:

  1. Array of JSON
[
{
"id": 1,
"name": "Glue"
},
{
"id": 2,
"name": "SQL"
}
]
  1. Single JSON
{
"name": "GlueSQL"
"keywords": ["Database, Rust"]
"stars": 999999
}

Examples

Read Existing JSON/JSONL Schemaless Files

  1. Locate your JSON/JSONL schemaless files in the data path. Here, we use ./data.
$ ls -rlt ./data

User.json
LoginHistory.jsonl

Keep in mind that if there are no *.sql files, the data is considered schemaless, meaning that the number of columns in each row may vary.

//! User.json
[
{
"id": 1,
"name": "Alice",
"location": "New York"
},
{
"id": 2,
"name": "Bob",
"language": "Rust"
},
{
"id": 3,
"name": "Eve"
}
]
//! LoginHistory.jsonl
{"timestamp": "2023-05-01T14:36:22.000Z", "userId": 1, "action": "login"}
{"timestamp": "2023-05-01T14:38:17.000Z", "userId": 2, "action": "logout"}
{"timestamp": "2023-05-02T08:12:05.000Z", "userId": 2, "action": "logout"}
{"timestamp": "2023-05-02T09:45:13.000Z", "userId": 3, "action": "login"}
{"timestamp": "2023-05-03T16:21:44.000Z", "userId": 1, "action": "logout"}
  1. Read with GlueSQL JSON Storage
let path = "./data/";
let json_storage = JsonStorage::new(path).unwrap();
let mut glue = Glue::new(json_storage);

glue.execute("
SELECT *
FROM User U
JOIN LoginHistory L ON U.id = L.userId;
");
actionidlanguagelocationnametimestampuserId
login1New YorkAlice2023-05-01T14:36:22.000Z1
logout1New YorkAlice2023-05-03T16:21:44.000Z1
logout2RustBob2023-05-01T14:38:17.000Z2
logout2RustBob2023-05-02T08:12:05.000Z2
login3Eve2023-05-02T09:45:13.000Z3

Create Schema Table

  1. Create Table
let path = "./data/";
let json_storage = JsonStorage::new(path).unwrap();
let mut glue = Glue::new(json_storage);

glue.execute("
CREATE TABLE Account (
accountId INT NOT NULL,
accountOwner TEXT NOT NULL,
accountType TEXT NOT NULL,
balance INT NOT NULL,
isActive BOOLEAN NOT NULL
);
");
$ ls -l

Account.sql
Account.jsonl
  1. Verity Schema file
--! Account.sql
CREATE TABLE Account (
accountId INT NOT NULL,
accountOwner TEXT NOT NULL,
accountType TEXT NOT NULL,
balance INT NOT NULL,
isActive BOOLEAN NOT NULL
);
  1. Insert data
glue.execute("
INSERT INTO Account VALUES
(10001, 'John Smith', 'Checking', 5000, true),
(10002, 'Jane Doe', 'Savings', 10000, true),
(10003, 'Robert Johnson', 'Checking', 2500, false),
(10004, 'Alice Kim', 'Savings', 7500, true),
(10005, 'Michael Chen', 'Checking', 10000, true);
");
  1. Select data
glue.execute("SELECT * FROM Account;");
accountIdaccountOwneraccountTypebalanceisActive
10001John SmithChecking5000TRUE
10002Jane DoeSavings10000TRUE
10003Robert JohnsonChecking2500FALSE
10004Alice KimSavings7500TRUE
10005Michael ChenChecking10000TRUE
  1. Verify Data file
//! Account.jsonl
{"accountId":10001,"accountOwner":"John Smith","accountType":"Checking","balance":5000,"isActive":true}
{"accountId":10002,"accountOwner":"Jane Doe","accountType":"Savings","balance":10000,"isActive":true}
{"accountId":10003,"accountOwner":"Robert Johnson","accountType":"Checking","balance":2500,"isActive":false}
{"accountId":10004,"accountOwner":"Alice Kim","accountType":"Savings","balance":7500,"isActive":true}
{"accountId":10005,"accountOwner":"Michael Chen","accountType":"Checking","balance":10000,"isActive":true}

Limitation

JSON Storage is capable of supporting a variety of operations, including SELECT, INSERT, DELETE, and UPDATE.
However, its design primarily emphasizes SELECT and APPEND INSERT functionality.
It's important to note that if you perform DELETE, UPDATE, or INSERT in the middle of the rows, it can cause the internal rewriting of all the rows, which can lead to a decrease in performance.

- - + + \ No newline at end of file diff --git a/docs/dev/storages/supported-storages/memory-storage/index.html b/docs/dev/storages/supported-storages/memory-storage/index.html index 6ef03464..adcc004c 100644 --- a/docs/dev/storages/supported-storages/memory-storage/index.html +++ b/docs/dev/storages/supported-storages/memory-storage/index.html @@ -1,17 +1,17 @@ - + - + Memory Storage | GlueSQL - - - + + +

Memory Storage

MemoryStorage is a foundational storage option designed for in-memory, non-persistent data. Despite its simplicity, it is robust enough for use in production environments.

A key aspect of MemoryStorage is not only its functionality but also its role as an exemplary case showcasing how simple it is to develop custom storage in GlueSQL. It provides a practical demonstration of what a minimalistic, yet fully functional storage interface can look like in GlueSQL.

MemoryStorage is accessible across multiple environments, including Rust, Rust (WASM), JavaScript (Web), and Node.js.

The storage interface is implemented with the following traits: Store, StoreMut, AlterTable, CustomFunction, CustomFunctionMut, and Metadata.

Consider the Rust code structure for MemoryStorage:

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Item {
pub schema: Schema,
pub rows: BTreeMap<Key, DataRow>,
}

#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct MemoryStorage {
pub id_counter: i64,
pub items: HashMap<String, Item>,
pub metadata: HashMap<String, HashMap<String, Value>>,
pub functions: HashMap<String, StructCustomFunction>,
}

This structure defines the Item and MemoryStorage structs. Item struct holds the schema and rows, while MemoryStorage struct consists of id_counter (to keep track of the row IDs), items (to store the actual data), metadata (to keep metadata), and functions (to store custom functions).

Below are the implementations of the Store and StoreMut traits for MemoryStorage:

#[async_trait(?Send)]
impl Store for MemoryStorage {
// Code for fetching schemas and data
}

#[async_trait(?Send)]
impl StoreMut for MemoryStorage {
// Code for manipulating schemas and data
}

The Store trait implementation provides methods for fetching all schemas, fetching a specific schema, fetching data from a specific table with a given key, and scanning all data from a particular table.

On the other hand, the StoreMut trait implementation provides methods for inserting a new schema, deleting an existing schema, appending data to a table, inserting data into a table with a specific key, and deleting data from a table with given keys.

In summary, the MemoryStorage structure in GlueSQL is a straightforward yet powerful tool that elegantly showcases how simple it is to create a custom storage system. It's a testament to the power and flexibility of GlueSQL's design and the ease of implementing robust storage solutions with it.

- - + + \ No newline at end of file diff --git a/docs/dev/storages/supported-storages/shared-memory-storage/index.html b/docs/dev/storages/supported-storages/shared-memory-storage/index.html index 883ee1c2..797e03b8 100644 --- a/docs/dev/storages/supported-storages/shared-memory-storage/index.html +++ b/docs/dev/storages/supported-storages/shared-memory-storage/index.html @@ -1,17 +1,17 @@ - + - + Shared Memory Storage | GlueSQL - - - + + +

Shared Memory Storage

SharedMemoryStorage is a storage option designed to provide more comfortable usage of MemoryStorage in concurrent environments. Although it doesn't operate in parallel, it makes accessing the same data from multiple threads simultaneously more convenient.

The basic structure of SharedMemoryStorage is straightforward. It wraps the MemoryStorage with a read-write lock (RwLock) and an atomic reference count (Arc):

#[derive(Clone, Debug)]
pub struct SharedMemoryStorage {
pub database: Arc<RwLock<MemoryStorage>>,
}

This structure allows you to clone the storage instance and use it effortlessly across multiple threads. Regardless of how many times the storage is cloned, all storage instances will refer to the same data.

Here's an example of how to use SharedMemoryStorage in a concurrent environment:

use gluesql_core::prelude::{Glue, Payload, Value};

async fn concurrent_access() {
let storage = SharedMemoryStorage::new();

let mut glue = Glue::new(storage.clone());
glue.execute("CREATE TABLE Thread (id INTEGER);").unwrap();

let thread_1 = tokio::spawn({
let storage = storage.clone();
async {
let mut glue = Glue::new(storage);
glue.execute("INSERT INTO Thread VALUES(1)").unwrap();
}
});

let thread_2 = tokio::spawn({
let storage = storage.clone();
async {
let mut glue = Glue::new(storage);
glue.execute("INSERT INTO Thread VALUES(2)").unwrap();
}
});

let _ = tokio::join!(thread_1, thread_2);

let actual = glue.execute("SELECT * FROM Thread").unwrap();
let expected = vec![Payload::Select {
labels: vec!["id".to_owned()],
rows: vec![vec![Value::I64(1)], vec![Value::I64(2)]],
}];
assert_eq!(actual, expected);
}

The concurrent_access function above illustrates how to concurrently insert data into the same table from different threads. After inserting data from two separate threads, we can confirm that the inserted data is correctly stored by executing a SELECT statement.

SharedMemoryStorage is primarily intended for convenience rather than performance when dealing with multiple threads. As you can see from the structure, placing a read-write lock (RwLock) on the entire database is not recommended for performance reasons when handling data concurrently from multiple threads. Therefore, it's best to use SharedMemoryStorage or MemoryStorage depending on the situation.

SharedMemoryStorage is only available in the Rust environment, and its implementation of the Store trait is identical to that of MemoryStorage.

- - + + \ No newline at end of file diff --git a/docs/dev/storages/supported-storages/sled-storage/index.html b/docs/dev/storages/supported-storages/sled-storage/index.html index acc70eed..5faee1a3 100644 --- a/docs/dev/storages/supported-storages/sled-storage/index.html +++ b/docs/dev/storages/supported-storages/sled-storage/index.html @@ -1,17 +1,17 @@ - + - + Sled Storage | GlueSQL - - - + + +

Sled Storage

SledStorage is currently the representative persistent data storage for GlueSQL. As the name suggests, it's a storage option based on the Sled key-value embedded database built in Rust (Sled on Github).

SledStorage can only be used in a Rust environment. It is the only storage among those currently supported by GlueSQL that implements all Store traits, from non-clustered indexes to transactions. If you're looking for a basic storage to handle and store data in a Rust environment, SledStorage is an excellent choice.

How to use

You can simply create a SledStorage instance using a path, as shown below:

use {
gluesql::{prelude::Glue, sled_storage::SledStorage},
sled_storage::sled,
std::convert::TryFrom,
};

fn main() {
let storage = SledStorage::new("data/temp").unwrap();
let mut glue = Glue::new(storage);

let sqls = "
CREATE TABLE Glue (id INTEGER);
INSERT INTO Glue VALUES (100), (200);
";

glue.execute(sqls).unwrap();
}

If you want to use the Sled that SledStorage uses directly with a specific configuration, you can do so as follows:

let config = sled::Config::default()
.path("data/using_config")
.temporary(true)
.mode(sled::Mode::HighThroughput);

let storage = SledStorage::try_from(config).unwrap();
let mut glue = Glue::new(storage);

Things to Know About Transactions

The implementation of transactions in SledStorage manages not only data but also indexes and schema information based on snapshots. For example, if you use the following commands:

BEGIN;

CREATE TABLE Foo;
INSERT INTO Foo VALUES (1);

ROLLBACK;

The above usage will result in a rollback of even the contents regarding the Foo table. The transaction isolation level is repeatable read (snapshot isolation).

By default, there is a timeout for Transactions. The default is set to one hour, but you can modify the value or remove the timeout if desired.

storage.set_transaction_timeout(Some(1000)); // 1 sec
storage.set_transaction_timeout(None); // no timeout

Summary

If you're looking for a storage to handle data for general purposes in a Rust environment, SledStorage would be your go-to choice. It offers all the necessary features of a database system, such as managing non-clustered indexes, handling transactions, and maintaining persistent storage. Additionally, its snapshot-based transaction model ensures consistency and reliability, making it an excellent choice for applications requiring persistent data storage.

- - + + \ No newline at end of file diff --git a/docs/dev/storages/supported-storages/web-storage/index.html b/docs/dev/storages/supported-storages/web-storage/index.html index 54e32b08..c6683cd1 100644 --- a/docs/dev/storages/supported-storages/web-storage/index.html +++ b/docs/dev/storages/supported-storages/web-storage/index.html @@ -1,17 +1,17 @@ - + - + WebStorage (local & session) | GlueSQL - - - + + +

WebStorage (local & session)

WebStorage - yes, the localStorage and sessionStorage you're familiar with. With GlueSQL, you can use SQL to interact with these storages!

WebStorage serves as a data storage that supports READ & WRITE operations. As GlueSQL can be ported to any place where READ & WRITE are possible, it can utilize WebStorage as one of its storage systems.

WebStorage provides a very simple and easy-to-use interface. All you need to do is read and write data using a string key. If you need to manage more structured data, you can use GlueSQL.

WebStorage can be used in JavaScript (Web) environments and Rust WebAssembly environments.

Usage

The way to use it is no different from using other storages.

import { gluesql } from 'gluesql';

async function run() {
const db = await gluesql();

const result = await db.query(`
CREATE TABLE Foo (id INTEGER, name TEXT) ENGINE = localStorage;
INSERT INTO Foo VALUES (1, 'hello'), (2, 'world');
SELECT * FROM Foo;
CREATE TABLE Bar ENGINE = sessionStorage;
INSERT INTO Bar VALUES ('{ "a": "schemaless", "b": 1024 }');
SELECT * FROM Bar;
`);

console.log(result);
}

Simple, isn't it?

Things to keep in mind

In the case of WebStorage, depending on the web browser, there is usually a size constraint of about 10MB for data storage. Even when using GlueSQL, you should keep in mind that it is used within these restrictions.

Summary

To sum up, WebStorage is a handy feature that allows you to manipulate localStorage and sessionStorage with SQL in a browser environment. It's simple, easy to use, and can handle structured data which makes it an ideal choice for lightweight web applications.

However, due to storage limitations, it's not suitable for large-scale data handling. Remember to consider these limitations when choosing your storage options in GlueSQL. Even with these constraints, it serves as a great tool for managing and interacting with your browser's storage in a structured way using SQL.

- - + + \ No newline at end of file