diff --git a/404.html b/404.html index 9585ae28..97716ca9 100644 --- a/404.html +++ b/404.html @@ -3,12 +3,12 @@ -Page Not Found | OpenHouse +Page Not Found | OpenHouse - - + + -
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.

+
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/assets/images/openhouse-deployed-architecture-1bcd512d5ecde3919f2bcc5bdd0e93dd.jpeg b/assets/images/openhouse-deployed-architecture-1bcd512d5ecde3919f2bcc5bdd0e93dd.jpeg new file mode 100644 index 00000000..a0d54b9b Binary files /dev/null and b/assets/images/openhouse-deployed-architecture-1bcd512d5ecde3919f2bcc5bdd0e93dd.jpeg differ diff --git a/assets/images/openhouse-deployed-architecture-94d43e6dfe0c0035ada5755c63a53310.jpeg b/assets/images/openhouse-deployed-architecture-94d43e6dfe0c0035ada5755c63a53310.jpeg deleted file mode 100644 index 2d625977..00000000 Binary files a/assets/images/openhouse-deployed-architecture-94d43e6dfe0c0035ada5755c63a53310.jpeg and /dev/null differ diff --git a/assets/js/0e384e19.1fa53ec9.js b/assets/js/0e384e19.1fa53ec9.js deleted file mode 100644 index 4cc92062..00000000 --- a/assets/js/0e384e19.1fa53ec9.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkdocs=self.webpackChunkdocs||[]).push([[9671],{7876:(e,a,t)=>{t.r(a),t.d(a,{assets:()=>l,contentTitle:()=>r,default:()=>h,frontMatter:()=>s,metadata:()=>o,toc:()=>c});var n=t(5893),i=t(1151);const s={sidebar_position:1},r="Overview",o={id:"intro",title:"Overview",description:"OpenHouse is an open-source control plane designed for efficient management of tables within open data lakehouse",source:"@site/docs/intro.md",sourceDirName:".",slug:"/intro",permalink:"/docs/intro",draft:!1,unlisted:!1,tags:[],version:"current",sidebarPosition:1,frontMatter:{sidebar_position:1},sidebar:"docsSidebar",next:{title:"User Guide",permalink:"/docs/category/user-guide"}},l={},c=[{value:"Control Plane for Tables",id:"control-plane-for-tables",level:2},{value:"Catalog Service",id:"catalog-service",level:3},{value:"Multi Table Format Support",id:"multi-table-format-support",level:4},{value:"Committing Table Metadata",id:"committing-table-metadata",level:4},{value:"House Table Service",id:"house-table-service",level:3},{value:"Data Services",id:"data-services",level:3},{value:"Jobs Scheduler",id:"jobs-scheduler",level:4},{value:"Jobs Service",id:"jobs-service",level:4},{value:"Engine Integration",id:"engine-integration",level:2},{value:"Deployed System Architecture",id:"deployed-system-architecture",level:2},{value:"Pluggable Architecture",id:"pluggable-architecture",level:2}];function d(e){const a={a:"a",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",h4:"h4",img:"img",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,i.a)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(a.h1,{id:"overview",children:"Overview"}),"\n",(0,n.jsxs)(a.p,{children:["OpenHouse is an open-source control plane designed for efficient management of tables within open data lakehouse\ndeployments. The control plane comprises a ",(0,n.jsx)(a.strong,{children:"declarative catalog"})," and a suite of ",(0,n.jsx)(a.strong,{children:"data services"}),". Users can\nseamlessly define Tables, their schemas, and associated metadata declaratively within the catalog.\nOpenHouse reconciles the observed state of Tables with their desired state by orchestrating various\ndata services."]}),"\n",(0,n.jsx)(a.h2,{id:"control-plane-for-tables",children:"Control Plane for Tables"}),"\n",(0,n.jsx)(a.p,{children:"Following figure shows how OpenHouse control plane fits into a broader open source data lakehouse deployment."}),"\n",(0,n.jsx)(a.p,{children:(0,n.jsx)(a.img,{alt:"High Level Overview",src:t(1369).Z+"",width:"510",height:"660"})}),"\n",(0,n.jsx)(a.h3,{id:"catalog-service",children:"Catalog Service"}),"\n",(0,n.jsx)(a.p,{children:"The core of OpenHouse's control plane is a RESTful Table Service that provides secure and scalable table provisioning\nand declarative metadata management.\nAt the core of the Catalog Service is the Table model. A Table is a logical representation of a dataset in the data.\nIt includes the following metadata:"}),"\n",(0,n.jsxs)(a.ul,{children:["\n",(0,n.jsx)(a.li,{children:"Identifiers (Cluster ID, Database ID, Table ID, Table URI, Table UUID)"}),"\n",(0,n.jsx)(a.li,{children:"Schema (Column Name, Column Type, Column Comment)"}),"\n",(0,n.jsx)(a.li,{children:"Time Partitioning and String Clustering (Column Name)"}),"\n",(0,n.jsx)(a.li,{children:"Table Policies (Retention, Sharing, Tags)"}),"\n",(0,n.jsx)(a.li,{children:"Table Type (Primary, Replica)"}),"\n",(0,n.jsx)(a.li,{children:"Versioning (Table Version)"}),"\n",(0,n.jsx)(a.li,{children:"Other Metadata (Creator, Created Time, Last Modified Time)"}),"\n"]}),"\n",(0,n.jsx)(a.h4,{id:"multi-table-format-support",children:"Multi Table Format Support"}),"\n",(0,n.jsx)(a.p,{children:"Catalog Service APIs are designed to support multiple table formats. Currently, it supports Iceberg and POC for Delta is\nWIP. To be able to extend to multiple table formats, following considerations need to be made:"}),"\n",(0,n.jsxs)(a.ol,{children:["\n",(0,n.jsx)(a.li,{children:"Base Table API, Metadata and Policies are designed to be format agnostic. For example, Retention, Sharing are generic\nuse-cases across all table formats."}),"\n",(0,n.jsxs)(a.li,{children:["Schema representation is serialized string. This allows to use the ",(0,n.jsx)(a.a,{href:"https://github.com/apache/iceberg/blob/main/api/src/main/java/org/apache/iceberg/Schema.java",children:"Iceberg Schema"}),"\nfor Iceberg tables and for Delta tables use the ",(0,n.jsx)(a.a,{href:"https://spark.apache.org/docs/latest/api/java/org/apache/spark/sql/types/StructType.html",children:"Spark StructType"})]}),"\n",(0,n.jsx)(a.li,{children:"In case there is a need to represent format specific metadata in the API, it is done through the API extensions as\nshown below:"}),"\n"]}),"\n",(0,n.jsx)(a.pre,{children:(0,n.jsx)(a.code,{children:"/dabatase/{databaseId}/table/{tableId}/ --\x3e Base Table API\n/database/{databaseId}/table/{tableId}/iceberg/v2/snapshots --\x3e Iceberg specific API extensions\n/databases/{databaseId}/tables/{tableId}/delta/v1/actions --\x3e Delta specific API extensions\n"})}),"\n",(0,n.jsx)(a.h4,{id:"committing-table-metadata",children:"Committing Table Metadata"}),"\n",(0,n.jsx)(a.p,{children:"When a table is created or updated, catalog service writes the table metadata to the table format specific metadata\nfile on storage. In case of Iceberg tables, the service writes all the Openhouse specific table metadata to Iceberg\ntable's root metadata json file. The service then writes the location of this root metadata to the House Table Service\nthrough an atomic compare version and swap version and file location."}),"\n",(0,n.jsx)(a.h3,{id:"house-table-service",children:"House Table Service"}),"\n",(0,n.jsxs)(a.p,{children:["House Table Service is a RESTful service designed to provide a key-value API for storing and retrieving\nmetadata for ",(0,n.jsx)(a.a,{href:"#catalog-service",children:"Catalog Service"})," and ",(0,n.jsx)(a.a,{href:"#jobs-service",children:"Jobs Service"}),". The backend storage for House Table\nService is pluggable, and can use a Database supported by ",(0,n.jsx)(a.a,{href:"https://spring.io/projects/spring-data",children:"Spring Data JPA"}),".\nThe default implementation uses H2 in-memory, but it can be extended to use other databases like MySQL, Postgres, etc."]}),"\n",(0,n.jsx)(a.p,{children:"Note, house table service is an internal service, and should only be accessed via Catalog Service or Jobs Service."}),"\n",(0,n.jsx)(a.h3,{id:"data-services",children:"Data Services"}),"\n",(0,n.jsx)(a.p,{children:"Jobs Scheduler and Jobs Service are the two components that are responsible for orchestrating the execution of data\nservices. These components are designed to be modular and can be extended to support multiple data services."}),"\n",(0,n.jsx)(a.h4,{id:"jobs-scheduler",children:"Jobs Scheduler"}),"\n",(0,n.jsx)(a.p,{children:"Jobs Scheduler (at /apps/spark) is responsible for iterating through all the tables, and for each table, it will trigger\nthe corresponding job type by calling the Jobs Service endpoint. It can be run as a cronjob per job type. Currently,\nfollowing job types are supported:"}),"\n",(0,n.jsxs)(a.ul,{children:["\n",(0,n.jsx)(a.li,{children:"Retention"}),"\n",(0,n.jsx)(a.li,{children:"Iceberg Snapshot Expiration"}),"\n",(0,n.jsx)(a.li,{children:"Iceberg Orphan File Deletion"}),"\n",(0,n.jsx)(a.li,{children:"Iceberg Staged File Deletion"}),"\n"]}),"\n",(0,n.jsxs)(a.p,{children:["Jobs Scheduler integrates with the ",(0,n.jsx)(a.a,{href:"#catalog-service",children:"Catalog Service"})," to get the list of tables and corresponding\nmetadata. For example, if a table has a retention policy of 30 days, Jobs Scheduler will trigger the Job Service with\nthe table name and retention period."]}),"\n",(0,n.jsx)(a.h4,{id:"jobs-service",children:"Jobs Service"}),"\n",(0,n.jsxs)(a.p,{children:["All the job types discussed in ",(0,n.jsx)(a.a,{href:"#jobs-scheduler",children:"Jobs Scheduler"})," are implemented as Spark applications, and it is the\nJobs Service (at /services/jobs) that is responsible for submitting these jobs to the Spark cluster. Jobs Services is a\nRESTful service that provides an endpoint for the scheduler to trigger a job. Jobs Service is modularized in a way that\nit can be extended to support various spark job submission APIs. One such implementation based on Apache Livy can be\nfound at ",(0,n.jsx)(a.em,{children:"services/jobs"}),", and it is used in docker compose setup."]}),"\n",(0,n.jsxs)(a.p,{children:["Jobs Service also maintains all the job metadata in the ",(0,n.jsx)(a.a,{href:"#house-table-service",children:"House Table Service"}),", including the\nstatus of the job, the time it was triggered, table name, table metadata, error logs, and job type. This metadata is\nused for tracking job completions, observability and monitoring purposes."]}),"\n",(0,n.jsx)(a.h2,{id:"engine-integration",children:"Engine Integration"}),"\n",(0,n.jsxs)(a.p,{children:["OpenHouse is designed to integrate with various engines like Spark, Trino, and Flink at their Catalog layer. For Iceberg\ntables, OpenHouseCatalog (at /integrations/spark) implementation is provided that extends Iceberg's ",(0,n.jsx)(a.a,{href:"https://github.com/apache/iceberg/blob/main/core/src/main/java/org/apache/iceberg/BaseMetastoreCatalog.java",children:"BaseMetastoreCatalog"}),"\nGiven OpenHouse supports Table Sharing and Policy Management through Spark SQL syntax, SQL extensions are created, and\nimplemented in the OpenHouseCatalog."]}),"\n",(0,n.jsx)(a.p,{children:"The engine side integration with OpenHouseCatalog leverages a lower level REST client to interact with the Catalog\nService. This REST client is autogenerated as part of the build process from the OpenAPI documentation as described in\nthe Client Codegen (docs/development/client-code-generation.md) guide."}),"\n",(0,n.jsx)(a.p,{children:"Trino and Flink engines follow a similar pattern of integration with OpenHouse and are work in progress."}),"\n",(0,n.jsx)(a.h2,{id:"deployed-system-architecture",children:"Deployed System Architecture"}),"\n",(0,n.jsx)(a.p,{children:(0,n.jsx)(a.img,{alt:"Example Deployed System Architecture",src:t(9009).Z+"",width:"1024",height:"584"})}),"\n",(0,n.jsx)(a.p,{children:"The figure above shows system components of OpenHouse deployed at LinkedIn. Each component is numbered and its purpose\nis as follows:"}),"\n",(0,n.jsx)(a.p,{children:"[1] Catalog (/Table) service: This is a RESTful web service that exposes tables REST resources. This service is deployed\non a Kubernetes cluster with a fronting Envoy Network Proxy."}),"\n",(0,n.jsx)(a.p,{children:"[2] REST clients: A variety of applications use REST clients to call into table service (#1). Clients include but are\nnot limited to compliance apps, replication apps, data discovery apps like Datahub and IaC, Terraform providers, and\ndata quality checkers. Some of the apps that work on all the tables in OpenHouse are assigned higher privileges."}),"\n",(0,n.jsx)(a.p,{children:"[3] Metastore Catalog: Spark,Trino, andFlink engines are a special flavor of REST clients. An OpenHouse specific\nmetastore catalog implementation allows engines to integrate with OpenHouse tables."}),"\n",(0,n.jsx)(a.p,{children:"[4] House Database (/Table) service: This is an internal service to store table service and data service metadata. This\nservice exposes a key-value interface that is designed to use a NoSQL DB for scale and cost optimization. However the\ndeployed system is currently backed by a MySQL instance, for ease of development and deployment."}),"\n",(0,n.jsx)(a.p,{children:"[5] Managed namespace: This is a managed HDFS namespace where tables are persisted in Iceberg table format. Table\nservice is responsible for setting up the table directory structure with appropriate FileSystem permissioning.\nOpenHouse has a novel HDFS permissioning scheme that makes it possible for any ETL flow to publish directly to Iceberg tables and securely into a managed HDFS namespace."}),"\n",(0,n.jsx)(a.p,{children:"[6] Data services: This is a set of data services that reconciles the user / system declared configuration with the\nsystem observed configuration. This includes use cases such as retention, restatement, and Iceberg-specific maintenance.\nEach maintenance activity is scheduled as a Spark job per table. A Kubernetes cronjob is run periodically on a schedule to trigger a maintenance activity. All the bookkeeping of jobs is done in House Database Service using a jobs metadata table for ease of debugging and monitoring."}),"\n",(0,n.jsx)(a.h2,{id:"pluggable-architecture",children:"Pluggable Architecture"}),"\n",(0,n.jsx)(a.p,{children:"Components of OpenHouse are designed to be pluggable, so that OpenHouse can be deployed in diverse private and public\ncloud environments. This pluggability is available for the following components (Note: Integrations with a (*) are\navailable, and for other integrations, APIs are defined but not implemented yet.)"}),"\n",(0,n.jsxs)(a.ul,{children:["\n",(0,n.jsx)(a.li,{children:"Storage backend for example, HDFS(*), Blob Stores, etc."}),"\n",(0,n.jsxs)(a.li,{children:["File Formats for example, Orc(",(0,n.jsx)(a.em,{children:"), Parquet("}),")."]}),"\n",(0,n.jsxs)(a.li,{children:["Database for ",(0,n.jsx)(a.a,{href:"#house-table-service",children:"House Table Service"})," for example, MySQL(*), Postgres, etc."]}),"\n",(0,n.jsxs)(a.li,{children:["Job Submission API for ",(0,n.jsx)(a.a,{href:"#jobs-service",children:"Jobs Service"})," for example, Apache Livy(*), Spark REST etc."]}),"\n",(0,n.jsx)(a.li,{children:"Custom Authentication and Authorization handlers for all the services specific to an environment."}),"\n"]}),"\n",(0,n.jsx)(a.p,{children:"OpenHouse Cluster Configuration Spec (at /cluster/configs) is the place where all the configurations are defined for a\nparticular cluster setup."})]})}function h(e={}){const{wrapper:a}={...(0,i.a)(),...e.components};return a?(0,n.jsx)(a,{...e,children:(0,n.jsx)(d,{...e})}):d(e)}},1369:(e,a,t)=>{t.d(a,{Z:()=>n});const n=t.p+"assets/images/openhouse-controlplane-91ace254c8643ca21b4dae37692b4299.jpeg"},9009:(e,a,t)=>{t.d(a,{Z:()=>n});const n=t.p+"assets/images/openhouse-deployed-architecture-94d43e6dfe0c0035ada5755c63a53310.jpeg"},1151:(e,a,t)=>{t.d(a,{Z:()=>o,a:()=>r});var n=t(7294);const i={},s=n.createContext(i);function r(e){const a=n.useContext(s);return n.useMemo((function(){return"function"==typeof e?e(a):{...a,...e}}),[a,e])}function o(e){let a;return a=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:r(e.components),n.createElement(s.Provider,{value:a},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/0e384e19.aab8cbe3.js b/assets/js/0e384e19.aab8cbe3.js new file mode 100644 index 00000000..9016fa7c --- /dev/null +++ b/assets/js/0e384e19.aab8cbe3.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs=self.webpackChunkdocs||[]).push([[9671],{7876:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>l,contentTitle:()=>o,default:()=>h,frontMatter:()=>s,metadata:()=>r,toc:()=>c});var t=i(5893),a=i(1151);const s={sidebar_position:1},o="Overview",r={id:"intro",title:"Overview",description:"OpenHouse is an open-source control plane designed for efficient management of tables within open data lakehouse",source:"@site/docs/intro.md",sourceDirName:".",slug:"/intro",permalink:"/docs/intro",draft:!1,unlisted:!1,tags:[],version:"current",sidebarPosition:1,frontMatter:{sidebar_position:1},sidebar:"docsSidebar",next:{title:"User Guide",permalink:"/docs/category/user-guide"}},l={},c=[{value:"Control Plane for Tables",id:"control-plane-for-tables",level:2},{value:"Catalog Service",id:"catalog-service",level:3},{value:"Data Services",id:"data-services",level:3},{value:"Jobs Scheduler",id:"jobs-scheduler",level:4},{value:"Jobs Service",id:"jobs-service",level:4},{value:"House Table Service",id:"house-table-service",level:3},{value:"Engine Integration",id:"engine-integration",level:2},{value:"Deployed System Architecture",id:"deployed-system-architecture",level:2},{value:"Pluggable Architecture",id:"pluggable-architecture",level:2}];function d(e){const n={a:"a",h1:"h1",h2:"h2",h3:"h3",h4:"h4",img:"img",li:"li",p:"p",strong:"strong",ul:"ul",...(0,a.a)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h1,{id:"overview",children:"Overview"}),"\n",(0,t.jsxs)(n.p,{children:["OpenHouse is an open-source control plane designed for efficient management of tables within open data lakehouse\ndeployments. The control plane comprises a ",(0,t.jsx)(n.strong,{children:"declarative catalog"})," and a suite of ",(0,t.jsx)(n.strong,{children:"data services"}),". Users can\nseamlessly define Tables, their schemas, and associated metadata declaratively within the catalog.\nOpenHouse reconciles the observed state of Tables with their desired state by orchestrating various\ndata services."]}),"\n",(0,t.jsx)(n.h2,{id:"control-plane-for-tables",children:"Control Plane for Tables"}),"\n",(0,t.jsx)(n.p,{children:"Following figure shows how OpenHouse control plane fits into a broader open source data lakehouse deployment."}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.img,{alt:"High Level Overview",src:i(1369).Z+"",width:"510",height:"660"})}),"\n",(0,t.jsx)(n.h3,{id:"catalog-service",children:"Catalog Service"}),"\n",(0,t.jsx)(n.p,{children:"The core of OpenHouse's control plane is a RESTful Table Service that provides secure and scalable table provisioning\nand declarative metadata management. The service exposes Tables as the RESTful resource which includes following metadata:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"Identifiers (Cluster ID, Database ID, Table ID, Table URI, Table UUID)"}),"\n",(0,t.jsx)(n.li,{children:"Schema (Column Name, Column Type, Column Comment)"}),"\n",(0,t.jsx)(n.li,{children:"Time Partitioning and String Clustering (Column Name)"}),"\n",(0,t.jsx)(n.li,{children:"Table Policies (Retention, Sharing, Tags)"}),"\n",(0,t.jsx)(n.li,{children:"Table Type (Primary, Replica)"}),"\n",(0,t.jsx)(n.li,{children:"Other Metadata (Creator Principal, Created Time, Last Modified Time, and Version)"}),"\n"]}),"\n",(0,t.jsx)(n.h3,{id:"data-services",children:"Data Services"}),"\n",(0,t.jsx)(n.p,{children:"Jobs Scheduler and Jobs Service are the two components that are responsible for orchestrating the execution of data\nservices. Data services are designed to be modular and can be extended to support various data management operations."}),"\n",(0,t.jsx)(n.h4,{id:"jobs-scheduler",children:"Jobs Scheduler"}),"\n",(0,t.jsxs)(n.p,{children:["Jobs Scheduler is responsible for iterating through all the tables, and for each table, it triggers a set of jobs\n(i.e. data services) to keep the table in a user-configured, system-defined, and compliant state. Job scheduler can be\nrun as a cronjob per job type. It integrates with the ",(0,t.jsx)(n.a,{href:"#catalog-service",children:"Catalog Service"})," to get the list of tables and\ncorresponding metadata. It triggers the corresponding job by calling the ",(0,t.jsx)(n.a,{href:"#jobs-service",children:"Jobs Service"})," endpoint. For\nexample, if a table has a retention policy of 30 days, Jobs Scheduler will trigger the Job Service with the table name\nand retention period."]}),"\n",(0,t.jsx)(n.p,{children:"Job types supported today are described below:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["Retention","\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"Users can establish retention policies on time-partitioned tables. Retention job automatically identifies and delete\npartitions older than the specified threshold."}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["Iceberg Snapshot Expiration","\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"Iceberg tables can have a retention policy on the snapshots. This job type is responsible for deleting the snapshots\nolder than the specified threshold."}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["Iceberg Orphan File Deletion","\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"Iceberg tables can have orphan files that are not referenced by any snapshot. This job type is responsible for\nidentifying and staging them for deleting in a trash directory."}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["Staged File Deletion","\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"All the staged files that are marked for deletion are deleted by staged file deletion job."}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["Data Compaction","\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"This job type is responsible for compacting the small files in the table to improve the query performance and\noptimally use the assigned file quotas."}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,t.jsx)(n.h4,{id:"jobs-service",children:"Jobs Service"}),"\n",(0,t.jsxs)(n.p,{children:["All the job types discussed in ",(0,t.jsx)(n.a,{href:"#jobs-scheduler",children:"Jobs Scheduler"})," are implemented as Spark applications, and it is the\nJobs Service that is responsible for submitting these jobs to the Spark cluster. Jobs Services is a\nRESTful service that provides an endpoint for the scheduler to trigger a job. Jobs Service is modularized in a way that\nit can be extended to support various spark job submission APIs. One such implementation based on Apache Livy API is\nshipped with the repository, and is used in docker compose setup."]}),"\n",(0,t.jsx)(n.p,{children:"Jobs Service also tracks all the job metadata, including the status of the job, the time it was triggered, table name,\ntable metadata, error logs, and job type. This metadata is used for tracking job completions, observability and\nmonitoring purposes at table granularity."}),"\n",(0,t.jsx)(n.h3,{id:"house-table-service",children:"House Table Service"}),"\n",(0,t.jsxs)(n.p,{children:["House Table Service is an internal RESTful service used by ",(0,t.jsx)(n.a,{href:"#catalog-service",children:"Catalog Service"})," and ",(0,t.jsx)(n.a,{href:"#data-services",children:"Data Services"}),".\nThe backend storage for House Table Service is pluggable, and can use a Database supported by ",(0,t.jsx)(n.a,{href:"https://spring.io/projects/spring-data",children:"Spring Data JPA"}),".\nThe default implementation uses H2 in-memory, but it can be extended to use other databases like MySQL, Postgres, etc."]}),"\n",(0,t.jsx)(n.h2,{id:"engine-integration",children:"Engine Integration"}),"\n",(0,t.jsxs)(n.p,{children:["OpenHouse is designed to integrate with various engines like Spark, Trino, and Flink at their Catalog layer. For Iceberg\ntables, ",(0,t.jsx)(n.a,{href:"https://github.com/linkedin/openhouse/blob/main/integrations/java/openhouse-java-runtime/src/main/java/com/linkedin/openhouse/javaclient/OpenHouseCatalog.java",children:"OpenHouseCatalog"}),"\nimplementation is provided to integrate with Spark. Given OpenHouse supports Table Sharing and Policy Management through\nSpark SQL syntax, SQL extensions are created, and implemented in the OpenHouseCatalog."]}),"\n",(0,t.jsx)(n.p,{children:"The integration on the engine side is anticipated to utilize a lightweight REST client for communication with the\nCatalog Service."}),"\n",(0,t.jsx)(n.p,{children:"Trino and Flink engines follow a similar pattern of integration with OpenHouse and are work in progress."}),"\n",(0,t.jsx)(n.h2,{id:"deployed-system-architecture",children:"Deployed System Architecture"}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.img,{alt:"Example Deployed System Architecture",src:i(9009).Z+"",width:"7938",height:"4532"})}),"\n",(0,t.jsx)(n.p,{children:"The figure above shows system components of OpenHouse deployed at LinkedIn. Each component is numbered and its purpose\nis as follows:"}),"\n",(0,t.jsx)(n.p,{children:"[1] Catalog (/Table) service: This is a RESTful web service that exposes tables REST resources. This service is deployed\non a Kubernetes cluster with a fronting Envoy Network Proxy."}),"\n",(0,t.jsx)(n.p,{children:"[2] REST clients: A variety of applications use REST clients to call into table service (#1). Clients include but are\nnot limited to compliance apps, replication apps, data discovery apps like Datahub and IaC, Terraform providers, and\ndata quality checkers. Some of the apps that work on all the tables in OpenHouse are assigned higher privileges."}),"\n",(0,t.jsx)(n.p,{children:"[3] Metastore Catalog: Spark,Trino, andFlink engines are a special flavor of REST clients. An OpenHouse specific\nmetastore catalog implementation allows engines to integrate with OpenHouse tables."}),"\n",(0,t.jsx)(n.p,{children:"[4] House Database (/Table) service: This is an internal service to store table service and data service metadata. This\nservice exposes a key-value interface that is designed to use a NoSQL DB for scale and cost optimization. However the\ndeployed system is currently backed by a MySQL instance, for ease of development and deployment."}),"\n",(0,t.jsx)(n.p,{children:"[5] Managed namespace: This is a managed HDFS namespace where tables are persisted in Iceberg table format. Table\nservice is responsible for setting up the table directory structure with appropriate FileSystem permissioning.\nOpenHouse has a novel HDFS permissioning scheme that makes it possible for any ETL flow to publish directly to Iceberg tables and securely into a managed HDFS namespace."}),"\n",(0,t.jsx)(n.p,{children:"[6] Data services: This is a set of data services that reconciles the user / system declared configuration with the\nsystem observed configuration. This includes use cases such as retention, restatement, and Iceberg-specific maintenance.\nEach maintenance activity is scheduled as a Spark job per table. A Kubernetes cronjob is run periodically on a schedule to trigger a maintenance activity. All the bookkeeping of jobs is done in House Database Service using a jobs metadata table for ease of debugging and monitoring."}),"\n",(0,t.jsx)(n.h2,{id:"pluggable-architecture",children:"Pluggable Architecture"}),"\n",(0,t.jsx)(n.p,{children:"Components of OpenHouse are designed to be pluggable, so that OpenHouse can be deployed in diverse private and public\ncloud environments. This pluggability is available for the following components:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"Storage: OpenHouse supports a Hadoop Filesystem interface, compatible with HDFS and blob stores that support it. Storage\ninterfaces can be augmented to plugin with native blob store APIs."}),"\n",(0,t.jsx)(n.li,{children:"Authentication: OpenHouse supports token-based authentication. Given that token validation varies depending on the\nenvironment, custom implementations can be built according to organizational needs."}),"\n",(0,t.jsx)(n.li,{children:"Authorization: OpenHouse Table Sharing APIs can be extended to suit organizational requirements, covering both metadata\nand data authorization. While we expect implementations to delegate data ACLs to the underlying storage (e.g., POSIX\npermissions for HDFS), for metadata role-based access control, we recommend the use of OPA."}),"\n",(0,t.jsx)(n.li,{children:"Database: OpenHouse utilizes a MySQL database to store metadata pointers for Iceberg table metadata on storage. Choice\nof DB is pluggable, using Spring Data JPA framework, offers flexibility for integration with various database systems."}),"\n",(0,t.jsx)(n.li,{children:"Job Submission: OpenHouse code ships with Apache Livy API for submission of Spark jobs. For custom managed spark services,\njobs services can be extended to trigger spark applications."}),"\n"]}),"\n",(0,t.jsxs)(n.p,{children:["OpenHouse ",(0,t.jsx)(n.a,{href:"https://github.com/linkedin/openhouse/tree/main/cluster/configs/src/main/java/com/linkedin/openhouse/cluster/configs",children:"Cluster Configuration Spec"}),"\nis the place where all the configurations are defined for a particular cluster setup."]})]})}function h(e={}){const{wrapper:n}={...(0,a.a)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(d,{...e})}):d(e)}},1369:(e,n,i)=>{i.d(n,{Z:()=>t});const t=i.p+"assets/images/openhouse-controlplane-91ace254c8643ca21b4dae37692b4299.jpeg"},9009:(e,n,i)=>{i.d(n,{Z:()=>t});const t=i.p+"assets/images/openhouse-deployed-architecture-1bcd512d5ecde3919f2bcc5bdd0e93dd.jpeg"},1151:(e,n,i)=>{i.d(n,{Z:()=>r,a:()=>o});var t=i(7294);const a={},s=t.createContext(a);function o(e){const n=t.useContext(s);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:o(e.components),t.createElement(s.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/19e6b04b.af3848ca.js b/assets/js/19e6b04b.af3848ca.js deleted file mode 100644 index d87da26b..00000000 --- a/assets/js/19e6b04b.af3848ca.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkdocs=self.webpackChunkdocs||[]).push([[1899],{2120:(e,a,t)=>{t.r(a),t.d(a,{assets:()=>s,contentTitle:()=>l,default:()=>p,frontMatter:()=>r,metadata:()=>o,toc:()=>d});var n=t(5893),i=t(1151);const r={title:"Scala",tags:["Spark","Scala","API","OpenHouse"]},l=void 0,o={id:"User Guide/Catalog/Scala",title:"Scala",description:"Data Definition Language (DDL)",source:"@site/docs/User Guide/Catalog/Scala.md",sourceDirName:"User Guide/Catalog",slug:"/User Guide/Catalog/Scala",permalink:"/docs/User Guide/Catalog/Scala",draft:!1,unlisted:!1,tags:[{label:"Spark",permalink:"/docs/tags/spark"},{label:"Scala",permalink:"/docs/tags/scala"},{label:"API",permalink:"/docs/tags/api"},{label:"OpenHouse",permalink:"/docs/tags/open-house"}],version:"current",frontMatter:{title:"Scala",tags:["Spark","Scala","API","OpenHouse"]},sidebar:"docsSidebar",previous:{title:"SQL",permalink:"/docs/User Guide/Catalog/SQL"},next:{title:"Spec",permalink:"/docs/User Guide/Catalog/TableSpec"}},s={},d=[{value:"Data Definition Language (DDL)",id:"data-definition-language-ddl",level:2},{value:"Reads",id:"reads",level:2},{value:"With Time-Travel",id:"with-time-travel",level:3},{value:"Writes",id:"writes",level:2},{value:"Create Table",id:"create-table",level:3},{value:"Create Partitioned Table",id:"create-partitioned-table",level:3},{value:"Append Data to Partitioned Table",id:"append-data-to-partitioned-table",level:3},{value:"Overwrite Data",id:"overwrite-data",level:3}];function c(e){const a={a:"a",admonition:"admonition",code:"code",h2:"h2",h3:"h3",p:"p",pre:"pre",...(0,i.a)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(a.h2,{id:"data-definition-language-ddl",children:"Data Definition Language (DDL)"}),"\n",(0,n.jsxs)(a.p,{children:["For DDLs such as ",(0,n.jsx)(a.code,{children:"CREATE TABLE"}),", ",(0,n.jsx)(a.code,{children:"ALTER TABLE"}),", ",(0,n.jsx)(a.code,{children:"GRANT/REVOKE"})," etc; use ",(0,n.jsx)(a.code,{children:".sql()"})," in SparkSession. Native Scala APIs for achieving those outcomes aren't available currently."]}),"\n",(0,n.jsx)(a.pre,{children:(0,n.jsx)(a.code,{className:"language-scala",children:"-- Create Table\nspark.sql(\"CREATE TABLE openhouse.db.table (id bigint COMMENT 'unique id', data string)\")\n\n-- Alter Table\nspark.sql(\"\"\"ALTER TABLE openhouse.db.table SET TBLPROPERTIES (\n 'key1' = 'value1',\n 'key2' = 'value2'\n)\"\"\")\n\n-- Grant Select\nspark.sql(\"GRANT SELECT ON TABLE openhouse.db.table TO ;\")\n"})}),"\n",(0,n.jsx)(a.p,{children:(0,n.jsx)(a.a,{href:"/docs/User%20Guide/Catalog/SQL#data-definition-language-ddl",children:"See all available DDL commands here."})}),"\n",(0,n.jsx)(a.h2,{id:"reads",children:"Reads"}),"\n",(0,n.jsx)(a.p,{children:"To query a table, run the following:"}),"\n",(0,n.jsx)(a.pre,{children:(0,n.jsx)(a.code,{className:"language-scala",children:'val df = spark.table("openhouse.db.table")\n'})}),"\n",(0,n.jsx)(a.p,{children:"You can also filter data using custom filters as follows:"}),"\n",(0,n.jsx)(a.pre,{children:(0,n.jsx)(a.code,{className:"language-scala",children:'val filtered_df = df.filter(col("datepartition") > "2022-05-10")\n'})}),"\n",(0,n.jsx)(a.h3,{id:"with-time-travel",children:"With Time-Travel"}),"\n",(0,n.jsxs)(a.p,{children:["Identify older snapshot you want to read, by ",(0,n.jsx)(a.a,{href:"/docs/User%20Guide/Catalog/SQL#inspecting-metadata",children:"Inspecting Metadata"}),". Then run the following:"]}),"\n",(0,n.jsx)(a.pre,{children:(0,n.jsx)(a.code,{className:"language-scala",children:'spark.read.option("snapshot-id", 1031031135387001532L).table("openhouse.db.table")\n'})}),"\n",(0,n.jsx)(a.h2,{id:"writes",children:"Writes"}),"\n",(0,n.jsx)(a.p,{children:"We highly recommend users adopt Apache Spark\u2019s new DataFrameWriterV2 API in Spark 3 when programming with DataFrame API."}),"\n",(0,n.jsx)(a.p,{children:"The following are example Scala statements in Spark 3 to write to a partitioned table."}),"\n",(0,n.jsx)(a.h3,{id:"create-table",children:"Create Table"}),"\n",(0,n.jsx)(a.pre,{children:(0,n.jsx)(a.code,{className:"language-scala",children:'import org.apache.spark.sql.functions;\n\n// Your code preparing DataFrame\n \ndf.writeTo("openhouse.db.table").create()\n'})}),"\n",(0,n.jsx)(a.h3,{id:"create-partitioned-table",children:"Create Partitioned Table"}),"\n",(0,n.jsx)(a.pre,{children:(0,n.jsx)(a.code,{className:"language-scala",children:'import org.apache.spark.sql.functions;\n \n// Your code to create a table through existing data frame.\n \ndf.sortWithinPartitions("datepartition")\n.writeTo("openhouse.db.table")\n.partitionedBy(functions.col("datepartition"))\n.create()\n'})}),"\n",(0,n.jsx)(a.h3,{id:"append-data-to-partitioned-table",children:"Append Data to Partitioned Table"}),"\n",(0,n.jsx)(a.pre,{children:(0,n.jsx)(a.code,{className:"language-scala",children:'append_df.sortWithinPartitions("datepartition")\n.writeTo("openhouse.db.table")\n.append()\n'})}),"\n",(0,n.jsx)(a.h3,{id:"overwrite-data",children:"Overwrite Data"}),"\n",(0,n.jsx)(a.pre,{children:(0,n.jsx)(a.code,{className:"language-scala",children:'// You can dynamically overwrite partitions, which means\n// any partitions with at least one row matched will be overwritten.\n// To make overwritePartitions work for table-overwrite:\n \noverwrite_df.sortWithinPartitions("datepartition")\n.writeTo("openhouse.db.table")\n.overwritePartitions()\n \n \n// To explicitly overwrite, use the following\noverwrite_df.sortWithinPartitions("datepartition")\n.writeTo("openhouse.db.table")\n.overwrite($"level" === "INFO")\n'})}),"\n",(0,n.jsx)(a.admonition,{type:"note",children:(0,n.jsxs)(a.p,{children:["Note that explicit sort is necessary in partition-write because Spark doesn\u2019t allow Iceberg to request a sort before writing as of Spark 3.0. ",(0,n.jsx)(a.a,{href:"https://iceberg.apache.org/docs/latest/spark-writes/#writing-to-partitioned-tables",children:"See more at link"}),"."]})})]})}function p(e={}){const{wrapper:a}={...(0,i.a)(),...e.components};return a?(0,n.jsx)(a,{...e,children:(0,n.jsx)(c,{...e})}):c(e)}},1151:(e,a,t)=>{t.d(a,{Z:()=>o,a:()=>l});var n=t(7294);const i={},r=n.createContext(i);function l(e){const a=n.useContext(r);return n.useMemo((function(){return"function"==typeof e?e(a):{...a,...e}}),[a,e])}function o(e){let a;return a=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:l(e.components),n.createElement(r.Provider,{value:a},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/19e6b04b.c61fb0cc.js b/assets/js/19e6b04b.c61fb0cc.js new file mode 100644 index 00000000..075a9b24 --- /dev/null +++ b/assets/js/19e6b04b.c61fb0cc.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs=self.webpackChunkdocs||[]).push([[1899],{2120:(e,a,t)=>{t.r(a),t.d(a,{assets:()=>l,contentTitle:()=>o,default:()=>p,frontMatter:()=>i,metadata:()=>s,toc:()=>d});var n=t(5893),r=t(1151);const i={title:"Scala",tags:["Spark","Scala","API","OpenHouse","Iceberg"]},o=void 0,s={id:"User Guide/Catalog/Scala",title:"Scala",description:"Data Definition Language (DDL)",source:"@site/docs/User Guide/Catalog/Scala.md",sourceDirName:"User Guide/Catalog",slug:"/User Guide/Catalog/Scala",permalink:"/docs/User Guide/Catalog/Scala",draft:!1,unlisted:!1,tags:[{label:"Spark",permalink:"/docs/tags/spark"},{label:"Scala",permalink:"/docs/tags/scala"},{label:"API",permalink:"/docs/tags/api"},{label:"OpenHouse",permalink:"/docs/tags/open-house"},{label:"Iceberg",permalink:"/docs/tags/iceberg"}],version:"current",frontMatter:{title:"Scala",tags:["Spark","Scala","API","OpenHouse","Iceberg"]},sidebar:"docsSidebar",previous:{title:"SQL",permalink:"/docs/User Guide/Catalog/SQL"},next:{title:"Spec",permalink:"/docs/User Guide/Catalog/TableSpec"}},l={},d=[{value:"Data Definition Language (DDL)",id:"data-definition-language-ddl",level:2},{value:"Reads",id:"reads",level:2},{value:"With Time-Travel",id:"with-time-travel",level:3},{value:"Writes",id:"writes",level:2},{value:"Create Table",id:"create-table",level:3},{value:"Create Partitioned Table",id:"create-partitioned-table",level:3},{value:"Append Data to Partitioned Table",id:"append-data-to-partitioned-table",level:3},{value:"Overwrite Data",id:"overwrite-data",level:3}];function c(e){const a={a:"a",admonition:"admonition",code:"code",h2:"h2",h3:"h3",p:"p",pre:"pre",...(0,r.a)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(a.h2,{id:"data-definition-language-ddl",children:"Data Definition Language (DDL)"}),"\n",(0,n.jsxs)(a.p,{children:["OpenHouse tables supports ",(0,n.jsx)(a.a,{href:"https://iceberg.apache.org/",children:"Apache Iceberg"})," as the underlying table format. You can use native\nSpark syntax to create, alter, and drop tables, but do note there are some constraints OpenHouse imposes."]}),"\n",(0,n.jsxs)(a.p,{children:["For DDLs such as ",(0,n.jsx)(a.code,{children:"CREATE TABLE"}),", ",(0,n.jsx)(a.code,{children:"ALTER TABLE"}),", ",(0,n.jsx)(a.code,{children:"GRANT/REVOKE"})," etc; use ",(0,n.jsx)(a.code,{children:".sql()"})," in SparkSession. You can also use\nnative Spark Scala syntax that creates table if not exists."]}),"\n",(0,n.jsx)(a.pre,{children:(0,n.jsx)(a.code,{className:"language-sql",children:'import org.apache.spark.sql.functions;\n \n// Your code preparing DataFrame\n \ndf.writeTo("openhouse..").create()\n'})}),"\n",(0,n.jsx)(a.p,{children:(0,n.jsx)(a.a,{href:"/docs/User%20Guide/Catalog/SQL#data-definition-language-ddl",children:"SQL DDL commands"})}),"\n",(0,n.jsx)(a.h2,{id:"reads",children:"Reads"}),"\n",(0,n.jsx)(a.p,{children:"To query a table, run the following:"}),"\n",(0,n.jsx)(a.pre,{children:(0,n.jsx)(a.code,{className:"language-sql",children:'val df = spark.table("openhouse.db.table")\n'})}),"\n",(0,n.jsx)(a.p,{children:"You can also filter data using custom filters as follows:"}),"\n",(0,n.jsx)(a.pre,{children:(0,n.jsx)(a.code,{className:"language-sql",children:'val filtered_df = df.filter(col("datepartition") > "2022-05-10")\n'})}),"\n",(0,n.jsx)(a.h3,{id:"with-time-travel",children:"With Time-Travel"}),"\n",(0,n.jsxs)(a.p,{children:["Identify older snapshot you want to read, by ",(0,n.jsx)(a.a,{href:"/docs/User%20Guide/Catalog/SQL#inspecting-metadata",children:"Inspecting Metadata"}),". Then run the following:"]}),"\n",(0,n.jsx)(a.pre,{children:(0,n.jsx)(a.code,{className:"language-scala",children:'spark.read.option("snapshot-id", 1031031135387001532L).table("openhouse.db.table")\n'})}),"\n",(0,n.jsx)(a.h2,{id:"writes",children:"Writes"}),"\n",(0,n.jsx)(a.p,{children:"We highly recommend users adopt Apache Spark\u2019s new DataFrameWriterV2 API in Spark 3 when programming with DataFrame API."}),"\n",(0,n.jsx)(a.p,{children:"The following are example Scala statements in Spark 3 to write to a partitioned table."}),"\n",(0,n.jsx)(a.h3,{id:"create-table",children:"Create Table"}),"\n",(0,n.jsx)(a.pre,{children:(0,n.jsx)(a.code,{className:"language-scala",children:'import org.apache.spark.sql.functions;\n\n// Your code preparing DataFrame\n \ndf.writeTo("openhouse.db.table").create()\n'})}),"\n",(0,n.jsx)(a.h3,{id:"create-partitioned-table",children:"Create Partitioned Table"}),"\n",(0,n.jsx)(a.pre,{children:(0,n.jsx)(a.code,{className:"language-scala",children:'import org.apache.spark.sql.functions;\n \n// Your code to create a table through existing data frame.\n \ndf.sortWithinPartitions("datepartition")\n.writeTo("openhouse.db.table")\n.partitionedBy(functions.col("datepartition"))\n.create()\n'})}),"\n",(0,n.jsx)(a.h3,{id:"append-data-to-partitioned-table",children:"Append Data to Partitioned Table"}),"\n",(0,n.jsx)(a.pre,{children:(0,n.jsx)(a.code,{className:"language-scala",children:'append_df.sortWithinPartitions("datepartition")\n.writeTo("openhouse.db.table")\n.append()\n'})}),"\n",(0,n.jsx)(a.h3,{id:"overwrite-data",children:"Overwrite Data"}),"\n",(0,n.jsx)(a.pre,{children:(0,n.jsx)(a.code,{className:"language-scala",children:'// You can dynamically overwrite partitions, which means\n// any partitions with at least one row matched will be overwritten.\n// To make overwritePartitions work for table-overwrite:\n \noverwrite_df.sortWithinPartitions("datepartition")\n.writeTo("openhouse.db.table")\n.overwritePartitions()\n \n \n// To explicitly overwrite, use the following\noverwrite_df.sortWithinPartitions("datepartition")\n.writeTo("openhouse.db.table")\n.overwrite($"level" === "INFO")\n'})}),"\n",(0,n.jsx)(a.admonition,{type:"note",children:(0,n.jsxs)(a.p,{children:["Note that explicit sort is necessary in partition-write because Spark doesn\u2019t allow Iceberg to request a sort before writing as of Spark 3.0. ",(0,n.jsx)(a.a,{href:"https://iceberg.apache.org/docs/latest/spark-writes/#writing-to-partitioned-tables",children:"See more at link"}),"."]})})]})}function p(e={}){const{wrapper:a}={...(0,r.a)(),...e.components};return a?(0,n.jsx)(a,{...e,children:(0,n.jsx)(c,{...e})}):c(e)}},1151:(e,a,t)=>{t.d(a,{Z:()=>s,a:()=>o});var n=t(7294);const r={},i=n.createContext(r);function o(e){const a=n.useContext(i);return n.useMemo((function(){return"function"==typeof e?e(a):{...a,...e}}),[a,e])}function s(e){let a;return a=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:o(e.components),n.createElement(i.Provider,{value:a},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/55960ee5.170abfb5.js b/assets/js/55960ee5.170abfb5.js deleted file mode 100644 index bb68652f..00000000 --- a/assets/js/55960ee5.170abfb5.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkdocs=self.webpackChunkdocs||[]).push([[4121],{8070:a=>{a.exports=JSON.parse('[{"label":"Spark","permalink":"/docs/tags/spark","count":2},{"label":"Scala","permalink":"/docs/tags/scala","count":1},{"label":"API","permalink":"/docs/tags/api","count":4},{"label":"OpenHouse","permalink":"/docs/tags/open-house","count":2},{"label":"SQL","permalink":"/docs/tags/sql","count":1},{"label":"Table","permalink":"/docs/tags/table","count":1},{"label":"Service","permalink":"/docs/tags/service","count":2},{"label":"OpenAPI","permalink":"/docs/tags/open-api","count":2},{"label":"Spec","permalink":"/docs/tags/spec","count":2},{"label":"Jobs","permalink":"/docs/tags/jobs","count":1}]')}}]); \ No newline at end of file diff --git a/assets/js/55960ee5.d673555c.js b/assets/js/55960ee5.d673555c.js new file mode 100644 index 00000000..fede8b67 --- /dev/null +++ b/assets/js/55960ee5.d673555c.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs=self.webpackChunkdocs||[]).push([[4121],{8070:e=>{e.exports=JSON.parse('[{"label":"Spark","permalink":"/docs/tags/spark","count":2},{"label":"Scala","permalink":"/docs/tags/scala","count":1},{"label":"API","permalink":"/docs/tags/api","count":4},{"label":"OpenHouse","permalink":"/docs/tags/open-house","count":2},{"label":"Iceberg","permalink":"/docs/tags/iceberg","count":2},{"label":"SQL","permalink":"/docs/tags/sql","count":1},{"label":"Table","permalink":"/docs/tags/table","count":1},{"label":"Service","permalink":"/docs/tags/service","count":2},{"label":"OpenAPI","permalink":"/docs/tags/open-api","count":2},{"label":"Spec","permalink":"/docs/tags/spec","count":2},{"label":"Jobs","permalink":"/docs/tags/jobs","count":1}]')}}]); \ No newline at end of file diff --git a/assets/js/8c8650e1.72fb38c3.js b/assets/js/8c8650e1.72fb38c3.js new file mode 100644 index 00000000..3aaace83 --- /dev/null +++ b/assets/js/8c8650e1.72fb38c3.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs=self.webpackChunkdocs||[]).push([[3279],{7161:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>o,contentTitle:()=>r,default:()=>h,frontMatter:()=>l,metadata:()=>i,toc:()=>d});var a=s(5893),t=s(1151);const l={title:"SQL",tags:["Spark","SQL","API","OpenHouse","Iceberg"]},r=void 0,i={id:"User Guide/Catalog/SQL",title:"SQL",description:"Data Definition Language (DDL)",source:"@site/docs/User Guide/Catalog/SQL.md",sourceDirName:"User Guide/Catalog",slug:"/User Guide/Catalog/SQL",permalink:"/docs/User Guide/Catalog/SQL",draft:!1,unlisted:!1,tags:[{label:"Spark",permalink:"/docs/tags/spark"},{label:"SQL",permalink:"/docs/tags/sql"},{label:"API",permalink:"/docs/tags/api"},{label:"OpenHouse",permalink:"/docs/tags/open-house"},{label:"Iceberg",permalink:"/docs/tags/iceberg"}],version:"current",frontMatter:{title:"SQL",tags:["Spark","SQL","API","OpenHouse","Iceberg"]},sidebar:"docsSidebar",previous:{title:"User Guide",permalink:"/docs/category/user-guide"},next:{title:"Scala",permalink:"/docs/User Guide/Catalog/Scala"}},o={},d=[{value:"Data Definition Language (DDL)",id:"data-definition-language-ddl",level:2},{value:"CREATE TABLE",id:"create-table",level:3},{value:"PARTITIONED BY",id:"partitioned-by",level:4},{value:"TBLPROPERTIES",id:"tblproperties",level:4},{value:"CREATE TABLE AS SELECT (CTAS)",id:"create-table-as-select-ctas",level:4},{value:"REFRESH TABLE",id:"refresh-table",level:3},{value:"DROP TABLE",id:"drop-table",level:3},{value:"ALTER TABLE",id:"alter-table",level:3},{value:"ALTER TABLE ... SET TBLPROPERTIES",id:"alter-table--set-tblproperties",level:4},{value:"ALTER TABLE ... ADD COLUMN",id:"alter-table--add-column",level:4},{value:"ALTER TABLE ... ALTER COLUMN",id:"alter-table--alter-column",level:4},{value:"GRANT/ REVOKE",id:"grant-revoke",level:3},{value:"ALTER TABLE SET POLICY (SHARING=)",id:"alter-table-set-policy-sharing",level:4},{value:"GRANT/ REVOKE SELECT ON TABLE",id:"grant-revoke-select-on-table",level:4},{value:"GRANT/ REVOKE MANAGE GRANTS ON TABLE",id:"grant-revoke-manage-grants-on-table",level:4},{value:"GRANT/REVOKE CREATE TABLE ON DATABASE",id:"grantrevoke-create-table-on-database",level:4},{value:"SHOW GRANTS ON TABLE/DATABASE",id:"show-grants-on-tabledatabase",level:4},{value:"Reads",id:"reads",level:2},{value:"SELECT FROM",id:"select-from",level:3},{value:"SELECT FROM w/ Time-Travel",id:"select-from-w-time-travel",level:3},{value:"Writes",id:"writes",level:2},{value:"INSERT INTO",id:"insert-into",level:3},{value:"DELETE FROM",id:"delete-from",level:3},{value:"INSERT OVERWRITE",id:"insert-overwrite",level:3},{value:"UPDATE",id:"update",level:3},{value:"MERGE INTO",id:"merge-into",level:3},{value:"Inspecting Metadata",id:"inspecting-metadata",level:2},{value:"List Partitions",id:"list-partitions",level:3},{value:"List Snapshots",id:"list-snapshots",level:3},{value:"Unsupported Operations",id:"unsupported-operations",level:2}];function c(e){const n={a:"a",admonition:"admonition",code:"code",h2:"h2",h3:"h3",h4:"h4",li:"li",ol:"ol",p:"p",pre:"pre",ul:"ul",...(0,t.a)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(n.h2,{id:"data-definition-language-ddl",children:"Data Definition Language (DDL)"}),"\n",(0,a.jsxs)(n.p,{children:["OpenHouse tables supports ",(0,a.jsx)(n.a,{href:"https://iceberg.apache.org/",children:"Apache Iceberg"})," as the underlying table format. You can use native\nSpark syntax to create, alter, and drop tables, but do note there are some constraints OpenHouse imposes."]}),"\n",(0,a.jsx)(n.h3,{id:"create-table",children:"CREATE TABLE"}),"\n",(0,a.jsx)(n.p,{children:"To create an OpenHouse table, run following SQL in Spark."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sql",children:"CREATE TABLE openhouse.db.table (id bigint COMMENT 'unique id', data string);\n"})}),"\n",(0,a.jsx)(n.p,{children:"OpenHouse supports following Create clauses:"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:(0,a.jsx)(n.code,{children:"PARTITIONED BY"})}),"\n",(0,a.jsx)(n.li,{children:(0,a.jsx)(n.code,{children:"TBLPROPERTIES (\u2018key\u2019=\u2019value\u2019,..)"})}),"\n"]}),"\n",(0,a.jsxs)(n.p,{children:["List of supported DataTypes are the same as found in ",(0,a.jsx)(n.a,{href:"https://iceberg.apache.org/docs/latest/spark-writes/#spark-type-to-iceberg-type",children:"Iceberg Spark Types"}),"."]}),"\n",(0,a.jsxs)(n.admonition,{type:"warning",children:[(0,a.jsx)(n.p,{children:"OpenHouse does not support following Create clauses:"}),(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:(0,a.jsx)(n.code,{children:"LOCATION (*)"})}),"\n",(0,a.jsx)(n.li,{children:(0,a.jsx)(n.code,{children:"CLUSTERED BY (*)"})}),"\n",(0,a.jsx)(n.li,{children:(0,a.jsx)(n.code,{children:"COMMENT \u2018table documentation\u2019"})}),"\n"]})]}),"\n",(0,a.jsx)(n.h4,{id:"partitioned-by",children:"PARTITIONED BY"}),"\n",(0,a.jsx)(n.p,{children:"OpenHouse supports single timestamp column to be specified in the partitioning scheme. It also supports upto three string or integer type column based partitioning scheme.\nTo partition your table, you can use the following SQL syntax"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sql",children:"CREATE TABLE openhouse.db.table(datepartition string, epoch_ts timestamp)\nPARTITIONED BY (\n days(epoch_ts),\n datepartition\n)\n"})}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.code,{children:"days(epoch_ts)"}),': partitions data by applying day-granularity on the timestamp-type column "epoch_ts".']}),"\n"]}),"\n",(0,a.jsx)(n.p,{children:"Other granularities supported are:"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.code,{children:"years(epoch_ts)"}),": partition by year"]}),"\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.code,{children:"months(epoch_ts)"}),": partition by month"]}),"\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.code,{children:"hours(epoch_ts)"}),": partition by hour"]}),"\n"]}),"\n",(0,a.jsxs)(n.p,{children:["You can also partition your data based on string column by using identity partitioning (for example: ",(0,a.jsx)(n.code,{children:"datepartition"}),")."]}),"\n",(0,a.jsx)(n.admonition,{type:"warning",children:(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"Iceberg transforms such as bucket, truncate are not supported on timestamp column."}),"\n",(0,a.jsx)(n.li,{children:"No transformation is supported on string or integer type partition column."}),"\n"]})}),"\n",(0,a.jsx)(n.h4,{id:"tblproperties",children:"TBLPROPERTIES"}),"\n",(0,a.jsx)(n.p,{children:"To set table properties, you can use the following SQL syntax"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sql",children:"CREATE TABLE openhouse.db.table(\n data string\n)\nTBLPROPERTIES (\n 'key'='value',\n ...\n);\n"})}),"\n",(0,a.jsx)(n.admonition,{type:"warning",children:(0,a.jsxs)(n.p,{children:["Keys with the prefix \u201copenhouse.\u201d (for example: \u201copenhouse.tableId\u201d) are preserved and cannot be set/modified.\nAdditionally, all Iceberg ",(0,a.jsx)(n.a,{href:"https://github.com/apache/iceberg/blob/master/core/src/main/java/org/apache/iceberg/TableProperties.java",children:"TableProperties"}),"\nare also preserved.\nCatalog service has the ability to set these preserved properties as it finds suit."]})}),"\n",(0,a.jsx)(n.h4,{id:"create-table-as-select-ctas",children:"CREATE TABLE AS SELECT (CTAS)"}),"\n",(0,a.jsx)(n.p,{children:"To create an OpenHouse table with some data, run following SQL in Spark."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sql",children:"CREATE TABLE openhouse.db.table\nAS\nSELECT * FROM hive.srcDb.srcTable WHERE data = 'v1';\n"})}),"\n",(0,a.jsx)(n.admonition,{type:"warning",children:(0,a.jsxs)(n.p,{children:[(0,a.jsx)(n.code,{children:"Create table like tableName"})," is not supported. You can use ",(0,a.jsx)(n.code,{children:"create table A as select * from B limit 0"})," to achieve same effect"]})}),"\n",(0,a.jsx)(n.h3,{id:"refresh-table",children:"REFRESH TABLE"}),"\n",(0,a.jsx)(n.p,{children:"Upon reading a table, its state is cached in your session. In order to read the new state of the table:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sql",children:"REFRESH TABLE openhouse.db.table;\n"})}),"\n",(0,a.jsx)(n.h3,{id:"drop-table",children:"DROP TABLE"}),"\n",(0,a.jsx)(n.p,{children:"To delete table\u2019s data and metadata, run:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sql",children:"DROP TABLE openhouse.db.table;\n"})}),"\n",(0,a.jsx)(n.h3,{id:"alter-table",children:"ALTER TABLE"}),"\n",(0,a.jsx)(n.p,{children:"OpenHouse supports following ALTER statements"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"Setting or removing table properties."}),"\n",(0,a.jsxs)(n.li,{children:["Schema Evolution:","\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"Adding columns in both top and nested level."}),"\n",(0,a.jsx)(n.li,{children:"Widening the type of int, float, and decimal fields."}),"\n",(0,a.jsx)(n.li,{children:"Making required columns optional."}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,a.jsxs)(n.admonition,{type:"warning",children:[(0,a.jsx)(n.p,{children:"OpenHouse doesn\u2019t allow the following:"}),(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"Schema evolution: Drop, rename and reordering."}),"\n",(0,a.jsx)(n.li,{children:"Renaming a table."}),"\n",(0,a.jsx)(n.li,{children:"Adding, removing, and changing partitioning."}),"\n",(0,a.jsxs)(n.li,{children:["Other iceberg alters such as: ",(0,a.jsx)(n.code,{children:"write ordered by"})," / ",(0,a.jsx)(n.code,{children:"write distributed by"})]}),"\n"]})]}),"\n",(0,a.jsx)(n.h4,{id:"alter-table--set-tblproperties",children:"ALTER TABLE ... SET TBLPROPERTIES"}),"\n",(0,a.jsx)(n.p,{children:"To set table properties, you can use the following SQL syntax"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sql",children:"ALTER TABLE openhouse.db.table SET TBLPROPERTIES (\n 'key1' = 'value1',\n 'key2' = 'value2'\n)\n"})}),"\n",(0,a.jsx)(n.p,{children:"To unset table properties, you can use the following SQL syntax"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sql",children:"ALTER TABLE openhouse.db.table UNSET TBLPROPERTIES ('key1', 'key2')\n"})}),"\n",(0,a.jsx)(n.admonition,{type:"warning",children:(0,a.jsxs)(n.p,{children:["Keys with the prefix \u201copenhouse.\u201d (for example: \u201copenhouse.tableId\u201d) are preserved and cannot be set/modified.\nAdditionally, all Iceberg ",(0,a.jsx)(n.a,{href:"https://github.com/apache/iceberg/blob/master/core/src/main/java/org/apache/iceberg/TableProperties.java",children:"TableProperties"})," are also preserved.\nCatalog service has the ability to set these preserved properties as it finds suit."]})}),"\n",(0,a.jsx)(n.h4,{id:"alter-table--add-column",children:"ALTER TABLE ... ADD COLUMN"}),"\n",(0,a.jsx)(n.p,{children:"Adding column is a supported schema evolution, to add a new column:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sql",children:"ALTER TABLE openhouse.db.table\nADD COLUMNS (\n new_column string comment 'new_column docs'\n)\n"})}),"\n",(0,a.jsx)(n.p,{children:"Multiple columns can be added separated by comma.\nNested columns can be added as follows:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sql",children:"-- create a struct column\nALTER TABLE openhouse.db.table\nADD COLUMN point struct;\n \n-- add a field to the struct\nALTER TABLE openhouse.db.table\nADD COLUMN point.z double\n"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sql",children:"-- create a nested array column of struct\nALTER TABLE openhouse.db.table\nADD COLUMN points array>;\n \n-- add a field to the struct within an array. Using keyword 'element' to access the array's element column.\nALTER TABLE openhouse.db.table\nADD COLUMN points.element.z double\n"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sql",children:"-- create a map column of struct key and struct value\nALTER TABLE openhouse.db.table\nADD COLUMN point_map map, struct>;\n \n-- add a field to the value struct in a map. Using keyword 'value' to access the map's value column.\nALTER TABLE openhouse.db.table\nADD COLUMN point_map.value.b int\n \n-- Altering 'key' struct is not allowed. Only map 'value' can be updated.\n"})}),"\n",(0,a.jsx)(n.h4,{id:"alter-table--alter-column",children:"ALTER TABLE ... ALTER COLUMN"}),"\n",(0,a.jsx)(n.p,{children:"Alter column is used for:"}),"\n",(0,a.jsxs)(n.ol,{children:["\n",(0,a.jsxs)(n.li,{children:["Type widening, OpenHouse supports ",(0,a.jsx)(n.code,{children:"int to bigint"}),", ",(0,a.jsx)(n.code,{children:"float to double"})]}),"\n"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sql",children:"ALTER TABLE openhouse.db.table ALTER COLUMN measurement TYPE double;\n"})}),"\n",(0,a.jsxs)(n.ol,{start:"2",children:["\n",(0,a.jsx)(n.li,{children:"Setting column comments"}),"\n"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sql",children:"ALTER TABLE openhouse.db.table ALTER COLUMN measurement COMMENT 'unit is kilobytes per second';\n"})}),"\n",(0,a.jsxs)(n.ol,{start:"3",children:["\n",(0,a.jsx)(n.li,{children:"Make field optional"}),"\n"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sql",children:"ALTER TABLE openhouse.db.table ALTER COLUMN id DROP NOT NULL;\n"})}),"\n",(0,a.jsx)(n.h3,{id:"grant-revoke",children:"GRANT/ REVOKE"}),"\n",(0,a.jsx)(n.p,{children:"Tables and databases in OpenHouse are access controlled by its own RBAC system, to perform any operation you need to have the right privilege."}),"\n",(0,a.jsx)(n.h4,{id:"alter-table-set-policy-sharing",children:"ALTER TABLE SET POLICY (SHARING=)"}),"\n",(0,a.jsx)(n.p,{children:"To make your table sharable, run the following command:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sql",children:"ALTER TABLE openhouse.db.table SET POLICY (SHARING=TRUE);\n"})}),"\n",(0,a.jsx)(n.admonition,{type:"note",children:(0,a.jsxs)(n.p,{children:["Trying to share a table without running this command will throw the error: ",(0,a.jsx)(n.code,{children:"db.table"})," is not a shared table"]})}),"\n",(0,a.jsx)(n.h4,{id:"grant-revoke-select-on-table",children:"GRANT/ REVOKE SELECT ON TABLE"}),"\n",(0,a.jsx)(n.p,{children:"As a TABLE_ADMIN you can grant another user TABLE_VIEWER role by running the SQL:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sql",children:"GRANT SELECT ON TABLE openhouse.db.table TO ;\n"})}),"\n",(0,a.jsx)(n.p,{children:"To revoke the privilege:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sql",children:"REVOKE SELECT ON TABLE openhouse.db.table FROM ;\n"})}),"\n",(0,a.jsx)(n.h4,{id:"grant-revoke-manage-grants-on-table",children:"GRANT/ REVOKE MANAGE GRANTS ON TABLE"}),"\n",(0,a.jsx)(n.p,{children:"As a ACL_EDITOR / TABLE_ADMIN, In order to grant sharing rights on your table to other users, you can make them ACL_EDITOR by running the SQL:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sql",children:"GRANT MANAGE GRANTS ON TABLE openhouse.db.table TO ;\n"})}),"\n",(0,a.jsx)(n.p,{children:"To revoke:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sql",children:"REVOKE MANAGE GRANTS ON TABLE openhouse.db.table FROM ;\n"})}),"\n",(0,a.jsx)(n.h4,{id:"grantrevoke-create-table-on-database",children:"GRANT/REVOKE CREATE TABLE ON DATABASE"}),"\n",(0,a.jsx)(n.p,{children:"As a ACL_EDITOR role of database you can grant TABLE_CREATOR role to whoever wants to create a table in your database."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sql",children:"GRANT CREATE TABLE ON DATABASE openhouse.db TO ;\n"})}),"\n",(0,a.jsx)(n.p,{children:"To revoke:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sql",children:"REVOKE CREATE TABLE ON DATABASE openhouse.db FROM ;\n"})}),"\n",(0,a.jsx)(n.h4,{id:"show-grants-on-tabledatabase",children:"SHOW GRANTS ON TABLE/DATABASE"}),"\n",(0,a.jsx)(n.p,{children:"In order to view granted privileges:"}),"\n",(0,a.jsx)(n.p,{children:"For Table:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sql",children:"SHOW GRANTS ON TABLE openhouse.db.table;\n"})}),"\n",(0,a.jsx)(n.p,{children:"For Database:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sql",children:"SHOW GRANTS ON DATABASE openhouse.db;\n"})}),"\n",(0,a.jsx)(n.h2,{id:"reads",children:"Reads"}),"\n",(0,a.jsx)(n.h3,{id:"select-from",children:"SELECT FROM"}),"\n",(0,a.jsxs)(n.p,{children:["OpenHouse supports ANSI SQL for SELECT statements. For complete syntax see ",(0,a.jsx)(n.a,{href:"https://spark.apache.org/docs/latest/sql-ref-syntax-qry-select.html",children:"Spark SELECT syntax"}),"."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sql",children:"SELECT * FROM openhouse.db.table;\n"})}),"\n",(0,a.jsx)(n.admonition,{type:"note",children:(0,a.jsxs)(n.p,{children:["Note: response of the table is cached for the duration of the session. In order to refresh the cache, please run\n",(0,a.jsx)(n.code,{children:"REFRESH TABLE"})]})}),"\n",(0,a.jsx)(n.h3,{id:"select-from-w-time-travel",children:"SELECT FROM w/ Time-Travel"}),"\n",(0,a.jsx)(n.p,{children:"OpenHouse uses Iceberg as the table format. Iceberg generates a version/snapshot for every update to the table. A\nsnapshot captures the state of the table at a specific point in time. We can query iceberg tables using the snapshot ID\nor timestamp from the past. Unlike Hive, Iceberg guarantees query reproducibility when querying historical data."}),"\n",(0,a.jsx)(n.p,{children:"Time-travel is supported through following syntax."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sql",children:'-- suffix with "at_timestamp" string and epoch time in milliseconds.\nSELECT * FROM openhouse.db.table.at_timestamp_1686699440000;\n \n-- standard sql dialect for this time-travel is NOT supported\nSELECT * FROM openhouse.db.table FOR SYSTEM_TIME AS OF 1686699440000;\n'})}),"\n",(0,a.jsx)(n.p,{children:"Querying a older version of a table is supported through following syntax."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sql",children:'-- suffix with "snapshot_id" string followed by the ID of snapshot or version.\nSELECT * FROM openhouse.db.table.snapshot_id_821787972099903997;\n \n-- standard sql dialect for this version query is NOT supported\nSELECT * FROM openhouse.db.table FOR SYSTEM_VERSION AS OF 821787972099903997;\n'})}),"\n",(0,a.jsx)(n.h2,{id:"writes",children:"Writes"}),"\n",(0,a.jsx)(n.h3,{id:"insert-into",children:"INSERT INTO"}),"\n",(0,a.jsx)(n.p,{children:"OpenHouse supports standard ANSI SQL for INSERT statements."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sql",children:"INSERT INTO openhouse.db.table VALUES (1, 'a'), (2, 'b');\n"})}),"\n",(0,a.jsx)(n.h3,{id:"delete-from",children:"DELETE FROM"}),"\n",(0,a.jsx)(n.p,{children:"Where clause is used to delete rows"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sql",children:"DELETE FROM openhouse.db.table WHERE ts >= '2020-05-01 00:00:00' and ts < '2020-06-01 00:00:00';\n"})}),"\n",(0,a.jsx)(n.h3,{id:"insert-overwrite",children:"INSERT OVERWRITE"}),"\n",(0,a.jsx)(n.p,{children:"Insert overwrite replaces the partitions in the target table that contains rows from the SELECT query."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sql",children:"INSERT OVERWRITE openhouse.db.table SELECT uuid, ts\nFROM anyCatalog.db.another_table\nWHERE cast(ts as date) = '2020-07-01'\n"})}),"\n",(0,a.jsx)(n.admonition,{type:"danger",children:(0,a.jsx)(n.p,{children:"If the table is unpartitioned the whole table data will be replaced."})}),"\n",(0,a.jsx)(n.h3,{id:"update",children:"UPDATE"}),"\n",(0,a.jsxs)(n.p,{children:["You can use ",(0,a.jsx)(n.code,{children:"update"})," clause to update specific rows."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sql",children:"UPDATE openhouse.db.table SET data = 'updated_data'\nWHERE ts >= '2020-05-01 00:00:00' and ts < '2020-06-01 00:00:00'\n"})}),"\n",(0,a.jsx)(n.h3,{id:"merge-into",children:"MERGE INTO"}),"\n",(0,a.jsx)(n.p,{children:"Merge into is used to update target table (ex. db.target) based on source query (SELECT ..)"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sql",children:"MERGE INTO openhouse.db.table t\nUSING (SELECT ...) s\nON t.id = s.id\nWHEN MATCHED .. THEN..\n"})}),"\n",(0,a.jsxs)(n.p,{children:["The merge condition ",(0,a.jsx)(n.code,{children:"WHEN MATCHED .. THEN .."})," determines whether update/delete/insert would happen"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sql",children:"-- delete\nWHEN MATCHED AND s.op = 'delete' THEN DELETE\n-- update\nWHEN MATCHED AND t.count IS NULL AND s.op = 'increment' THEN UPDATE SET t.count = 0\n-- insert\nWHEN NOT MATCHED THEN INSERT *\n"})}),"\n",(0,a.jsxs)(n.p,{children:[(0,a.jsx)(n.code,{children:"THEN INSERT"})," also supports additional conditions"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sql",children:"WHEN NOT MATCHED AND s.event_time > still_valid_threshold THEN INSERT (id, count) VALUES (s.id, 1)\n"})}),"\n",(0,a.jsxs)(n.p,{children:["Complete syntax can be seen at ",(0,a.jsx)(n.a,{href:"https://docs.databricks.com/spark/latest/spark-sql/language-manual/delta-merge-into.html",children:"Databricks Merge Into"}),"."]}),"\n",(0,a.jsx)(n.h2,{id:"inspecting-metadata",children:"Inspecting Metadata"}),"\n",(0,a.jsx)(n.h3,{id:"list-partitions",children:"List Partitions"}),"\n",(0,a.jsxs)(n.p,{children:[(0,a.jsx)(n.code,{children:"show partitions db.table"})," does not work for OpenHouse tables. You can do the same thing with different SQL syntax like below:"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sql",children:" SELECT * FROM openhouse.db.table.partitions;\n"})}),"\n",(0,a.jsx)(n.h3,{id:"list-snapshots",children:"List Snapshots"}),"\n",(0,a.jsx)(n.p,{children:"Each update to the table will generate a new snapshot. Browsing snapshots is a critical feature to enable time-travel queries with snapshhot-id and commit-timestamp."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sql",children:"SELECT * FROM openhouse.db.table.snapshots\n"})}),"\n",(0,a.jsx)(n.h2,{id:"unsupported-operations",children:"Unsupported Operations"}),"\n",(0,a.jsx)(n.p,{children:"Following SQL commands are unsupported"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sql",children:"CREATE TABLE LIKE\n\n-- Renaming Fields\nALTER TABLE openhouse.db.table RENAME COLUMN data TO payload\nALTER TABLE openhouse.db.table RENAME COLUMN point.x TO x_axis\n \n-- Setting comments and type-widening at the same time\nALTER TABLE openhouse.db.table ALTER COLUMN measurement TYPE double COMMENT 'unit is bytes per second'\n \n-- Reorder\nALTER TABLE openhouse.db.table ALTER COLUMN col FIRST\nALTER TABLE openhouse.db.sample ALTER COLUMN nested.col AFTER other_col\n \n-- Drop\nALTER TABLE openhouse.db.table DROP COLUMN id\nALTER TABLE openhouse.db.table DROP COLUMN point.z\n \n-- Other commands that are not supported yet\nALTER TABLE .. RENAME TO\nALTER TABLE ... ADD PARTITION FIELD\nALTER TABLE ... DROP PARTITION FIELD\nALTER TABLE ... REPLACE PARTITION FIELD\nALTER TABLE ... WRITE ORDERED BY\nALTER TABLE ... WRITE DISTRIBUTED BY PARTITION\n"})})]})}function h(e={}){const{wrapper:n}={...(0,t.a)(),...e.components};return n?(0,a.jsx)(n,{...e,children:(0,a.jsx)(c,{...e})}):c(e)}},1151:(e,n,s)=>{s.d(n,{Z:()=>i,a:()=>r});var a=s(7294);const t={},l=a.createContext(t);function r(e){const n=a.useContext(l);return a.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function i(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:r(e.components),a.createElement(l.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/8c8650e1.97130f08.js b/assets/js/8c8650e1.97130f08.js deleted file mode 100644 index a58a6ca8..00000000 --- a/assets/js/8c8650e1.97130f08.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkdocs=self.webpackChunkdocs||[]).push([[3279],{7161:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>o,contentTitle:()=>r,default:()=>h,frontMatter:()=>l,metadata:()=>i,toc:()=>d});var a=s(5893),t=s(1151);const l={title:"SQL",tags:["Spark","SQL","API","OpenHouse"]},r=void 0,i={id:"User Guide/Catalog/SQL",title:"SQL",description:"Data Definition Language (DDL)",source:"@site/docs/User Guide/Catalog/SQL.md",sourceDirName:"User Guide/Catalog",slug:"/User Guide/Catalog/SQL",permalink:"/docs/User Guide/Catalog/SQL",draft:!1,unlisted:!1,tags:[{label:"Spark",permalink:"/docs/tags/spark"},{label:"SQL",permalink:"/docs/tags/sql"},{label:"API",permalink:"/docs/tags/api"},{label:"OpenHouse",permalink:"/docs/tags/open-house"}],version:"current",frontMatter:{title:"SQL",tags:["Spark","SQL","API","OpenHouse"]},sidebar:"docsSidebar",previous:{title:"User Guide",permalink:"/docs/category/user-guide"},next:{title:"Scala",permalink:"/docs/User Guide/Catalog/Scala"}},o={},d=[{value:"Data Definition Language (DDL)",id:"data-definition-language-ddl",level:2},{value:"CREATE TABLE",id:"create-table",level:3},{value:"PARTITIONED BY",id:"partitioned-by",level:4},{value:"TBLPROPERTIES",id:"tblproperties",level:4},{value:"CREATE TABLE AS SELECT (CTAS)",id:"create-table-as-select-ctas",level:4},{value:"REFRESH TABLE",id:"refresh-table",level:3},{value:"DROP TABLE",id:"drop-table",level:3},{value:"ALTER TABLE",id:"alter-table",level:3},{value:"ALTER TABLE ... SET TBLPROPERTIES",id:"alter-table--set-tblproperties",level:4},{value:"ALTER TABLE ... ADD COLUMN",id:"alter-table--add-column",level:4},{value:"ALTER TABLE ... ALTER COLUMN",id:"alter-table--alter-column",level:4},{value:"GRANT/ REVOKE",id:"grant-revoke",level:3},{value:"ALTER TABLE SET POLICY (SHARING=)",id:"alter-table-set-policy-sharing",level:4},{value:"GRANT/ REVOKE SELECT ON TABLE",id:"grant-revoke-select-on-table",level:4},{value:"GRANT/ REVOKE MANAGE GRANTS ON TABLE",id:"grant-revoke-manage-grants-on-table",level:4},{value:"GRANT/REVOKE CREATE TABLE ON DATABASE",id:"grantrevoke-create-table-on-database",level:4},{value:"SHOW GRANTS ON TABLE/DATABASE",id:"show-grants-on-tabledatabase",level:4},{value:"Reads",id:"reads",level:2},{value:"SELECT FROM",id:"select-from",level:3},{value:"SELECT FROM w/ Time-Travel",id:"select-from-w-time-travel",level:3},{value:"Writes",id:"writes",level:2},{value:"INSERT INTO",id:"insert-into",level:3},{value:"DELETE FROM",id:"delete-from",level:3},{value:"INSERT OVERWRITE",id:"insert-overwrite",level:3},{value:"UPDATE",id:"update",level:3},{value:"MERGE INTO",id:"merge-into",level:3},{value:"Inspecting Metadata",id:"inspecting-metadata",level:2},{value:"List Partitions",id:"list-partitions",level:3},{value:"List Snapshots",id:"list-snapshots",level:3},{value:"Unsupported Operations",id:"unsupported-operations",level:2}];function c(e){const n={a:"a",admonition:"admonition",code:"code",h2:"h2",h3:"h3",h4:"h4",li:"li",ol:"ol",p:"p",pre:"pre",ul:"ul",...(0,t.a)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(n.h2,{id:"data-definition-language-ddl",children:"Data Definition Language (DDL)"}),"\n",(0,a.jsx)(n.h3,{id:"create-table",children:"CREATE TABLE"}),"\n",(0,a.jsx)(n.p,{children:"To create an OpenHouse table, run following SQL in Spark."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sql",children:"CREATE TABLE openhouse.db.table (id bigint COMMENT 'unique id', data string);\n"})}),"\n",(0,a.jsx)(n.p,{children:"OpenHouse supports following Create clauses:"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:(0,a.jsx)(n.code,{children:"PARTITIONED BY"})}),"\n",(0,a.jsx)(n.li,{children:(0,a.jsx)(n.code,{children:"TBLPROPERTIES (\u2018key\u2019=\u2019value\u2019,..)"})}),"\n"]}),"\n",(0,a.jsx)(n.p,{children:"OpenHouse does not support following Create clauses:"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:(0,a.jsx)(n.code,{children:"LOCATION (*)"})}),"\n",(0,a.jsx)(n.li,{children:(0,a.jsx)(n.code,{children:"CLUSTERED BY (*)"})}),"\n",(0,a.jsx)(n.li,{children:(0,a.jsx)(n.code,{children:"COMMENT \u2018table documentation\u2019"})}),"\n"]}),"\n",(0,a.jsxs)(n.p,{children:["List of supported DataTypes can be seen in ",(0,a.jsx)(n.a,{href:"https://iceberg.apache.org/docs/latest/spark-writes/#spark-type-to-iceberg-type",children:"Iceberg Spark Types"}),"."]}),"\n",(0,a.jsx)(n.h4,{id:"partitioned-by",children:"PARTITIONED BY"}),"\n",(0,a.jsx)(n.p,{children:"OpenHouse supports single timestamp column to be specified in the partitioning scheme. It also supports upto three string or integer type column based partitioning scheme."}),"\n",(0,a.jsx)(n.p,{children:"To partition your table, you can use the following SQL syntax"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sql",children:"CREATE TABLE openhouse.db.table(datepartition string, epoch_ts timestamp)\nPARTITIONED BY (\n days(epoch_ts),\n datepartition\n )\n"})}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.code,{children:"days(epoch_ts)"}),': partitions data by applying day-granularity on the timestamp-type column "epoch_ts".']}),"\n"]}),"\n",(0,a.jsx)(n.p,{children:"Other granularities supported are:"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.code,{children:"years(epoch_ts)"}),": partition by year"]}),"\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.code,{children:"months(epoch_ts)"}),": partition by month"]}),"\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.code,{children:"hours(epoch_ts)"}),": partition by hour"]}),"\n"]}),"\n",(0,a.jsxs)(n.p,{children:["You can also partition your data based on string column by using identity partitioning (for example: ",(0,a.jsx)(n.code,{children:"datepartition"}),")."]}),"\n",(0,a.jsx)(n.p,{children:"Constraints:"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"Other iceberg transforms such as bucket, truncate are not supported on timestamp column."}),"\n",(0,a.jsx)(n.li,{children:"No transformation is supported on string or integer type partition column. Only timestamp-type column allows transformation."}),"\n"]}),"\n",(0,a.jsx)(n.h4,{id:"tblproperties",children:"TBLPROPERTIES"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sql",children:"CREATE TABLE openhouse.db.table(\n data string\n)\nTBLPROPERTIES (\n 'key'='value',\n ...\n);\n"})}),"\n",(0,a.jsx)(n.admonition,{type:"warning",children:(0,a.jsxs)(n.p,{children:["Keys with the prefix \u201copenhouse.\u201d (for example: \u201copenhouse.tableId\u201d) are preserved and cannot be set/modified.\nAdditionally, all Iceberg ",(0,a.jsx)(n.a,{href:"https://github.com/apache/iceberg/blob/master/core/src/main/java/org/apache/iceberg/TableProperties.java",children:"TableProperties"})," are also preserved."]})}),"\n",(0,a.jsx)(n.h4,{id:"create-table-as-select-ctas",children:"CREATE TABLE AS SELECT (CTAS)"}),"\n",(0,a.jsx)(n.p,{children:"To create an OpenHouse table with some data, run following SQL in Spark."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sql",children:"CREATE TABLE openhouse.db.table\nAS\nSELECT * FROM anyCatalog.srcDb.srcTable WHERE data = 'v1';\n"})}),"\n",(0,a.jsx)(n.admonition,{type:"tip",children:(0,a.jsxs)(n.p,{children:[(0,a.jsx)(n.code,{children:"Create table like tableName"})," is not supported. You can use ",(0,a.jsx)(n.code,{children:"create table A as select * from B limit 0"})," to achieve same effect"]})}),"\n",(0,a.jsx)(n.h3,{id:"refresh-table",children:"REFRESH TABLE"}),"\n",(0,a.jsx)(n.p,{children:"Upon reading a table, its state is cached in your session. In order to read the new state of the table:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sql",children:"REFRESH TABLE openhouse.db.table;\n"})}),"\n",(0,a.jsx)(n.h3,{id:"drop-table",children:"DROP TABLE"}),"\n",(0,a.jsx)(n.p,{children:"To delete table\u2019s data and metadata, run:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sql",children:"DROP TABLE openhouse.db.table;\n"})}),"\n",(0,a.jsx)(n.h3,{id:"alter-table",children:"ALTER TABLE"}),"\n",(0,a.jsx)(n.p,{children:"OpenHouse supports following ALTER statements"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"Setting or removing table properties."}),"\n",(0,a.jsxs)(n.li,{children:["Schema Evolution:","\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"Adding columns in both top and nested level."}),"\n",(0,a.jsx)(n.li,{children:"Widening the type of int, float, and decimal fields."}),"\n",(0,a.jsx)(n.li,{children:"Making required columns optional."}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,a.jsx)(n.p,{children:"OpenHouse doesn\u2019t support for now"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"Schema evolution: Drop, rename and reordering."}),"\n",(0,a.jsx)(n.li,{children:"Renaming a table."}),"\n",(0,a.jsx)(n.li,{children:"Adding, removing, and changing partitioning."}),"\n",(0,a.jsxs)(n.li,{children:["Other iceberg alters such as: ",(0,a.jsx)(n.code,{children:"write ordered by"})," / ",(0,a.jsx)(n.code,{children:"write distributed by"})]}),"\n"]}),"\n",(0,a.jsx)(n.h4,{id:"alter-table--set-tblproperties",children:"ALTER TABLE ... SET TBLPROPERTIES"}),"\n",(0,a.jsx)(n.p,{children:"To set table properties"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sql",children:"ALTER TABLE openhouse.db.table SET TBLPROPERTIES (\n 'key1' = 'value1',\n 'key2' = 'value2'\n)\n"})}),"\n",(0,a.jsx)(n.p,{children:"To unset table properties"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sql",children:"ALTER TABLE openhouse.db.table UNSET TBLPROPERTIES ('key1', 'key2')\n"})}),"\n",(0,a.jsx)(n.admonition,{type:"warning",children:(0,a.jsxs)(n.p,{children:["Keys with the prefix \u201copenhouse.\u201d (for example: \u201copenhouse.tableId\u201d) are preserved and cannot be set/modified.\nAdditionally, all Iceberg ",(0,a.jsx)(n.a,{href:"https://github.com/apache/iceberg/blob/master/core/src/main/java/org/apache/iceberg/TableProperties.java",children:"TableProperties"})," are also preserved."]})}),"\n",(0,a.jsx)(n.h4,{id:"alter-table--add-column",children:"ALTER TABLE ... ADD COLUMN"}),"\n",(0,a.jsx)(n.p,{children:"Adding column is a supported schema evolution, to add a new column:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sql",children:"ALTER TABLE openhouse.db.table\nADD COLUMNS (\n new_column string comment 'new_column docs'\n)\n"})}),"\n",(0,a.jsx)(n.p,{children:"Multiple columns can be added separated by comma.\nNested columns can be added as follows:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sql",children:"-- create a struct column\nALTER TABLE openhouse.db.table\nADD COLUMN point struct;\n \n-- add a field to the struct\nALTER TABLE openhouse.db.table\nADD COLUMN point.z double\n"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sql",children:"-- create a nested array column of struct\nALTER TABLE openhouse.db.table\nADD COLUMN points array>;\n \n-- add a field to the struct within an array. Using keyword 'element' to access the array's element column.\nALTER TABLE openhouse.db.table\nADD COLUMN points.element.z double\n"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sql",children:"-- create a map column of struct key and struct value\nALTER TABLE openhouse.db.table\nADD COLUMN point_map map, struct>;\n \n-- add a field to the value struct in a map. Using keyword 'value' to access the map's value column.\nALTER TABLE openhouse.db.table\nADD COLUMN point_map.value.b int\n \n-- Altering 'key' struct is not allowed. Only map 'value' can be updated.\n"})}),"\n",(0,a.jsx)(n.h4,{id:"alter-table--alter-column",children:"ALTER TABLE ... ALTER COLUMN"}),"\n",(0,a.jsx)(n.p,{children:"Alter column is used for:"}),"\n",(0,a.jsxs)(n.ol,{children:["\n",(0,a.jsxs)(n.li,{children:["Type widening, OpenHouse supports ",(0,a.jsx)(n.code,{children:"int to bigint"}),", ",(0,a.jsx)(n.code,{children:"float to double"})]}),"\n"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sql",children:"ALTER TABLE openhouse.db.table ALTER COLUMN measurement TYPE double;\n"})}),"\n",(0,a.jsxs)(n.ol,{start:"2",children:["\n",(0,a.jsx)(n.li,{children:"Setting column comments"}),"\n"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sql",children:"ALTER TABLE openhouse.db.table ALTER COLUMN measurement COMMENT 'unit is kilobytes per second';\n"})}),"\n",(0,a.jsxs)(n.ol,{start:"3",children:["\n",(0,a.jsx)(n.li,{children:"Make field optional"}),"\n"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sql",children:"ALTER TABLE openhouse.db.table ALTER COLUMN id DROP NOT NULL;\n"})}),"\n",(0,a.jsx)(n.h3,{id:"grant-revoke",children:"GRANT/ REVOKE"}),"\n",(0,a.jsx)(n.p,{children:"Tables and databases in OpenHouse are access controlled by its own RBAC system, to perform any operation you need to have the right privilege."}),"\n",(0,a.jsx)(n.h4,{id:"alter-table-set-policy-sharing",children:"ALTER TABLE SET POLICY (SHARING=)"}),"\n",(0,a.jsx)(n.p,{children:"To make your table sharable, run the following command:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sql",children:"ALTER TABLE openhouse.db.table SET POLICY (SHARING=TRUE);\n"})}),"\n",(0,a.jsx)(n.admonition,{type:"note",children:(0,a.jsxs)(n.p,{children:["Trying to share a table without running this command will throw the error: ",(0,a.jsx)(n.code,{children:"db.table"})," is not a shared table"]})}),"\n",(0,a.jsx)(n.h4,{id:"grant-revoke-select-on-table",children:"GRANT/ REVOKE SELECT ON TABLE"}),"\n",(0,a.jsx)(n.p,{children:"As a TABLE_ADMIN you can grant another user TABLE_VIEWER role by running the SQL:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sql",children:"GRANT SELECT ON TABLE openhouse.db.table TO ;\n"})}),"\n",(0,a.jsx)(n.p,{children:"To revoke the privilege:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sql",children:"REVOKE SELECT ON TABLE openhouse.db.table FROM ;\n"})}),"\n",(0,a.jsx)(n.h4,{id:"grant-revoke-manage-grants-on-table",children:"GRANT/ REVOKE MANAGE GRANTS ON TABLE"}),"\n",(0,a.jsx)(n.p,{children:"As a ACL_EDITOR / TABLE_ADMIN, In order to grant sharing rights on your table to other users, you can make them ACL_EDITOR by running the SQL:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sql",children:"GRANT MANAGE GRANTS ON TABLE openhouse.db.table TO ;\n"})}),"\n",(0,a.jsx)(n.p,{children:"To revoke:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sql",children:"REVOKE MANAGE GRANTS ON TABLE openhouse.db.table FROM ;\n"})}),"\n",(0,a.jsx)(n.h4,{id:"grantrevoke-create-table-on-database",children:"GRANT/REVOKE CREATE TABLE ON DATABASE"}),"\n",(0,a.jsx)(n.p,{children:"As a ACL_EDITOR role of database you can grant TABLE_CREATOR role to whoever wants to create a table in your database."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sql",children:"GRANT CREATE TABLE ON DATABASE openhouse.db TO ;\n"})}),"\n",(0,a.jsx)(n.p,{children:"To revoke:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sql",children:"REVOKE CREATE TABLE ON DATABASE openhouse.db FROM ;\n"})}),"\n",(0,a.jsx)(n.h4,{id:"show-grants-on-tabledatabase",children:"SHOW GRANTS ON TABLE/DATABASE"}),"\n",(0,a.jsx)(n.p,{children:"In order to view granted privileges:"}),"\n",(0,a.jsx)(n.p,{children:"For Table:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sql",children:"SHOW GRANTS ON TABLE openhouse.db.table;\n"})}),"\n",(0,a.jsx)(n.p,{children:"For Database:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sql",children:"SHOW GRANTS ON DATABASE openhouse.db;\n"})}),"\n",(0,a.jsx)(n.h2,{id:"reads",children:"Reads"}),"\n",(0,a.jsx)(n.h3,{id:"select-from",children:"SELECT FROM"}),"\n",(0,a.jsxs)(n.p,{children:["OpenHouse supports ANSI SQL for SELECT statements. For complete syntax see ",(0,a.jsx)(n.a,{href:"https://spark.apache.org/docs/latest/sql-ref-syntax-qry-select.html",children:"Spark SELECT syntax"}),"."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sql",children:"SELECT * FROM openhouse.db.table;\n"})}),"\n",(0,a.jsx)(n.admonition,{type:"note",children:(0,a.jsxs)(n.p,{children:["Note: response of the table is cached for the duration of the session. In order to refresh the cache, please run\n",(0,a.jsx)(n.code,{children:"REFRESH TABLE"})]})}),"\n",(0,a.jsx)(n.h3,{id:"select-from-w-time-travel",children:"SELECT FROM w/ Time-Travel"}),"\n",(0,a.jsx)(n.p,{children:"OpenHouse uses Iceberg as the table format. Iceberg generates a version/snapshot for every update to the table. A snapshot captures the state of the table at a specific point in time. We can query iceberg tables using the snapshot ID or timestamp from the past. Unlike Hive, Iceberg guarantees query reproducibility when querying historical data."}),"\n",(0,a.jsx)(n.p,{children:"Time-travel is supported through following syntax."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sql",children:'-- suffix with "at_timestamp" string and epoch time in milliseconds.\nSELECT * FROM openhouse.db.table.at_timestamp_1686699440000;\n \n-- standard sql dialect for this time-travel is NOT supported\nSELECT * FROM openhouse.db.table FOR SYSTEM_TIME AS OF 1686699440000;\n'})}),"\n",(0,a.jsx)(n.p,{children:"Querying a older version of a table is supported through following syntax."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sql",children:'-- suffix with "snapshot_id" string followed by the ID of snapshot or version.\nSELECT * FROM openhouse.db.table.snapshot_id_821787972099903997;\n \n-- standard sql dialect for this version query is NOT supported\nSELECT * FROM openhouse.db.table FOR SYSTEM_VERSION AS OF 821787972099903997;\n'})}),"\n",(0,a.jsx)(n.h2,{id:"writes",children:"Writes"}),"\n",(0,a.jsx)(n.h3,{id:"insert-into",children:"INSERT INTO"}),"\n",(0,a.jsx)(n.p,{children:"OpenHouse supports standard ANSI SQL for INSERT statements."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sql",children:"INSERT INTO openhouse.db.table VALUES (1, 'a'), (2, 'b');\n"})}),"\n",(0,a.jsx)(n.h3,{id:"delete-from",children:"DELETE FROM"}),"\n",(0,a.jsx)(n.p,{children:"Where clause is used to delete rows"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sql",children:"DELETE FROM openhouse.db.table WHERE ts >= '2020-05-01 00:00:00' and ts < '2020-06-01 00:00:00';\n"})}),"\n",(0,a.jsx)(n.h3,{id:"insert-overwrite",children:"INSERT OVERWRITE"}),"\n",(0,a.jsx)(n.p,{children:"Insert overwrite replaces the partitions in the target table that contains rows from the SELECT query."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sql",children:"INSERT OVERWRITE openhouse.db.table SELECT uuid, ts\nFROM anyCatalog.db.another_table\nWHERE cast(ts as date) = '2020-07-01'\n"})}),"\n",(0,a.jsx)(n.admonition,{type:"danger",children:(0,a.jsx)(n.p,{children:"If the table is unpartitioned the whole table data will be replaced."})}),"\n",(0,a.jsx)(n.h3,{id:"update",children:"UPDATE"}),"\n",(0,a.jsxs)(n.p,{children:["You can use ",(0,a.jsx)(n.code,{children:"update"})," clause to update specific rows."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sql",children:"UPDATE openhouse.db.table SET data = 'updated_data'\nWHERE ts >= '2020-05-01 00:00:00' and ts < '2020-06-01 00:00:00'\n"})}),"\n",(0,a.jsx)(n.h3,{id:"merge-into",children:"MERGE INTO"}),"\n",(0,a.jsx)(n.p,{children:"Merge into is used to update target table (ex. db.target) based on source query (SELECT ..)"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sql",children:"MERGE INTO openhouse.db.table t\nUSING (SELECT ...) s\nON t.id = s.id\nWHEN MATCHED .. THEN..\n"})}),"\n",(0,a.jsxs)(n.p,{children:["The merge condition ",(0,a.jsx)(n.code,{children:"WHEN MATCHED .. THEN .."})," determines whether update/delete/insert would happen"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sql",children:"-- delete\nWHEN MATCHED AND s.op = 'delete' THEN DELETE\n-- update\nWHEN MATCHED AND t.count IS NULL AND s.op = 'increment' THEN UPDATE SET t.count = 0\n-- insert\nWHEN NOT MATCHED THEN INSERT *\n"})}),"\n",(0,a.jsxs)(n.p,{children:[(0,a.jsx)(n.code,{children:"THEN INSERT"})," also supports additional conditions"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sql",children:"WHEN NOT MATCHED AND s.event_time > still_valid_threshold THEN INSERT (id, count) VALUES (s.id, 1)\n"})}),"\n",(0,a.jsxs)(n.p,{children:["Complete syntax can be seen at ",(0,a.jsx)(n.a,{href:"https://docs.databricks.com/spark/latest/spark-sql/language-manual/delta-merge-into.html",children:"Databricks Merge Into"}),"."]}),"\n",(0,a.jsx)(n.h2,{id:"inspecting-metadata",children:"Inspecting Metadata"}),"\n",(0,a.jsx)(n.h3,{id:"list-partitions",children:"List Partitions"}),"\n",(0,a.jsxs)(n.p,{children:[(0,a.jsx)(n.code,{children:"show partitions db.table"})," does not work for OpenHouse tables. You can do the same thing with different SQL syntax like below:"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sql",children:" SELECT * FROM openhouse.db.table.partitions;\n"})}),"\n",(0,a.jsx)(n.h3,{id:"list-snapshots",children:"List Snapshots"}),"\n",(0,a.jsx)(n.p,{children:"Each update to the table will generate a new snapshot. Browsing snapshots is a critical feature to enable time-travel queries with snapshhot-id and commit-timestamp."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sql",children:"SELECT * FROM openhouse.db.table.snapshots\n"})}),"\n",(0,a.jsx)(n.h2,{id:"unsupported-operations",children:"Unsupported Operations"}),"\n",(0,a.jsx)(n.p,{children:"Following SQL commands are unsupported"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sql",children:"CREATE TABLE LIKE\n\n-- Renaming Fields\nALTER TABLE openhouse.db.table RENAME COLUMN data TO payload\nALTER TABLE openhouse.db.table RENAME COLUMN point.x TO x_axis\n \n-- Setting comments and type-widening at the same time\nALTER TABLE openhouse.db.table ALTER COLUMN measurement TYPE double COMMENT 'unit is bytes per second'\n \n-- Reorder\nALTER TABLE openhouse.db.table ALTER COLUMN col FIRST\nALTER TABLE openhouse.db.sample ALTER COLUMN nested.col AFTER other_col\n \n-- Drop\nALTER TABLE openhouse.db.table DROP COLUMN id\nALTER TABLE openhouse.db.table DROP COLUMN point.z\n \n-- Other commands that are not supported yet\nALTER TABLE .. RENAME TO\nALTER TABLE ... ADD PARTITION FIELD\nALTER TABLE ... DROP PARTITION FIELD\nALTER TABLE ... REPLACE PARTITION FIELD\nALTER TABLE ... WRITE ORDERED BY\nALTER TABLE ... WRITE DISTRIBUTED BY PARTITION\n"})})]})}function h(e={}){const{wrapper:n}={...(0,t.a)(),...e.components};return n?(0,a.jsx)(n,{...e,children:(0,a.jsx)(c,{...e})}):c(e)}},1151:(e,n,s)=>{s.d(n,{Z:()=>i,a:()=>r});var a=s(7294);const t={},l=a.createContext(t);function r(e){const n=a.useContext(l);return a.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function i(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:r(e.components),a.createElement(l.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/b2f554cd.40fd487d.js b/assets/js/b2f554cd.40fd487d.js new file mode 100644 index 00000000..86382170 --- /dev/null +++ b/assets/js/b2f554cd.40fd487d.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs=self.webpackChunkdocs||[]).push([[1477],{10:e=>{e.exports=JSON.parse('{"blogPosts":[{"id":"introduction-oh","metadata":{"permalink":"/blog/introduction-oh","source":"@site/blog/2023-07-19-introduction-oh.mdx","title":"Taking Charge of Tables, Introducing OpenHouse for Big Data Management","description":"\\n Read More \\n"}]}')}}]); \ No newline at end of file diff --git a/assets/js/b2f554cd.518b73f8.js b/assets/js/b2f554cd.518b73f8.js deleted file mode 100644 index 93c224b5..00000000 --- a/assets/js/b2f554cd.518b73f8.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkdocs=self.webpackChunkdocs||[]).push([[1477],{10:e=>{e.exports=JSON.parse('{"blogPosts":[{"id":"introduction-oh","metadata":{"permalink":"/blog/introduction-oh","source":"@site/blog/2023-07-19-introduction-oh.mdx","title":"Taking Charge of Tables, Introducing OpenHouse for Big Data Management","description":"\\n Read More \\n"}]}')}}]); \ No newline at end of file diff --git a/assets/js/be5943d9.03e7259b.js b/assets/js/be5943d9.03e7259b.js new file mode 100644 index 00000000..3b2590e0 --- /dev/null +++ b/assets/js/be5943d9.03e7259b.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs=self.webpackChunkdocs||[]).push([[5424],{2978:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>d,contentTitle:()=>r,default:()=>l,frontMatter:()=>s,metadata:()=>u,toc:()=>g});var o=n(5893),a=n(1151),i=n(3692);const s={slug:"introduction-oh",title:"Taking Charge of Tables, Introducing OpenHouse for Big Data Management",authors:{name:"Sumedh Sakdeo",url:"https://www.linkedin.com/in/sumedhsakdeo/",image_url:"https://github.com/sumedhsakdeo.png"},tags:["openhouse","introduction","big data"],hide_reading_time:!0},r=void 0,u={permalink:"/blog/introduction-oh",source:"@site/blog/2023-07-19-introduction-oh.mdx",title:"Taking Charge of Tables, Introducing OpenHouse for Big Data Management",description:"{n.d(t,{Z:()=>r,a:()=>s});var o=n(7294);const a={},i=o.createContext(a);function s(e){const t=o.useContext(i);return o.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:s(e.components),o.createElement(i.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/be5943d9.582f0dc8.js b/assets/js/be5943d9.582f0dc8.js deleted file mode 100644 index 3446fee9..00000000 --- a/assets/js/be5943d9.582f0dc8.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkdocs=self.webpackChunkdocs||[]).push([[5424],{2978:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>d,contentTitle:()=>r,default:()=>c,frontMatter:()=>s,metadata:()=>u,toc:()=>g});var o=n(5893),a=n(1151),i=n(3692);const s={slug:"introduction-oh",title:"Taking Charge of Tables, Introducing OpenHouse for Big Data Management",authors:{name:"Sumedh Sakdeo",title:"OpenHouse @ LinkedIn, ex-Head of Data Lyft Self Driving Division",url:"https://www.linkedin.com/in/sumedhsakdeo/",image_url:"https://github.com/sumedhsakdeo.png"},tags:["openhouse","introduction","big data"],hide_reading_time:!0},r=void 0,u={permalink:"/blog/introduction-oh",source:"@site/blog/2023-07-19-introduction-oh.mdx",title:"Taking Charge of Tables, Introducing OpenHouse for Big Data Management",description:"{n.d(t,{Z:()=>r,a:()=>s});var o=n(7294);const a={},i=o.createContext(a);function s(e){const t=o.useContext(i);return o.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:s(e.components),o.createElement(i.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/e580fce4.2fe15caf.js b/assets/js/e580fce4.2fe15caf.js deleted file mode 100644 index f4897272..00000000 --- a/assets/js/e580fce4.2fe15caf.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkdocs=self.webpackChunkdocs||[]).push([[3123],{7288:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>d,contentTitle:()=>r,default:()=>c,frontMatter:()=>s,metadata:()=>u,toc:()=>g});var o=n(5893),a=n(1151),i=n(3692);const s={slug:"introduction-oh",title:"Taking Charge of Tables, Introducing OpenHouse for Big Data Management",authors:{name:"Sumedh Sakdeo",title:"OpenHouse @ LinkedIn, ex-Head of Data Lyft Self Driving Division",url:"https://www.linkedin.com/in/sumedhsakdeo/",image_url:"https://github.com/sumedhsakdeo.png"},tags:["openhouse","introduction","big data"],hide_reading_time:!0},r=void 0,u={permalink:"/blog/introduction-oh",source:"@site/blog/2023-07-19-introduction-oh.mdx",title:"Taking Charge of Tables, Introducing OpenHouse for Big Data Management",description:"{n.d(t,{Z:()=>r,a:()=>s});var o=n(7294);const a={},i=o.createContext(a);function s(e){const t=o.useContext(i);return o.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:s(e.components),o.createElement(i.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/e580fce4.5045eac8.js b/assets/js/e580fce4.5045eac8.js new file mode 100644 index 00000000..1b594ab4 --- /dev/null +++ b/assets/js/e580fce4.5045eac8.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs=self.webpackChunkdocs||[]).push([[3123],{7288:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>d,contentTitle:()=>r,default:()=>l,frontMatter:()=>s,metadata:()=>u,toc:()=>g});var o=n(5893),a=n(1151),i=n(3692);const s={slug:"introduction-oh",title:"Taking Charge of Tables, Introducing OpenHouse for Big Data Management",authors:{name:"Sumedh Sakdeo",url:"https://www.linkedin.com/in/sumedhsakdeo/",image_url:"https://github.com/sumedhsakdeo.png"},tags:["openhouse","introduction","big data"],hide_reading_time:!0},r=void 0,u={permalink:"/blog/introduction-oh",source:"@site/blog/2023-07-19-introduction-oh.mdx",title:"Taking Charge of Tables, Introducing OpenHouse for Big Data Management",description:"{n.d(t,{Z:()=>r,a:()=>s});var o=n(7294);const a={},i=o.createContext(a);function s(e){const t=o.useContext(i);return o.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:s(e.components),o.createElement(i.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/fa03218f.11c2933d.js b/assets/js/fa03218f.11c2933d.js new file mode 100644 index 00000000..2742f2a1 --- /dev/null +++ b/assets/js/fa03218f.11c2933d.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs=self.webpackChunkdocs||[]).push([[5714],{8631:a=>{a.exports=JSON.parse('{"label":"Iceberg","permalink":"/docs/tags/iceberg","allTagsPath":"/docs/tags","count":2,"items":[{"id":"User Guide/Catalog/Scala","title":"Scala","description":"Data Definition Language (DDL)","permalink":"/docs/User Guide/Catalog/Scala"},{"id":"User Guide/Catalog/SQL","title":"SQL","description":"Data Definition Language (DDL)","permalink":"/docs/User Guide/Catalog/SQL"}],"unlisted":false}')}}]); \ No newline at end of file diff --git a/assets/js/main.66874622.js b/assets/js/main.66874622.js deleted file mode 100644 index 1d8ad0da..00000000 --- a/assets/js/main.66874622.js +++ /dev/null @@ -1,2 +0,0 @@ -/*! For license information please see main.66874622.js.LICENSE.txt */ -(self.webpackChunkdocs=self.webpackChunkdocs||[]).push([[179],{723:(e,t,n)=>{"use strict";n.d(t,{Z:()=>p});n(7294);var r=n(8356),a=n.n(r),o=n(6887);const i={"01a85c17":[()=>Promise.all([n.e(532),n.e(4013)]).then(n.bind(n,4524)),"@theme/BlogTagsListPage",4524],"026085c5":[()=>n.e(9434).then(n.t.bind(n,7428,19)),"~docs/default/tag-docs-tags-scala-703.json",7428],"0e384e19":[()=>n.e(9671).then(n.bind(n,7876)),"@site/docs/intro.md",7876],"14eb3368":[()=>Promise.all([n.e(532),n.e(9817)]).then(n.bind(n,4228)),"@theme/DocCategoryGeneratedIndexPage",4228],17896441:[()=>Promise.all([n.e(532),n.e(1404),n.e(7918)]).then(n.bind(n,5154)),"@theme/DocItem",5154],"19e6b04b":[()=>n.e(1899).then(n.bind(n,2120)),"@site/docs/User Guide/Catalog/Scala.md",2120],"1af294fc":[()=>n.e(8401).then(n.t.bind(n,3800,19)),"~blog/default/blog-tags-openhouse-6e7-list.json",3800],"1f391b9e":[()=>Promise.all([n.e(532),n.e(1404),n.e(3085)]).then(n.bind(n,4247)),"@theme/MDXPage",4247],"20417f73":[()=>n.e(743).then(n.t.bind(n,7456,19)),"~blog/default/blog-tags-introduction-60a.json",7456],"36a45a48":[()=>n.e(3142).then(n.t.bind(n,3826,19)),"~blog/default/blog-tags-openhouse-6e7.json",3826],"3720c009":[()=>Promise.all([n.e(532),n.e(3751)]).then(n.bind(n,727)),"@theme/DocTagsListPage",727],"38c71761":[()=>n.e(2268).then(n.t.bind(n,2194,19)),"~docs/default/tag-docs-tags-open-house-b0e.json",2194],"393be207":[()=>n.e(7414).then(n.bind(n,1181)),"@site/src/pages/markdown-page.md",1181],"506626c6":[()=>n.e(6709).then(n.t.bind(n,5745,19)),"/home/runner/work/openhouse/openhouse/.docusaurus/docusaurus-plugin-content-pages/default/plugin-route-context-module-100.json",5745],"55960ee5":[()=>n.e(4121).then(n.t.bind(n,8070,19)),"~docs/default/tags-list-current-prop-15a.json",8070],"58c5ae10":[()=>Promise.all([n.e(532),n.e(1135),n.e(9576)]).then(n.bind(n,8551)),"@site/docs/User Guide/Jobs/JobSpec.mdx",8551],"5ad2500b":[()=>n.e(2979).then(n.t.bind(n,3599,19)),"~blog/default/blog-tags-introduction-60a-list.json",3599],"5bcc385b":[()=>n.e(5739).then(n.t.bind(n,7543,19)),"~docs/default/tag-docs-tags-service-a6b.json",7543],"5e95c892":[()=>n.e(9661).then(n.bind(n,1892)),"@theme/DocsRoot",1892],"5e9f5e1a":[()=>Promise.resolve().then(n.bind(n,6809)),"@generated/docusaurus.config",6809],"657e0780":[()=>Promise.all([n.e(532),n.e(1135),n.e(3189)]).then(n.bind(n,8923)),"@site/docs/User Guide/Catalog/TableSpec.mdx",8923],"6875c492":[()=>Promise.all([n.e(532),n.e(1404),n.e(9677),n.e(8610)]).then(n.bind(n,1714)),"@theme/BlogTagsPostsPage",1714],"712b36a0":[()=>n.e(1885).then(n.t.bind(n,8861,19)),"~docs/default/category-docs-docssidebar-category-user-guide-c72.json",8861],"814f3328":[()=>n.e(2535).then(n.t.bind(n,5641,19)),"~blog/default/blog-post-list-prop-default.json",5641],"87a50603":[()=>n.e(7723).then(n.t.bind(n,9602,19)),"~docs/default/tag-docs-tags-api-a37.json",9602],"8c8650e1":[()=>n.e(3279).then(n.bind(n,7161)),"@site/docs/User Guide/Catalog/SQL.md",7161],"935f2afb":[()=>n.e(53).then(n.t.bind(n,1109,19)),"~docs/default/version-current-metadata-prop-751.json",1109],"98659c7e":[()=>n.e(8201).then(n.t.bind(n,817,19)),"~docs/default/tag-docs-tags-spark-7a6.json",817],"9e4087bc":[()=>n.e(3608).then(n.bind(n,3169)),"@theme/BlogArchivePage",3169],a6aa9e1f:[()=>Promise.all([n.e(532),n.e(1404),n.e(9677),n.e(3089)]).then(n.bind(n,46)),"@theme/BlogListPage",46],a7023ddc:[()=>n.e(1713).then(n.t.bind(n,3457,19)),"~blog/default/blog-tags-tags-4c2.json",3457],a7bd4aaa:[()=>n.e(8518).then(n.bind(n,8564)),"@theme/DocVersionRoot",8564],a94703ab:[()=>Promise.all([n.e(532),n.e(4368)]).then(n.bind(n,2674)),"@theme/DocRoot",2674],ac091168:[()=>n.e(8378).then(n.t.bind(n,8437,19)),"~docs/default/tag-docs-tags-spec-3c5.json",8437],ae6d0d2c:[()=>n.e(1353).then(n.t.bind(n,4246,19)),"~blog/default/blog-tags-big-data-fd8-list.json",4246],b17b4ea9:[()=>n.e(959).then(n.t.bind(n,9826,19)),"~docs/default/tag-docs-tags-table-e6d.json",9826],b2b675dd:[()=>n.e(533).then(n.t.bind(n,8017,19)),"~blog/default/blog-c06.json",8017],b2f554cd:[()=>n.e(1477).then(n.t.bind(n,10,19)),"~blog/default/blog-archive-80c.json",10],be5943d9:[()=>n.e(5424).then(n.bind(n,2978)),"@site/blog/2023-07-19-introduction-oh.mdx?truncated=true",2978],c0a0d864:[()=>n.e(6583).then(n.t.bind(n,5705,19)),"~docs/default/tag-docs-tags-sql-a7a.json",5705],c3b6eefd:[()=>n.e(4612).then(n.t.bind(n,9218,19)),"~blog/default/blog-tags-big-data-fd8.json",9218],c4f5d8e4:[()=>Promise.all([n.e(532),n.e(4195)]).then(n.bind(n,5209)),"@site/src/pages/index.js",5209],ccc49370:[()=>Promise.all([n.e(532),n.e(1404),n.e(9677),n.e(6103)]).then(n.bind(n,5203)),"@theme/BlogPostPage",5203],df203c0f:[()=>Promise.all([n.e(532),n.e(9924)]).then(n.bind(n,491)),"@theme/DocTagDocListPage",491],e50d8c7a:[()=>n.e(8887).then(n.t.bind(n,4469,19)),"/home/runner/work/openhouse/openhouse/.docusaurus/docusaurus-plugin-content-blog/default/plugin-route-context-module-100.json",4469],e580fce4:[()=>n.e(3123).then(n.bind(n,7288)),"@site/blog/2023-07-19-introduction-oh.mdx",7288],f1301a38:[()=>n.e(2177).then(n.t.bind(n,1648,19)),"~docs/default/tag-docs-tags-jobs-258.json",1648],f465847f:[()=>n.e(9814).then(n.t.bind(n,8737,19)),"~docs/default/tag-docs-tags-open-api-1a6.json",8737],f92ddff4:[()=>n.e(9863).then(n.t.bind(n,3769,19)),"/home/runner/work/openhouse/openhouse/.docusaurus/docusaurus-plugin-content-docs/default/plugin-route-context-module-100.json",3769]};var s=n(5893);function l(e){let{error:t,retry:n,pastDelay:r}=e;return t?(0,s.jsxs)("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%"},children:[(0,s.jsx)("p",{children:String(t)}),(0,s.jsx)("div",{children:(0,s.jsx)("button",{type:"button",onClick:n,children:"Retry"})})]}):r?(0,s.jsx)("div",{style:{display:"flex",justifyContent:"center",alignItems:"center",height:"100vh"},children:(0,s.jsx)("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",children:(0,s.jsxs)("g",{fill:"none",fillRule:"evenodd",transform:"translate(1 1)",strokeWidth:"2",children:[(0,s.jsxs)("circle",{cx:"22",cy:"22",r:"6",strokeOpacity:"0",children:[(0,s.jsx)("animate",{attributeName:"r",begin:"1.5s",dur:"3s",values:"6;22",calcMode:"linear",repeatCount:"indefinite"}),(0,s.jsx)("animate",{attributeName:"stroke-opacity",begin:"1.5s",dur:"3s",values:"1;0",calcMode:"linear",repeatCount:"indefinite"}),(0,s.jsx)("animate",{attributeName:"stroke-width",begin:"1.5s",dur:"3s",values:"2;0",calcMode:"linear",repeatCount:"indefinite"})]}),(0,s.jsxs)("circle",{cx:"22",cy:"22",r:"6",strokeOpacity:"0",children:[(0,s.jsx)("animate",{attributeName:"r",begin:"3s",dur:"3s",values:"6;22",calcMode:"linear",repeatCount:"indefinite"}),(0,s.jsx)("animate",{attributeName:"stroke-opacity",begin:"3s",dur:"3s",values:"1;0",calcMode:"linear",repeatCount:"indefinite"}),(0,s.jsx)("animate",{attributeName:"stroke-width",begin:"3s",dur:"3s",values:"2;0",calcMode:"linear",repeatCount:"indefinite"})]}),(0,s.jsx)("circle",{cx:"22",cy:"22",r:"8",children:(0,s.jsx)("animate",{attributeName:"r",begin:"0s",dur:"1.5s",values:"6;1;2;3;4;5;6",calcMode:"linear",repeatCount:"indefinite"})})]})})}):null}var c=n(9670),u=n(226);function d(e,t){if("*"===e)return a()({loading:l,loader:()=>n.e(1772).then(n.bind(n,1772)),modules:["@theme/NotFound"],webpack:()=>[1772],render(e,t){const n=e.default;return(0,s.jsx)(u.z,{value:{plugin:{name:"native",id:"default"}},children:(0,s.jsx)(n,{...t})})}});const r=o[`${e}-${t}`],d={},p=[],f=[],m=(0,c.Z)(r);return Object.entries(m).forEach((e=>{let[t,n]=e;const r=i[n];r&&(d[t]=r[0],p.push(r[1]),f.push(r[2]))})),a().Map({loading:l,loader:d,modules:p,webpack:()=>f,render(t,n){const a=JSON.parse(JSON.stringify(r));Object.entries(t).forEach((t=>{let[n,r]=t;const o=r.default;if(!o)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 o&&"function"!=typeof o||Object.keys(r).filter((e=>"default"!==e)).forEach((e=>{o[e]=r[e]}));let i=a;const s=n.split(".");s.slice(0,-1).forEach((e=>{i=i[e]})),i[s[s.length-1]]=o}));const o=a.__comp;delete a.__comp;const i=a.__context;return delete a.__context,(0,s.jsx)(u.z,{value:i,children:(0,s.jsx)(o,{...a,...n})})}})}const p=[{path:"/blog",component:d("/blog","c2a"),exact:!0},{path:"/blog/archive",component:d("/blog/archive","fee"),exact:!0},{path:"/blog/introduction-oh",component:d("/blog/introduction-oh","583"),exact:!0},{path:"/blog/tags",component:d("/blog/tags","aad"),exact:!0},{path:"/blog/tags/big-data",component:d("/blog/tags/big-data","81f"),exact:!0},{path:"/blog/tags/introduction",component:d("/blog/tags/introduction","559"),exact:!0},{path:"/blog/tags/openhouse",component:d("/blog/tags/openhouse","432"),exact:!0},{path:"/markdown-page",component:d("/markdown-page","6bf"),exact:!0},{path:"/docs",component:d("/docs","505"),routes:[{path:"/docs",component:d("/docs","059"),routes:[{path:"/docs/tags",component:d("/docs/tags","0cc"),exact:!0},{path:"/docs/tags/api",component:d("/docs/tags/api","38c"),exact:!0},{path:"/docs/tags/jobs",component:d("/docs/tags/jobs","73c"),exact:!0},{path:"/docs/tags/open-api",component:d("/docs/tags/open-api","323"),exact:!0},{path:"/docs/tags/open-house",component:d("/docs/tags/open-house","231"),exact:!0},{path:"/docs/tags/scala",component:d("/docs/tags/scala","0c9"),exact:!0},{path:"/docs/tags/service",component:d("/docs/tags/service","f4e"),exact:!0},{path:"/docs/tags/spark",component:d("/docs/tags/spark","3d4"),exact:!0},{path:"/docs/tags/spec",component:d("/docs/tags/spec","74a"),exact:!0},{path:"/docs/tags/sql",component:d("/docs/tags/sql","1aa"),exact:!0},{path:"/docs/tags/table",component:d("/docs/tags/table","6ab"),exact:!0},{path:"/docs",component:d("/docs","330"),routes:[{path:"/docs/category/user-guide",component:d("/docs/category/user-guide","be1"),exact:!0,sidebar:"docsSidebar"},{path:"/docs/intro",component:d("/docs/intro","f79"),exact:!0,sidebar:"docsSidebar"},{path:"/docs/User Guide/Catalog/Scala",component:d("/docs/User Guide/Catalog/Scala","e88"),exact:!0,sidebar:"docsSidebar"},{path:"/docs/User Guide/Catalog/SQL",component:d("/docs/User Guide/Catalog/SQL","2a5"),exact:!0,sidebar:"docsSidebar"},{path:"/docs/User Guide/Catalog/TableSpec",component:d("/docs/User Guide/Catalog/TableSpec","5ad"),exact:!0,sidebar:"docsSidebar"},{path:"/docs/User Guide/Jobs/JobSpec",component:d("/docs/User Guide/Jobs/JobSpec","63c"),exact:!0,sidebar:"docsSidebar"}]}]}]},{path:"/",component:d("/","e25"),exact:!0},{path:"*",component:d("*")}]},8934:(e,t,n)=>{"use strict";n.d(t,{_:()=>o,t:()=>i});var r=n(7294),a=n(5893);const o=r.createContext(!1);function i(e){let{children:t}=e;const[n,i]=(0,r.useState)(!1);return(0,r.useEffect)((()=>{i(!0)}),[]),(0,a.jsx)(o.Provider,{value:n,children:t})}},7221:(e,t,n)=>{"use strict";var r=n(7294),a=n(745),o=n(3727),i=n(405),s=n(412);const l=[n(2497),n(3310),n(8320),n(2295),n(1304),n(4750)];var c=n(723),u=n(6550),d=n(8790),p=n(5893);function f(e){let{children:t}=e;return(0,p.jsx)(p.Fragment,{children:t})}var m=n(5742),h=n(2263),g=n(4996),b=n(6668),y=n(1944),v=n(4711),w=n(9727),k=n(3320),x=n(8780),T=n(197);function S(){const{i18n:{currentLocale:e,defaultLocale:t,localeConfigs:n}}=(0,h.Z)(),r=(0,v.l)(),a=n[e].htmlLang,o=e=>e.replace("-","_");return(0,p.jsxs)(m.Z,{children:[Object.entries(n).map((e=>{let[t,{htmlLang:n}]=e;return(0,p.jsx)("link",{rel:"alternate",href:r.createUrl({locale:t,fullyQualified:!0}),hrefLang:n},t)})),(0,p.jsx)("link",{rel:"alternate",href:r.createUrl({locale:t,fullyQualified:!0}),hrefLang:"x-default"}),(0,p.jsx)("meta",{property:"og:locale",content:o(a)}),Object.values(n).filter((e=>a!==e.htmlLang)).map((e=>(0,p.jsx)("meta",{property:"og:locale:alternate",content:o(e.htmlLang)},`meta-og-${e.htmlLang}`)))]})}function E(e){let{permalink:t}=e;const{siteConfig:{url:n}}=(0,h.Z)(),r=function(){const{siteConfig:{url:e,baseUrl:t,trailingSlash:n}}=(0,h.Z)(),{pathname:r}=(0,u.TH)();return e+(0,x.applyTrailingSlash)((0,g.Z)(r),{trailingSlash:n,baseUrl:t})}(),a=t?`${n}${t}`:r;return(0,p.jsxs)(m.Z,{children:[(0,p.jsx)("meta",{property:"og:url",content:a}),(0,p.jsx)("link",{rel:"canonical",href:a})]})}function C(){const{i18n:{currentLocale:e}}=(0,h.Z)(),{metadata:t,image:n}=(0,b.L)();return(0,p.jsxs)(p.Fragment,{children:[(0,p.jsxs)(m.Z,{children:[(0,p.jsx)("meta",{name:"twitter:card",content:"summary_large_image"}),(0,p.jsx)("body",{className:w.h})]}),n&&(0,p.jsx)(y.d,{image:n}),(0,p.jsx)(E,{}),(0,p.jsx)(S,{}),(0,p.jsx)(T.Z,{tag:k.HX,locale:e}),(0,p.jsx)(m.Z,{children:t.map(((e,t)=>(0,p.jsx)("meta",{...e},t)))})]})}const _=new Map;function A(e){if(_.has(e.pathname))return{...e,pathname:_.get(e.pathname)};if((0,d.f)(c.Z,e.pathname).some((e=>{let{route:t}=e;return!0===t.exact})))return _.set(e.pathname,e.pathname),e;const t=e.pathname.trim().replace(/(?:\/index)?\.html$/,"")||"/";return _.set(e.pathname,t),{...e,pathname:t}}var j=n(8934),R=n(8940),P=n(469);function D(e){for(var t=arguments.length,n=new Array(t>1?t-1:0),r=1;r{const r=t.default?.[e]??t[e];return r?.(...n)}));return()=>a.forEach((e=>e?.()))}const I=function(e){let{children:t,location:n,previousLocation:r}=e;return(0,P.Z)((()=>{r!==n&&(!function(e){let{location:t,previousLocation:n}=e;if(!n)return;const r=t.pathname===n.pathname,a=t.hash===n.hash,o=t.search===n.search;if(r&&a&&!o)return;const{hash:i}=t;if(i){const e=decodeURIComponent(i.substring(1)),t=document.getElementById(e);t?.scrollIntoView()}else window.scrollTo(0,0)}({location:n,previousLocation:r}),D("onRouteDidUpdate",{previousLocation:r,location:n}))}),[r,n]),t};function N(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 O extends r.Component{previousLocation;routeUpdateCleanupCb;constructor(e){super(e),this.previousLocation=null,this.routeUpdateCleanupCb=s.default.canUseDOM?D("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=D("onRouteUpdate",{previousLocation:this.previousLocation,location:n}),N(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(0,p.jsx)(I,{previousLocation:this.previousLocation,location:t,children:(0,p.jsx)(u.AW,{location:t,render:()=>e})})}}const L=O,B="__docusaurus-base-url-issue-banner-container",F="__docusaurus-base-url-issue-banner",U="__docusaurus-base-url-issue-banner-suggestion-container";function M(e){return`\ndocument.addEventListener('DOMContentLoaded', function maybeInsertBanner() {\n var shouldInsert = typeof window['docusaurus'] === 'undefined';\n shouldInsert && insertBanner();\n});\n\nfunction insertBanner() {\n var bannerContainer = document.createElement('div');\n bannerContainer.id = '${B}';\n var bannerHtml = ${JSON.stringify(function(e){return`\n
\n

Your Docusaurus site did not load properly.

\n

A very common reason is a wrong site baseUrl configuration.

\n

Current configured baseUrl = ${e} ${"/"===e?" (default value)":""}

\n

We suggest trying baseUrl =

\n
\n`}(e)).replace(/{if("undefined"==typeof document)return void n();const r=document.createElement("link");r.setAttribute("rel","prefetch"),r.setAttribute("href",e),r.onload=()=>t(),r.onerror=()=>n();const a=document.getElementsByTagName("head")[0]??document.getElementsByName("script")[0]?.parentNode;a?.appendChild(r)}))}:function(e){return new Promise(((t,n)=>{const r=new XMLHttpRequest;r.open("GET",e,!0),r.withCredentials=!0,r.onload=()=>{200===r.status?t():n()},r.send(null)}))};var J=n(9670);const K=new Set,Y=new Set,X=()=>navigator.connection?.effectiveType.includes("2g")||navigator.connection?.saveData,ee={prefetch(e){if(!(e=>!X()&&!Y.has(e)&&!K.has(e))(e))return!1;K.add(e);const t=(0,d.f)(c.Z,e).flatMap((e=>{return t=e.route.path,Object.entries(W).filter((e=>{let[n]=e;return n.replace(/-[^-]+$/,"")===t})).flatMap((e=>{let[,t]=e;return Object.values((0,J.Z)(t))}));var t}));return Promise.all(t.map((e=>{const t=n.gca(e);return t&&!t.includes("undefined")?Q(t).catch((()=>{})):Promise.resolve()})))},preload:e=>!!(e=>!X()&&!Y.has(e))(e)&&(Y.add(e),N(e))},te=Object.freeze(ee),ne=Boolean(!0);if(s.default.canUseDOM){window.docusaurus=te;const e=document.getElementById("__docusaurus"),t=(0,p.jsx)(i.B6,{children:(0,p.jsx)(o.VK,{children:(0,p.jsx)(V,{})})}),n=(e,t)=>{console.error("Docusaurus React Root onRecoverableError:",e,t)},s=()=>{if(ne)r.startTransition((()=>{a.hydrateRoot(e,t,{onRecoverableError:n})}));else{const o=a.createRoot(e,{onRecoverableError:n});r.startTransition((()=>{o.render(t)}))}};N(window.location.pathname).then(s)}},8940:(e,t,n)=>{"use strict";n.d(t,{_:()=>d,M:()=>p});var r=n(7294),a=n(6809);const o=JSON.parse('{"docusaurus-plugin-redoc":{"tables-openapi-spec-json":{"url":"redocusaurus/tables-openapi-spec-json.yaml","themeId":"theme-redoc","isSpecFile":true,"spec":{"openapi":"3.0.1","info":{"title":"OpenHouse Tables APIs","description":"API description for OpenHouse Tables API","termsOfService":"http://swagger.io/terms","license":{"name":"Apache 2.0","url":"http://springdoc.org"},"version":"v0.1"},"servers":[{"url":"http://localhost:8080","description":"Generated server url"}],"paths":{"/v1/databases/{databaseId}/tables/{tableId}/iceberg/v2/snapshots":{"put":{"tags":["Snapshot"],"summary":"Puts Iceberg snapshots to Table","description":"Puts Iceberg snapshots to Table","operationId":"putSnapshotsV1","parameters":[{"name":"databaseId","in":"path","description":"Database ID","required":true,"schema":{"type":"string"}},{"name":"tableId","in":"path","description":"Table ID","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IcebergSnapshotsRequestBody"}}},"required":true},"responses":{"200":{"description":"Iceberg snapshot PUT: UPDATED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetTableResponseBody"}}}},"201":{"description":"Iceberg snapshot PUT: CREATED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetTableResponseBody"}}}},"400":{"description":"Iceberg snapshot PUT: BAD_REQUEST","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetTableResponseBody"}}}},"409":{"description":"Iceberg snapshot PUT: CONFLICT","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetTableResponseBody"}}}}}}},"/v0/databases/{databaseId}/tables/{tableId}/iceberg/v2/snapshots":{"put":{"tags":["Snapshot"],"summary":"Puts Iceberg snapshots to Table","description":"Puts Iceberg snapshots to Table","operationId":"putSnapshotsV0","parameters":[{"name":"databaseId","in":"path","description":"Database ID","required":true,"schema":{"type":"string"}},{"name":"tableId","in":"path","description":"Table ID","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IcebergSnapshotsRequestBody"}}},"required":true},"responses":{"200":{"description":"Iceberg snapshot PUT: UPDATED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetTableResponseBody"}}}},"201":{"description":"Iceberg snapshot PUT: CREATED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetTableResponseBody"}}}},"400":{"description":"Iceberg snapshot PUT: BAD_REQUEST","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetTableResponseBody"}}}},"409":{"description":"Iceberg snapshot PUT: CONFLICT","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetTableResponseBody"}}}}}}},"/v0/databases/{databaseId}/tables/{tableId}":{"get":{"tags":["Table"],"summary":"Get Table in a Database","description":"Returns a Table resource identified by tableId in the database identified by databaseId.","operationId":"getTableV0","parameters":[{"name":"databaseId","in":"path","description":"Database ID","required":true,"schema":{"type":"string"}},{"name":"tableId","in":"path","description":"Table ID","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Table GET: OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetTableResponseBody"}}}},"401":{"description":"Table GET: UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetTableResponseBody"}}}},"403":{"description":"Table GET: FORBIDDEN","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetTableResponseBody"}}}},"404":{"description":"Table GET: NOT_FOUND","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetTableResponseBody"}}}}}},"put":{"tags":["Table"],"summary":"Update a Table","description":"Updates or creates a Table and returns the Table resources. If the table does not exist, it will be created. If the table exists, it will be updated.","operationId":"updateTableV0","parameters":[{"name":"databaseId","in":"path","description":"Database ID","required":true,"schema":{"type":"string"}},{"name":"tableId","in":"path","description":"Table ID","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateUpdateTableRequestBody"}}},"required":true},"responses":{"200":{"description":"Table PUT: UPDATED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetTableResponseBody"}}}},"201":{"description":"Table PUT: CREATED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetTableResponseBody"}}}},"400":{"description":"Table PUT: BAD_REQUEST","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetTableResponseBody"}}}},"401":{"description":"Table PUT: UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetTableResponseBody"}}}},"403":{"description":"Table PUT: FORBIDDEN","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetTableResponseBody"}}}},"404":{"description":"Table PUT: DB_NOT_FOUND","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetTableResponseBody"}}}}}},"delete":{"tags":["Table"],"summary":"DELETE Table","description":"Deletes a table resource","operationId":"deleteTableV0","parameters":[{"name":"databaseId","in":"path","description":"Database ID","required":true,"schema":{"type":"string"}},{"name":"tableId","in":"path","description":"Table ID","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Table DELETE: NO_CONTENT"},"400":{"description":"Table DELETE: BAD_REQUEST"},"401":{"description":"Table DELETE: UNAUTHORIZED"},"403":{"description":"Table DELETE: FORBIDDEN"},"404":{"description":"Table DELETE: TBL_DB_NOT_FOUND"}}}},"/v1/databases/{databaseId}/tables/{tableId}":{"get":{"tags":["Table"],"summary":"Get Table in a Database","description":"Returns a Table resource identified by tableId in the database identified by databaseId.","operationId":"getTableV1","parameters":[{"name":"databaseId","in":"path","description":"Database ID","required":true,"schema":{"type":"string"}},{"name":"tableId","in":"path","description":"Table ID","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Table GET: OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetTableResponseBody"}}}},"401":{"description":"Table GET: UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetTableResponseBody"}}}},"403":{"description":"Table GET: FORBIDDEN","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetTableResponseBody"}}}},"404":{"description":"Table GET: NOT_FOUND","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetTableResponseBody"}}}}}},"put":{"tags":["Table"],"summary":"Update a Table","description":"Updates or creates a Table and returns the Table resources. If the table does not exist, it will be created. If the table exists, it will be updated.","operationId":"updateTableV1","parameters":[{"name":"databaseId","in":"path","description":"Database ID","required":true,"schema":{"type":"string"}},{"name":"tableId","in":"path","description":"Table ID","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateUpdateTableRequestBody"}}},"required":true},"responses":{"200":{"description":"Table PUT: UPDATED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetTableResponseBody"}}}},"201":{"description":"Table PUT: CREATED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetTableResponseBody"}}}},"400":{"description":"Table PUT: BAD_REQUEST","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetTableResponseBody"}}}},"401":{"description":"Table PUT: UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetTableResponseBody"}}}},"403":{"description":"Table PUT: FORBIDDEN","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetTableResponseBody"}}}},"404":{"description":"Table PUT: DB_NOT_FOUND","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetTableResponseBody"}}}}}},"delete":{"tags":["Table"],"summary":"DELETE Table","description":"Deletes a table resource","operationId":"deleteTableV1","parameters":[{"name":"databaseId","in":"path","description":"Database ID","required":true,"schema":{"type":"string"}},{"name":"tableId","in":"path","description":"Table ID","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Table DELETE: NO_CONTENT"},"400":{"description":"Table DELETE: BAD_REQUEST"},"401":{"description":"Table DELETE: UNAUTHORIZED"},"403":{"description":"Table DELETE: FORBIDDEN"},"404":{"description":"Table DELETE: TBL_DB_NOT_FOUND"}}}},"/v0/databases/{databaseId}/tables/search":{"post":{"tags":["Table"],"summary":"Search Tables in a Database","description":"Returns a list of Table resources present in a database. Only filter supported is \'database_id\'.","operationId":"searchTablesV0","parameters":[{"name":"databaseId","in":"path","description":"Database ID","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Table SEARCH: OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetAllTablesResponseBody"}}}},"400":{"description":"Table SEARCH: BAD_REQUEST","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetAllTablesResponseBody"}}}},"401":{"description":"Table SEARCH: UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetAllTablesResponseBody"}}}},"403":{"description":"Table SEARCH: FORBIDDEN","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetAllTablesResponseBody"}}}},"404":{"description":"Table SEARCH: NOT_FOUND","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetAllTablesResponseBody"}}}}}}},"/v1/databases/{databaseId}/tables/search":{"post":{"tags":["Table"],"summary":"Search Tables in a Database","description":"Returns a list of Table resources present in a database. Only filter supported is \'database_id\'.","operationId":"searchTablesV1","parameters":[{"name":"databaseId","in":"path","description":"Database ID","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Table SEARCH: OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetAllTablesResponseBody"}}}},"400":{"description":"Table SEARCH: BAD_REQUEST","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetAllTablesResponseBody"}}}},"401":{"description":"Table SEARCH: UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetAllTablesResponseBody"}}}},"403":{"description":"Table SEARCH: FORBIDDEN","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetAllTablesResponseBody"}}}},"404":{"description":"Table SEARCH: NOT_FOUND","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetAllTablesResponseBody"}}}}}}},"/v0/databases/{databaseId}/tables":{"get":{"tags":["Table"],"summary":"List Tables in a Database","description":"Returns a list of Table resources present in a database identified by databaseId.","operationId":"getAllTablesV0","parameters":[{"name":"databaseId","in":"path","description":"Database ID","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Table GET_ALL: OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetAllTablesResponseBody"}}}},"401":{"description":"Table GET_ALL: UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetAllTablesResponseBody"}}}},"404":{"description":"Table GET_ALL: DB NOT_FOUND","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetAllTablesResponseBody"}}}}}},"post":{"tags":["Table"],"summary":"Create a Table","description":"Creates and returns a Table resource in a database identified by databaseId","operationId":"createTableV0","parameters":[{"name":"databaseId","in":"path","description":"Database ID","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateUpdateTableRequestBody"}}},"required":true},"responses":{"201":{"description":"Table POST: CREATED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetTableResponseBody"}}}},"400":{"description":"Table POST: BAD_REQUEST","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetTableResponseBody"}}}},"401":{"description":"Table POST: UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetTableResponseBody"}}}},"403":{"description":"Table POST: FORBIDDEN","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetTableResponseBody"}}}},"404":{"description":"Table POST: DB_NOT_FOUND","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetTableResponseBody"}}}},"409":{"description":"Table POST: TBL_EXISTS","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetTableResponseBody"}}}}}}},"/v1/databases/{databaseId}/tables":{"get":{"tags":["Table"],"summary":"List Tables in a Database","description":"Returns a list of Table resources present in a database identified by databaseId.","operationId":"getAllTablesV1","parameters":[{"name":"databaseId","in":"path","description":"Database ID","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Table GET_ALL: OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetAllTablesResponseBody"}}}},"401":{"description":"Table GET_ALL: UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetAllTablesResponseBody"}}}},"404":{"description":"Table GET_ALL: DB NOT_FOUND","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetAllTablesResponseBody"}}}}}},"post":{"tags":["Table"],"summary":"Create a Table","description":"Creates and returns a Table resource in a database identified by databaseId","operationId":"createTableV1","parameters":[{"name":"databaseId","in":"path","description":"Database ID","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateUpdateTableRequestBody"}}},"required":true},"responses":{"201":{"description":"Table POST: CREATED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetTableResponseBody"}}}},"400":{"description":"Table POST: BAD_REQUEST","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetTableResponseBody"}}}},"401":{"description":"Table POST: UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetTableResponseBody"}}}},"403":{"description":"Table POST: FORBIDDEN","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetTableResponseBody"}}}},"404":{"description":"Table POST: DB_NOT_FOUND","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetTableResponseBody"}}}},"409":{"description":"Table POST: TBL_EXISTS","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetTableResponseBody"}}}}}}},"/v0/databases/{databaseId}/tables/{tableId}/aclPolicies":{"get":{"tags":["Table"],"summary":"Get AclPolicies for Table","description":"Returns principal to role mappings on Table resource identified by databaseId and tableId.","operationId":"getAclPoliciesV0","parameters":[{"name":"databaseId","in":"path","description":"Database ID","required":true,"schema":{"type":"string"}},{"name":"tableId","in":"path","description":"Table ID","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"AclPolicies GET: OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetAclPoliciesResponseBody"}}}},"400":{"description":"AclPolicies GET: BAD_REQUEST","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetAclPoliciesResponseBody"}}}},"401":{"description":"AclPolicies GET: UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetAclPoliciesResponseBody"}}}},"403":{"description":"AclPolicies GET: FORBIDDEN","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetAclPoliciesResponseBody"}}}},"404":{"description":"AclPolicies GET: TABLE_NOT_FOUND","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetAclPoliciesResponseBody"}}}}}},"patch":{"tags":["Table"],"summary":"Update AclPolicies for Table","description":"Updates role for principal on Table identified by databaseId and tableId","operationId":"updateAclPoliciesV0","parameters":[{"name":"databaseId","in":"path","description":"Database ID","required":true,"schema":{"type":"string"}},{"name":"tableId","in":"path","description":"Table ID","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateAclPoliciesRequestBody"}}},"required":true},"responses":{"204":{"description":"AclPolicies PATCH: NO_CONTENT"},"400":{"description":"AclPolicies PATCH: BAD_REQUEST"},"401":{"description":"AclPolicies PATCH: UNAUTHORIZED"},"403":{"description":"AclPolicies PATCH: FORBIDDEN"},"404":{"description":"AclPolicies PATCH: TABLE_NOT_FOUND"}}}},"/v1/databases/{databaseId}/tables/{tableId}/aclPolicies":{"get":{"tags":["Table"],"summary":"Get AclPolicies for Table","description":"Returns principal to role mappings on Table resource identified by databaseId and tableId.","operationId":"getAclPoliciesV1","parameters":[{"name":"databaseId","in":"path","description":"Database ID","required":true,"schema":{"type":"string"}},{"name":"tableId","in":"path","description":"Table ID","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"AclPolicies GET: OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetAclPoliciesResponseBody"}}}},"400":{"description":"AclPolicies GET: BAD_REQUEST","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetAclPoliciesResponseBody"}}}},"401":{"description":"AclPolicies GET: UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetAclPoliciesResponseBody"}}}},"403":{"description":"AclPolicies GET: FORBIDDEN","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetAclPoliciesResponseBody"}}}},"404":{"description":"AclPolicies GET: TABLE_NOT_FOUND","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetAclPoliciesResponseBody"}}}}}},"patch":{"tags":["Table"],"summary":"Update AclPolicies for Table","description":"Updates role for principal on Table identified by databaseId and tableId","operationId":"updateAclPoliciesV1","parameters":[{"name":"databaseId","in":"path","description":"Database ID","required":true,"schema":{"type":"string"}},{"name":"tableId","in":"path","description":"Table ID","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateAclPoliciesRequestBody"}}},"required":true},"responses":{"204":{"description":"AclPolicies PATCH: NO_CONTENT"},"400":{"description":"AclPolicies PATCH: BAD_REQUEST"},"401":{"description":"AclPolicies PATCH: UNAUTHORIZED"},"403":{"description":"AclPolicies PATCH: FORBIDDEN"},"404":{"description":"AclPolicies PATCH: TABLE_NOT_FOUND"}}}},"/v0/databases/{databaseId}/aclPolicies":{"get":{"tags":["Database"],"summary":"Get AclPolicies on Database","description":"Returns principal to role mappings on resource identified by databaseId.","operationId":"getDatabaseAclPoliciesV0","parameters":[{"name":"databaseId","in":"path","description":"Database ID","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"AclPolicies GET: OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetAclPoliciesResponseBody"}}}},"400":{"description":"AclPolicies GET: BAD_REQUEST","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetAclPoliciesResponseBody"}}}},"401":{"description":"AclPolicies GET: UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetAclPoliciesResponseBody"}}}},"404":{"description":"AclPolicies GET: DB_NOT_FOUND","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetAclPoliciesResponseBody"}}}}}},"patch":{"tags":["Database"],"summary":"Update AclPolicies on database","description":"Updates role for principal on database identified by databaseId","operationId":"updateDatabaseAclPoliciesV0","parameters":[{"name":"databaseId","in":"path","description":"Database ID","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateAclPoliciesRequestBody"}}},"required":true},"responses":{"200":{"description":"AclPolicies PATCH: UPDATED"},"400":{"description":"AclPolicies PATCH: BAD_REQUEST"},"401":{"description":"AclPolicies PATCH: UNAUTHORIZED"},"403":{"description":"AclPolicies PATCH: FORBIDDEN"},"404":{"description":"AclPolicies PATCH: DB_NOT_FOUND"}}}},"/v1/databases/{databaseId}/aclPolicies":{"get":{"tags":["Database"],"summary":"Get AclPolicies on Database","description":"Returns principal to role mappings on resource identified by databaseId.","operationId":"getDatabaseAclPoliciesV1","parameters":[{"name":"databaseId","in":"path","description":"Database ID","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"AclPolicies GET: OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetAclPoliciesResponseBody"}}}},"400":{"description":"AclPolicies GET: BAD_REQUEST","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetAclPoliciesResponseBody"}}}},"401":{"description":"AclPolicies GET: UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetAclPoliciesResponseBody"}}}},"404":{"description":"AclPolicies GET: DB_NOT_FOUND","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetAclPoliciesResponseBody"}}}}}},"patch":{"tags":["Database"],"summary":"Update AclPolicies on database","description":"Updates role for principal on database identified by databaseId","operationId":"updateDatabaseAclPoliciesV1","parameters":[{"name":"databaseId","in":"path","description":"Database ID","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateAclPoliciesRequestBody"}}},"required":true},"responses":{"200":{"description":"AclPolicies PATCH: UPDATED"},"400":{"description":"AclPolicies PATCH: BAD_REQUEST"},"401":{"description":"AclPolicies PATCH: UNAUTHORIZED"},"403":{"description":"AclPolicies PATCH: FORBIDDEN"},"404":{"description":"AclPolicies PATCH: DB_NOT_FOUND"}}}},"/v1/databases/{databaseId}/tables/{tableId}/aclPolicies/{principal}":{"get":{"tags":["Table"],"summary":"Get AclPolicies for user principal on a table","description":"Returns role mappings, access information for a principal on resource identified by databaseId and tableId.","operationId":"getAclPoliciesForUserPrincipalV1","parameters":[{"name":"databaseId","in":"path","description":"Database ID","required":true,"schema":{"type":"string"}},{"name":"tableId","in":"path","description":"Table ID","required":true,"schema":{"type":"string"}},{"name":"principal","in":"path","description":"Principal","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"AclPolicies GET: OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetAclPoliciesResponseBody"}}}},"400":{"description":"AclPolicies GET: BAD_REQUEST","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetAclPoliciesResponseBody"}}}},"401":{"description":"AclPolicies GET: UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetAclPoliciesResponseBody"}}}},"403":{"description":"AclPolicies GET: FORBIDDEN","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetAclPoliciesResponseBody"}}}},"404":{"description":"AclPolicies GET: TABLE_NOT_FOUND","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetAclPoliciesResponseBody"}}}}}}},"/v0/databases/{databaseId}/tables/{tableId}/aclPolicies/{principal}":{"get":{"tags":["Table"],"summary":"Get AclPolicies for user principal on a table","description":"Returns role mappings, access information for a principal on resource identified by databaseId and tableId.","operationId":"getAclPoliciesForUserPrincipalV0","parameters":[{"name":"databaseId","in":"path","description":"Database ID","required":true,"schema":{"type":"string"}},{"name":"tableId","in":"path","description":"Table ID","required":true,"schema":{"type":"string"}},{"name":"principal","in":"path","description":"Principal","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"AclPolicies GET: OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetAclPoliciesResponseBody"}}}},"400":{"description":"AclPolicies GET: BAD_REQUEST","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetAclPoliciesResponseBody"}}}},"401":{"description":"AclPolicies GET: UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetAclPoliciesResponseBody"}}}},"403":{"description":"AclPolicies GET: FORBIDDEN","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetAclPoliciesResponseBody"}}}},"404":{"description":"AclPolicies GET: TABLE_NOT_FOUND","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetAclPoliciesResponseBody"}}}}}}},"/databases/{databaseId}/aclPolicies":{"get":{"tags":["Database"],"summary":"Get AclPolicies on Database","description":"Returns principal to role mappings on resource identified by databaseId.","operationId":"getDatabaseAclPolicies","parameters":[{"name":"databaseId","in":"path","description":"Database ID","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"AclPolicies GET: OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetAclPoliciesResponseBody"}}}},"400":{"description":"AclPolicies GET: BAD_REQUEST","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetAclPoliciesResponseBody"}}}},"401":{"description":"AclPolicies GET: UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetAclPoliciesResponseBody"}}}},"404":{"description":"AclPolicies GET: DB_NOT_FOUND","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetAclPoliciesResponseBody"}}}}}}},"/v0/databases":{"get":{"tags":["Database"],"summary":"List all Databases","description":"Returns a list of Database resources.","operationId":"getAllDatabasesV0","responses":{"200":{"description":"Database GET_ALL: OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetAllDatabasesResponseBody"}}}}}}},"/v1/databases":{"get":{"tags":["Database"],"summary":"List all Databases","description":"Returns a list of Database resources.","operationId":"getAllDatabasesV1","responses":{"200":{"description":"Database GET_ALL: OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetAllDatabasesResponseBody"}}}}}}}},"components":{"schemas":{"ClusteringColumn":{"required":["columnName"],"type":"object","properties":{"columnName":{"type":"string","description":"Name of the clustering column in provided schema. The column should be of the type \'String\'.Nested columns can also be provided with a dot-separated name (for example: \'eventHeader.countryCode\').Column name is case-sensitive.","example":"clusteringColumn"}},"description":"Clustering columns for the table","nullable":true,"example":"\\"clustering\\":[{\\"columnName\\":\\"country\\"},{\\"columnName\\":\\"city\\"}]"},"CreateUpdateTableRequestBody":{"required":["baseTableVersion","clusterId","databaseId","schema","tableId","tableProperties"],"type":"object","properties":{"tableId":{"maxLength":128,"minLength":0,"pattern":"^[a-zA-Z0-9_]+$","type":"string","description":"Unique Resource identifier for a table within a Database","example":"my_table"},"databaseId":{"maxLength":128,"minLength":0,"pattern":"^[a-zA-Z0-9_]+$","type":"string","description":"Unique Resource identifier for the Database containing the Table","example":"my_database"},"clusterId":{"pattern":"^[a-zA-Z0-9-_]+$","type":"string","description":"Unique Resource identifier for the Cluster containing the Database","example":"my_cluster"},"schema":{"type":"string","description":"Schema of the table. OpenHouse tables use Iceberg schema specification","example":"{\\"type\\":\\"struct\\",\\"fields\\":[{\\"id\\":1,\\"required\\":true,\\"name\\":\\"id\\",\\"type\\":\\"string\\"},{\\"id\\":2,\\"required\\":true,\\"name\\":\\"name\\",\\"type\\":\\"string\\"},{\\"id\\":3,\\"required\\":true,\\"name\\":\\"timestampColumn\\",\\"type\\":\\"timestamp\\"}]}"},"timePartitioning":{"$ref":"#/components/schemas/TimePartitionSpec"},"clustering":{"type":"array","description":"Clustering columns for the table","nullable":true,"example":"\\"clustering\\":[{\\"columnName\\":\\"country\\"},{\\"columnName\\":\\"city\\"}]","items":{"$ref":"#/components/schemas/ClusteringColumn"}},"tableProperties":{"type":"object","additionalProperties":{"type":"string","description":"Table properties","example":"{\\"key\\":\\"value\\"}"},"description":"Table properties","example":{"key":"value"}},"policies":{"$ref":"#/components/schemas/Policies"},"stageCreate":{"type":"boolean","description":"Boolean that determines creating a staged table","example":false,"default":false},"baseTableVersion":{"type":"string","description":"The version of table that the current update is based upon"},"tableType":{"type":"string","description":"The type of a table","enum":["PRIMARY_TABLE","REPLICA_TABLE"]}},"description":"Request containing details of the Table to be created"},"IcebergSnapshotsRequestBody":{"required":["baseTableVersion"],"type":"object","properties":{"baseTableVersion":{"type":"string","description":"Base Table Version","example":"Base table version to apply the change to"},"jsonSnapshots":{"type":"array","description":"List of json serialized snapshots to put","items":{"type":"string","description":"List of json serialized snapshots to put"}},"createUpdateTableRequestBody":{"$ref":"#/components/schemas/CreateUpdateTableRequestBody"}},"description":"Request containing a list of JSON serialized Iceberg Snapshots to be put"},"Policies":{"type":"object","properties":{"retention":{"$ref":"#/components/schemas/Retention"},"sharingEnabled":{"type":"boolean","description":"Whether data sharing needs to enabled for the table in /tables API request. Sharing is disabled by default","example":false},"columnTags":{"type":"object","additionalProperties":{"$ref":"#/components/schemas/PolicyTag"},"description":"Policy tags applied to columns in /tables API request.","example":"{\'colName\': [PII, HC]}"}},"description":"Policies of the table","nullable":true},"PolicyTag":{"type":"object","properties":{"tags":{"uniqueItems":true,"type":"array","description":"Policy tags","example":"PII, HC","items":{"type":"string","description":"Policy tags","example":"PII, HC","enum":["PII","HC"]}}},"description":"Policy tags applied to columns in /tables API request.","example":"{\'colName\': [PII, HC]}"},"Retention":{"required":["count","granularity"],"type":"object","properties":{"count":{"type":"integer","description":"time period in count for which the retention on table will be applied","format":"int32"},"granularity":{"type":"string","description":"time period granularity for which the retention on table will be applied","example":"hour, day, month, year","enum":["HOUR","DAY","MONTH","YEAR"]},"columnPattern":{"$ref":"#/components/schemas/RetentionColumnPattern"}},"description":"Retention as required in /tables API request. The column holds the retention part or Policies.","example":"{retention:{count:3, granularity: \'day\'}}"},"RetentionColumnPattern":{"required":["columnName","pattern"],"type":"object","properties":{"columnName":{"type":"string","description":"Name of retention column","example":"datepartition"},"pattern":{"type":"string","description":"Pattern for the value of the retention column following java.time.format.DateTimeFormatter standard. Defaults to \'yyyy-MM-dd\' day format if empty.","example":"yyyy-MM-dd-HH"}},"description":"Optional object to specify retention column in case where timestamp is represented as a string","example":"{columnName:datepartition, pattern: yyyy-MM-dd-HH}"},"TimePartitionSpec":{"required":["columnName","granularity"],"type":"object","properties":{"columnName":{"type":"string","description":"Name of the timestamp column in provided schema. The column should be of the type \'Timestamp\'. Nested columns can also be provided with a dot-separated name (for example: \'eventHeader.timeColumn\').Column name is case-sensitive.","example":"timestampColumn"},"granularity":{"type":"string","description":"Granularity of the time partition.","enum":["HOUR","DAY","MONTH","YEAR"]}},"description":"Time partitioning of the table","nullable":true,"example":"\\"timePartitioning\\":{\\"columnName\\":\\"timestampCol\\",\\"granularity\\":\\"HOUR\\"}"},"GetTableResponseBody":{"type":"object","properties":{"tableId":{"type":"string","description":"Unique Resource identifier for a table within a Database","readOnly":true,"example":"my_table"},"databaseId":{"type":"string","description":"Unique Resource identifier for the Database containing the Table","readOnly":true,"example":"my_database"},"clusterId":{"type":"string","description":"Unique Resource identifier for the Cluster containing the Database","readOnly":true,"example":"my_cluster"},"tableUri":{"type":"string","description":"Fully Qualified Resource URI for the table","readOnly":true,"example":"my_cluster.my_database.my_table"},"tableUUID":{"type":"string","description":"Table UUID","readOnly":true,"example":"73ea0d21-3c89-4987-a6cf-26e4f86bdcee"},"tableLocation":{"type":"string","description":"Location of Table in File System / Blob Store","readOnly":true,"example":"://////metadata/.metadata.json"},"tableVersion":{"type":"string","description":"Current Version of the Table.","readOnly":true},"tableCreator":{"type":"string","description":"Authenticated user principal that created the Table.","readOnly":true,"example":"bob"},"schema":{"type":"string","description":"Schema of the Table in Iceberg","readOnly":true,"example":"{\\"type\\":\\"struct\\",\\"fields\\":[{\\"id\\":1,\\"required\\":true,\\"name\\":\\"id\\",\\"type\\":\\"string\\"},{\\"id\\":2,\\"required\\":true,\\"name\\":\\"name\\",\\"type\\":\\"string\\"}]}"},"lastModifiedTime":{"type":"integer","description":"Last modification epoch time in UTC measured in milliseconds of a table.","format":"int64","readOnly":true,"example":1651002318265},"creationTime":{"type":"integer","description":"Table creation epoch time measured in UTC in milliseconds of a table.","format":"int64","readOnly":true,"example":1651002318265},"tableProperties":{"type":"object","additionalProperties":{"type":"string","description":"A map of table properties","example":"{\\"key\\":\\"value\\"}"},"description":"A map of table properties","readOnly":true,"example":{"key":"value"}},"timePartitioning":{"$ref":"#/components/schemas/TimePartitionSpec"},"clustering":{"type":"array","description":"Clustering columns for the table","nullable":true,"items":{"$ref":"#/components/schemas/ClusteringColumn"}},"policies":{"$ref":"#/components/schemas/Policies"},"tableType":{"type":"string","description":"The type of a table","readOnly":true,"example":"PRIMARY_TABLE","enum":["PRIMARY_TABLE","REPLICA_TABLE"]}}},"GetAllTablesResponseBody":{"type":"object","properties":{"results":{"type":"array","description":"List of Table objects in a database","readOnly":true,"items":{"$ref":"#/components/schemas/GetTableResponseBody"}}}},"UpdateAclPoliciesRequestBody":{"required":["operation","principal","role"],"type":"object","properties":{"role":{"type":"string","description":"Role that is being granted/revoked."},"principal":{"type":"string","description":"Grantee principal whose role is being updated"},"operation":{"type":"string","description":"Whether this is a grant/revoke request","example":"GRANT","enum":["GRANT","REVOKE"]}},"description":"Request containing aclPolicies of the Database to be updated"},"AclPolicy":{"type":"object","properties":{"principal":{"type":"string","description":"Principal with the role on the table/database","readOnly":true},"role":{"type":"string","description":"Role associated with the principal","readOnly":true},"properties":{"type":"object","additionalProperties":{"type":"string","description":"Optional properties to accept key-value pair"},"description":"Optional properties to accept key-value pair","readOnly":true}},"description":"List of acl policies associated with table/database"},"GetAclPoliciesResponseBody":{"type":"object","properties":{"results":{"type":"array","description":"List of acl policies associated with table/database","readOnly":true,"items":{"$ref":"#/components/schemas/AclPolicy"}}}},"GetAllDatabasesResponseBody":{"type":"object","properties":{"results":{"type":"array","description":"List of Database objects","readOnly":true,"items":{"$ref":"#/components/schemas/GetDatabaseResponseBody"}}}},"GetDatabaseResponseBody":{"type":"object","properties":{"databaseId":{"type":"string","description":"Unique Resource identifier for the Database","readOnly":true,"example":"my_database"},"clusterId":{"type":"string","description":"Unique Resource identifier for the Cluster containing the Database","readOnly":true,"example":"my_cluster"}},"description":"List of Database objects"}}}}},"jobs-openapi-spec-json":{"url":"redocusaurus/jobs-openapi-spec-json.yaml","themeId":"theme-redoc","isSpecFile":true,"spec":{"openapi":"3.0.1","info":{"title":"OpenHouse APIs","description":"API description for OpenHouse API","termsOfService":"http://swagger.io/terms","license":{"name":"Apache 2.0","url":"http://springdoc.org"},"version":"v0.0.1"},"servers":[{"url":"http://localhost:8080","description":"Generated server url"}],"paths":{"/jobs/{jobId}/cancel":{"put":{"tags":["Job"],"summary":"Cancel Job","description":"Cancels the job given jobId","operationId":"cancelJob","parameters":[{"name":"jobId","in":"path","description":"Job ID","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Job PUT: UPDATED"},"404":{"description":"Job PUT: NOT_FOUND"},"409":{"description":"Job PUT: CONFLICT"}}}},"/jobs":{"post":{"tags":["Job"],"summary":"Submit a Job","description":"Submits a Job and returns a Job resource.","operationId":"createJob","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateJobRequestBody"}}},"required":true},"responses":{"201":{"description":"Job POST: CREATED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobResponseBody"}}}},"400":{"description":"Job POST: BAD_REQUEST","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobResponseBody"}}}}}}},"/jobs/{jobId}":{"get":{"tags":["Job"],"summary":"Get Job","description":"Returns a Job resource identified by jobId.","operationId":"getJob","parameters":[{"name":"jobId","in":"path","description":"Job ID","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Job GET: OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobResponseBody"}}}},"404":{"description":"Job GET: NOT_FOUND","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobResponseBody"}}}}}}}},"components":{"schemas":{"CreateJobRequestBody":{"required":["clusterId","jobName"],"type":"object","properties":{"jobName":{"pattern":"^[a-zA-Z0-9-_]+$","type":"string","description":"Name of a job, doesn\'t need to be unique","example":"my_job"},"clusterId":{"pattern":"^[a-zA-Z0-9-_]+$","type":"string","description":"Unique identifier for the cluster","example":"my_cluster"},"jobConf":{"$ref":"#/components/schemas/JobConf"}},"description":"Request containing details of the Job to be created"},"JobConf":{"type":"object","properties":{"jobType":{"type":"string","enum":["NO_OP","SQL_TEST","RETENTION","ORPHAN_FILES_DELETION","SNAPSHOTS_EXPIRATION","STAGED_FILES_DELETION"]},"proxyUser":{"type":"string"},"args":{"type":"array","items":{"type":"string"}}},"description":"Job config","example":"{\'jobType\': \'RETENTION\', \'table\': \'db.tb\'}"},"JobResponseBody":{"required":["clusterId","creationTimeMs","jobId","jobName","state"],"type":"object","properties":{"jobId":{"pattern":"^[a-zA-Z0-9-_]+$","type":"string","description":"Unique auto-generated identifier for job prefixed with jobName","example":"my_job_8347adee-65b7-4e05-86fc-196af04f4e68"},"jobName":{"pattern":"^[a-zA-Z0-9-_]+$","type":"string","description":"Name of a job, doesn\'t need to be unique","example":"my_job"},"clusterId":{"pattern":"^[a-zA-Z0-9-_]+$","type":"string","description":"Unique identifier for the cluster","example":"my_cluster"},"state":{"type":"string","description":"Current job state, possible states: QUEUED, ACTIVE, CANCELLED, FAILED, SUCCEEDED","example":"SUCCEEDED","enum":["QUEUED","RUNNING","CANCELLED","FAILED","SUCCEEDED"]},"creationTimeMs":{"type":"integer","description":"Job creation time in unix epoch milliseconds","format":"int64","example":1651002318265},"startTimeMs":{"type":"integer","description":"Job start time in unix epoch milliseconds","format":"int64","example":1651002318265},"finishTimeMs":{"type":"integer","description":"Job finish time in unix epoch milliseconds","format":"int64","example":1651002318265},"lastUpdateTimeMs":{"type":"integer","description":"Job contents last update time in unix epoch milliseconds","format":"int64","example":1651002318265},"jobConf":{"$ref":"#/components/schemas/JobConf"},"executionId":{"type":"string","description":"Execution ID generated from engine where job is submitted"}}}}}}}},"docusaurus-theme-redoc":{"theme-redoc":{"lightTheme":{"typography":{"fontFamily":"var(--ifm-font-family-base)","fontSize":"var(--ifm-font-size-base)","lineHeight":"var(--ifm-line-height-base)","fontWeightLight":"var(--ifm-font-weight-light)","fontWeightRegular":"var(--ifm-font-weight-base)","fontWeightBold":"var(--ifm-font-weight-bold)","headings":{"fontFamily":"var(--ifm-heading-font-family)","fontWeight":"var(--ifm-heading-font-weight)","lineHeight":"var(--ifm-heading-line-height)"},"code":{"fontFamily":"var(--ifm-font-family-monospace)","lineHeight":"var(--ifm-pre-line-height)"}},"sidebar":{"width":"300px","backgroundColor":"#ffffff"},"rightPanel":{"backgroundColor":"#303846"},"colors":{"primary":{"main":"#25c2a0"}},"theme":{"prism":{"additionalLanguages":["scala"]}}},"darkTheme":{"typography":{"fontFamily":"var(--ifm-font-family-base)","fontSize":"var(--ifm-font-size-base)","lineHeight":"var(--ifm-line-height-base)","fontWeightLight":"var(--ifm-font-weight-light)","fontWeightRegular":"var(--ifm-font-weight-base)","fontWeightBold":"var(--ifm-font-weight-bold)","headings":{"fontFamily":"var(--ifm-heading-font-family)","fontWeight":"var(--ifm-heading-font-weight)","lineHeight":"var(--ifm-heading-line-height)"},"code":{"fontFamily":"var(--ifm-font-family-monospace)","lineHeight":"var(--ifm-pre-line-height)"}},"sidebar":{"width":"300px","backgroundColor":"rgb(24, 25, 26)","textColor":"#f5f6f7","arrow":{"color":"#f5f6f7"}},"colors":{"text":{"primary":"#f5f6f7","secondary":"rgba(255, 255, 255, 1)"},"gray":{"50":"#FAFAFA","100":"#F5F5F5"},"border":{"dark":"#ffffff","light":"rgba(0,0,0, 0.1)"},"primary":{"main":"#25c2a0"}},"schema":{"nestedBackground":"rgb(24, 25, 26)","typeNameColor":"rgba(255, 255, 255, 1)","typeTitleColor":"rgba(255, 255, 255, 1)"},"theme":{"prism":{"additionalLanguages":["scala"]}}},"options":{"scrollYOffset":"nav.navbar","expandSingleSchemaField":true,"menuToggle":true,"suppressWarnings":true}}},"docusaurus-plugin-content-docs":{"default":{"path":"/docs","versions":[{"name":"current","label":"Next","isLast":true,"path":"/docs","mainDocId":"intro","docs":[{"id":"intro","path":"/docs/intro","sidebar":"docsSidebar"},{"id":"User Guide/Catalog/Scala","path":"/docs/User Guide/Catalog/Scala","sidebar":"docsSidebar"},{"id":"User Guide/Catalog/SQL","path":"/docs/User Guide/Catalog/SQL","sidebar":"docsSidebar"},{"id":"User Guide/Catalog/TableSpec","path":"/docs/User Guide/Catalog/TableSpec","sidebar":"docsSidebar"},{"id":"User Guide/Jobs/JobSpec","path":"/docs/User Guide/Jobs/JobSpec","sidebar":"docsSidebar"},{"id":"/category/user-guide","path":"/docs/category/user-guide","sidebar":"docsSidebar"}],"draftIds":[],"sidebars":{"docsSidebar":{"link":{"path":"/docs/intro","label":"intro"}}}}],"breadcrumbs":true}}}'),i=JSON.parse('{"defaultLocale":"en","locales":["en"],"path":"i18n","currentLocale":"en","localeConfigs":{"en":{"label":"English","direction":"ltr","htmlLang":"en","calendar":"gregory","path":"en"}}}');var s=n(7529);const l=JSON.parse('{"docusaurusVersion":"3.1.0","siteVersion":"0.0.0","pluginVersions":{"docusaurus-plugin-content-docs":{"type":"package","name":"@docusaurus/plugin-content-docs","version":"3.1.0"},"docusaurus-plugin-content-blog":{"type":"package","name":"@docusaurus/plugin-content-blog","version":"3.1.0"},"docusaurus-plugin-content-pages":{"type":"package","name":"@docusaurus/plugin-content-pages","version":"3.1.0"},"docusaurus-plugin-sitemap":{"type":"package","name":"@docusaurus/plugin-sitemap","version":"3.1.0"},"docusaurus-plugin-redoc":{"type":"package","name":"docusaurus-plugin-redoc","version":"2.0.0"},"docusaurus-theme-classic":{"type":"package","name":"@docusaurus/theme-classic","version":"3.1.0"},"docusaurus-theme-redoc":{"type":"package","name":"docusaurus-theme-redoc","version":"2.0.1"}}}');var c=n(5893);const u={siteConfig:a.default,siteMetadata:l,globalData:o,i18n:i,codeTranslations:s},d=r.createContext(u);function p(e){let{children:t}=e;return(0,c.jsx)(d.Provider,{value:u,children:t})}},4763:(e,t,n)=>{"use strict";n.d(t,{Z:()=>f});var r=n(7294),a=n(412),o=n(5742),i=n(8780),s=n(6040),l=n(5893);function c(e){let{error:t,tryAgain:n}=e;return(0,l.jsxs)("div",{style:{display:"flex",flexDirection:"column",justifyContent:"center",alignItems:"flex-start",minHeight:"100vh",width:"100%",maxWidth:"80ch",fontSize:"20px",margin:"0 auto",padding:"1rem"},children:[(0,l.jsx)("h1",{style:{fontSize:"3rem"},children:"This page crashed"}),(0,l.jsx)("button",{type:"button",onClick:n,style:{margin:"1rem 0",fontSize:"2rem",cursor:"pointer",borderRadius:20,padding:"1rem"},children:"Try again"}),(0,l.jsx)(u,{error:t})]})}function u(e){let{error:t}=e;const n=(0,i.getErrorCausalChain)(t).map((e=>e.message)).join("\n\nCause:\n");return(0,l.jsx)("p",{style:{whiteSpace:"pre-wrap"},children:n})}function d(e){let{error:t,tryAgain:n}=e;return(0,l.jsxs)(f,{fallback:()=>(0,l.jsx)(c,{error:t,tryAgain:n}),children:[(0,l.jsx)(o.Z,{children:(0,l.jsx)("title",{children:"Page Error"})}),(0,l.jsx)(s.Z,{children:(0,l.jsx)(c,{error:t,tryAgain:n})})]})}const p=e=>(0,l.jsx)(d,{...e});class f extends r.Component{constructor(e){super(e),this.state={error:null}}componentDidCatch(e){a.default.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??p)(e)}return e??null}}},412:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>a});const r="undefined"!=typeof window&&"document"in window&&"createElement"in window.document,a={canUseDOM:r,canUseEventListeners:r&&("addEventListener"in window||"attachEvent"in window),canUseIntersectionObserver:r&&"IntersectionObserver"in window,canUseViewport:r&&"screen"in window}},5742:(e,t,n)=>{"use strict";n.d(t,{Z:()=>o});n(7294);var r=n(405),a=n(5893);function o(e){return(0,a.jsx)(r.ql,{...e})}},3692:(e,t,n)=>{"use strict";n.d(t,{Z:()=>f});var r=n(7294),a=n(3727),o=n(8780),i=n(2263),s=n(3919),l=n(412),c=n(8138),u=n(4996),d=n(5893);function p(e,t){let{isNavLink:n,to:p,href:f,activeClassName:m,isActive:h,"data-noBrokenLinkCheck":g,autoAddBaseUrl:b=!0,...y}=e;const{siteConfig:{trailingSlash:v,baseUrl:w}}=(0,i.Z)(),{withBaseUrl:k}=(0,u.C)(),x=(0,c.Z)(),T=(0,r.useRef)(null);(0,r.useImperativeHandle)(t,(()=>T.current));const S=p||f;const E=(0,s.Z)(S),C=S?.replace("pathname://","");let _=void 0!==C?(A=C,b&&(e=>e.startsWith("/"))(A)?k(A):A):void 0;var A;_&&E&&(_=(0,o.applyTrailingSlash)(_,{trailingSlash:v,baseUrl:w}));const j=(0,r.useRef)(!1),R=n?a.OL:a.rU,P=l.default.canUseIntersectionObserver,D=(0,r.useRef)(),I=()=>{j.current||null==_||(window.docusaurus.preload(_),j.current=!0)};(0,r.useEffect)((()=>(!P&&E&&null!=_&&window.docusaurus.prefetch(_),()=>{P&&D.current&&D.current.disconnect()})),[D,_,P,E]);const N=_?.startsWith("#")??!1,O=!_||!E||N;return O||g||x.collectLink(_),O?(0,d.jsx)("a",{ref:T,href:_,...S&&!E&&{target:"_blank",rel:"noopener noreferrer"},...y}):(0,d.jsx)(R,{...y,onMouseEnter:I,onTouchStart:I,innerRef:e=>{T.current=e,P&&e&&E&&(D.current=new window.IntersectionObserver((t=>{t.forEach((t=>{e===t.target&&(t.isIntersecting||t.intersectionRatio>0)&&(D.current.unobserve(e),D.current.disconnect(),null!=_&&window.docusaurus.prefetch(_))}))})),D.current.observe(e))},to:_,...n&&{isActive:h,activeClassName:m}})}const f=r.forwardRef(p)},1875:(e,t,n)=>{"use strict";n.d(t,{Z:()=>r});const r=()=>null},5999:(e,t,n)=>{"use strict";n.d(t,{Z:()=>c,I:()=>l});var r=n(7294),a=n(5893);function o(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,r.isValidElement)(e)))?n.map(((e,t)=>(0,r.isValidElement)(e)?r.cloneElement(e,{key:t}):e)).filter((e=>""!==e)):n.join("")}var i=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 i[t??n]??n??t}function l(e,t){let{message:n,id:r}=e;return o(s({message:n,id:r}),t)}function c(e){let{children:t,id:n,values:r}=e;if(t&&"string"!=typeof t)throw console.warn("Illegal children",t),new Error("The Docusaurus component only accept simple string values");const i=s({message:t,id:n});return(0,a.jsx)(a.Fragment,{children:o(i,r)})}},9935:(e,t,n)=>{"use strict";n.d(t,{m:()=>r});const r="default"},3919:(e,t,n)=>{"use strict";function r(e){return/^(?:\w*:|\/\/)/.test(e)}function a(e){return void 0!==e&&!r(e)}n.d(t,{Z:()=>a,b:()=>r})},4996:(e,t,n)=>{"use strict";n.d(t,{C:()=>i,Z:()=>s});var r=n(7294),a=n(2263),o=n(3919);function i(){const{siteConfig:{baseUrl:e,url:t}}=(0,a.Z)(),n=(0,r.useCallback)(((n,r)=>function(e,t,n,r){let{forcePrependBaseUrl:a=!1,absolute:i=!1}=void 0===r?{}:r;if(!n||n.startsWith("#")||(0,o.b)(n))return n;if(a)return t+n.replace(/^\//,"");if(n===t.replace(/\/$/,""))return t;const s=n.startsWith(t)?n:t+n.replace(/^\//,"");return i?e+s:s}(t,e,n,r)),[t,e]);return{withBaseUrl:n}}function s(e,t){void 0===t&&(t={});const{withBaseUrl:n}=i();return n(e,t)}},8138:(e,t,n)=>{"use strict";n.d(t,{Z:()=>i});var r=n(7294);n(5893);const a=r.createContext({collectAnchor:()=>{},collectLink:()=>{}}),o=()=>(0,r.useContext)(a);function i(){return o()}},2263:(e,t,n)=>{"use strict";n.d(t,{Z:()=>o});var r=n(7294),a=n(8940);function o(){return(0,r.useContext)(a._)}},8084:(e,t,n)=>{"use strict";n.d(t,{OD:()=>o,eZ:()=>i});var r=n(2263),a=n(9935);function o(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}function i(e,t,n){void 0===t&&(t=a.m),void 0===n&&(n={});const r=o(e),i=r?.[t];if(!i&&n.failfast)throw new Error(`Docusaurus plugin global data not found for "${e}" plugin with id "${t}".`);return i}},2389:(e,t,n)=>{"use strict";n.d(t,{Z:()=>o});var r=n(7294),a=n(8934);function o(){return(0,r.useContext)(a._)}},469:(e,t,n)=>{"use strict";n.d(t,{Z:()=>a});var r=n(7294);const a=n(412).default.canUseDOM?r.useLayoutEffect:r.useEffect},9670:(e,t,n)=>{"use strict";n.d(t,{Z:()=>a});const r=e=>"object"==typeof e&&!!e&&Object.keys(e).length>0;function a(e){const t={};return function e(n,a){Object.entries(n).forEach((n=>{let[o,i]=n;const s=a?`${a}.${o}`:o;r(i)?e(i,s):t[s]=i}))}(e),t}},226:(e,t,n)=>{"use strict";n.d(t,{_:()=>o,z:()=>i});var r=n(7294),a=n(5893);const o=r.createContext(null);function i(e){let{children:t,value:n}=e;const i=r.useContext(o),s=(0,r.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 r={...t.data,...n?.data};return{plugin:t.plugin,data:r}}({parent:i,value:n})),[i,n]);return(0,a.jsx)(o.Provider,{value:s,children:t})}},4104:(e,t,n)=>{"use strict";n.d(t,{Iw:()=>f,gA:()=>u,_r:()=>l,Jo:()=>m,zh:()=>c,yW:()=>p,gB:()=>d});var r=n(6550),a=n(8084);const o=e=>e.versions.find((e=>e.isLast));function i(e,t){const n=function(e,t){const n=o(e);return[...e.versions.filter((e=>e!==n)),n].find((e=>!!(0,r.LX)(t,{path:e.path,exact:!1,strict:!1})))}(e,t),a=n?.docs.find((e=>!!(0,r.LX)(t,{path:e.path,exact:!0,strict:!1})));return{activeVersion:n,activeDoc:a,alternateDocVersions:a?function(t){const n={};return e.versions.forEach((e=>{e.docs.forEach((r=>{r.id===t&&(n[e.name]=r)}))})),n}(a.id):{}}}const s={},l=()=>(0,a.OD)("docusaurus-plugin-content-docs")??s,c=e=>(0,a.eZ)("docusaurus-plugin-content-docs",e,{failfast:!0});function u(e){void 0===e&&(e={});const t=l(),{pathname:n}=(0,r.TH)();return function(e,t,n){void 0===n&&(n={});const a=Object.entries(e).sort(((e,t)=>t[1].path.localeCompare(e[1].path))).find((e=>{let[,n]=e;return!!(0,r.LX)(t,{path:n.path,exact:!1,strict:!1})})),o=a?{pluginId:a[0],pluginData:a[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 d(e){return c(e).versions}function p(e){const t=c(e);return o(t)}function f(e){const t=c(e),{pathname:n}=(0,r.TH)();return i(t,n)}function m(e){const t=c(e),{pathname:n}=(0,r.TH)();return function(e,t){const n=o(e);return{latestDocSuggestion:i(e,t).alternateDocVersions[n.name],latestVersionSuggestion:n}}(t,n)}},8320:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>o});var r=n(4865),a=n.n(r);a().configure({showSpinner:!1});const o={onRouteUpdate(e){let{location:t,previousLocation:n}=e;if(n&&t.pathname!==n.pathname){const e=window.setTimeout((()=>{a().start()}),200);return()=>window.clearTimeout(e)}},onRouteDidUpdate(){a().done()}}},3310:(e,t,n)=>{"use strict";n.r(t);var r=n(2573),a=n(6809);!function(e){const{themeConfig:{prism:t}}=a.default,{additionalLanguages:r}=t;globalThis.Prism=e,r.forEach((e=>{"php"===e&&n(6854),n(6726)(`./prism-${e}`)})),delete globalThis.Prism}(r.p1)},2503:(e,t,n)=>{"use strict";n.d(t,{Z:()=>u});n(7294);var r=n(512),a=n(5999),o=n(6668),i=n(3692),s=n(8138);const l={anchorWithStickyNavbar:"anchorWithStickyNavbar_LWe7",anchorWithHideOnScrollNavbar:"anchorWithHideOnScrollNavbar_WYt5"};var c=n(5893);function u(e){let{as:t,id:n,...u}=e;const d=(0,s.Z)(),{navbar:{hideOnScroll:p}}=(0,o.L)();if("h1"===t||!n)return(0,c.jsx)(t,{...u,id:void 0});d.collectAnchor(n);const f=(0,a.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(0,c.jsxs)(t,{...u,className:(0,r.Z)("anchor",p?l.anchorWithHideOnScrollNavbar:l.anchorWithStickyNavbar,u.className),id:n,children:[u.children,(0,c.jsx)(i.Z,{className:"hash-link",to:`#${n}`,"aria-label":f,title:f,children:"\u200b"})]})}},9471:(e,t,n)=>{"use strict";n.d(t,{Z:()=>o});n(7294);const r={iconExternalLink:"iconExternalLink_nPIU"};var a=n(5893);function o(e){let{width:t=13.5,height:n=13.5}=e;return(0,a.jsx)("svg",{width:t,height:n,"aria-hidden":"true",viewBox:"0 0 24 24",className:r.iconExternalLink,children:(0,a.jsx)("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"})})}},6040:(e,t,n)=>{"use strict";n.d(t,{Z:()=>ft});var r=n(7294),a=n(512),o=n(4763),i=n(1944),s=n(6550),l=n(5999),c=n(5936),u=n(5893);const d="__docusaurus_skipToContent_fallback";function p(e){e.setAttribute("tabindex","-1"),e.focus(),e.removeAttribute("tabindex")}function f(){const e=(0,r.useRef)(null),{action:t}=(0,s.k6)(),n=(0,r.useCallback)((e=>{e.preventDefault();const t=document.querySelector("main:first-of-type")??document.getElementById(d);t&&p(t)}),[]);return(0,c.S)((n=>{let{location:r}=n;e.current&&!r.hash&&"PUSH"===t&&p(e.current)})),{containerRef:e,onClick:n}}const m=(0,l.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 h(e){const t=e.children??m,{containerRef:n,onClick:r}=f();return(0,u.jsx)("div",{ref:n,role:"region","aria-label":m,children:(0,u.jsx)("a",{...e,href:`#${d}`,onClick:r,children:t})})}var g=n(5281),b=n(9727);const y={skipToContent:"skipToContent_fXgn"};function v(){return(0,u.jsx)(h,{className:y.skipToContent})}var w=n(6668),k=n(9689);function x(e){let{width:t=21,height:n=21,color:r="currentColor",strokeWidth:a=1.2,className:o,...i}=e;return(0,u.jsx)("svg",{viewBox:"0 0 15 15",width:t,height:n,...i,children:(0,u.jsx)("g",{stroke:r,strokeWidth:a,children:(0,u.jsx)("path",{d:"M.75.75l13.5 13.5M14.25.75L.75 14.25"})})})}const T={closeButton:"closeButton_CVFx"};function S(e){return(0,u.jsx)("button",{type:"button","aria-label":(0,l.I)({id:"theme.AnnouncementBar.closeButtonAriaLabel",message:"Close",description:"The ARIA label for close button of announcement bar"}),...e,className:(0,a.Z)("clean-btn close",T.closeButton,e.className),children:(0,u.jsx)(x,{width:14,height:14,strokeWidth:3.1})})}const E={content:"content_knG7"};function C(e){const{announcementBar:t}=(0,w.L)(),{content:n}=t;return(0,u.jsx)("div",{...e,className:(0,a.Z)(E.content,e.className),dangerouslySetInnerHTML:{__html:n}})}const _={announcementBar:"announcementBar_mb4j",announcementBarPlaceholder:"announcementBarPlaceholder_vyr4",announcementBarClose:"announcementBarClose_gvF7",announcementBarContent:"announcementBarContent_xLdY"};function A(){const{announcementBar:e}=(0,w.L)(),{isActive:t,close:n}=(0,k.nT)();if(!t)return null;const{backgroundColor:r,textColor:a,isCloseable:o}=e;return(0,u.jsxs)("div",{className:_.announcementBar,style:{backgroundColor:r,color:a},role:"banner",children:[o&&(0,u.jsx)("div",{className:_.announcementBarPlaceholder}),(0,u.jsx)(C,{className:_.announcementBarContent}),o&&(0,u.jsx)(S,{onClick:n,className:_.announcementBarClose})]})}var j=n(2961),R=n(2466);var P=n(902),D=n(3102);const I=r.createContext(null);function N(e){let{children:t}=e;const n=function(){const e=(0,j.e)(),t=(0,D.HY)(),[n,a]=(0,r.useState)(!1),o=null!==t.component,i=(0,P.D9)(o);return(0,r.useEffect)((()=>{o&&!i&&a(!0)}),[o,i]),(0,r.useEffect)((()=>{o?e.shown||a(!0):a(!1)}),[e.shown,o]),(0,r.useMemo)((()=>[n,a]),[n])}();return(0,u.jsx)(I.Provider,{value:n,children:t})}function O(e){if(e.component){const t=e.component;return(0,u.jsx)(t,{...e.props})}}function L(){const e=(0,r.useContext)(I);if(!e)throw new P.i6("NavbarSecondaryMenuDisplayProvider");const[t,n]=e,a=(0,r.useCallback)((()=>n(!1)),[n]),o=(0,D.HY)();return(0,r.useMemo)((()=>({shown:t,hide:a,content:O(o)})),[a,o,t])}function B(e){let{header:t,primaryMenu:n,secondaryMenu:r}=e;const{shown:o}=L();return(0,u.jsxs)("div",{className:"navbar-sidebar",children:[t,(0,u.jsxs)("div",{className:(0,a.Z)("navbar-sidebar__items",{"navbar-sidebar__items--show-secondary":o}),children:[(0,u.jsx)("div",{className:"navbar-sidebar__item menu",children:n}),(0,u.jsx)("div",{className:"navbar-sidebar__item menu",children:r})]})]})}var F=n(2949),U=n(2389);function M(e){return(0,u.jsx)("svg",{viewBox:"0 0 24 24",width:24,height:24,...e,children:(0,u.jsx)("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 $(e){return(0,u.jsx)("svg",{viewBox:"0 0 24 24",width:24,height:24,...e,children:(0,u.jsx)("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 z={toggle:"toggle_vylO",toggleButton:"toggleButton_gllP",darkToggleIcon:"darkToggleIcon_wfgR",lightToggleIcon:"lightToggleIcon_pyhR",toggleButtonDisabled:"toggleButtonDisabled_aARS"};function G(e){let{className:t,buttonClassName:n,value:r,onChange:o}=e;const i=(0,U.Z)(),s=(0,l.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"===r?(0,l.I)({message:"dark mode",id:"theme.colorToggle.ariaLabel.mode.dark",description:"The name for the dark color mode"}):(0,l.I)({message:"light mode",id:"theme.colorToggle.ariaLabel.mode.light",description:"The name for the light color mode"})});return(0,u.jsx)("div",{className:(0,a.Z)(z.toggle,t),children:(0,u.jsxs)("button",{className:(0,a.Z)("clean-btn",z.toggleButton,!i&&z.toggleButtonDisabled,n),type:"button",onClick:()=>o("dark"===r?"light":"dark"),disabled:!i,title:s,"aria-label":s,"aria-live":"polite",children:[(0,u.jsx)(M,{className:(0,a.Z)(z.toggleIcon,z.lightToggleIcon)}),(0,u.jsx)($,{className:(0,a.Z)(z.toggleIcon,z.darkToggleIcon)})]})})}const q=r.memo(G),H={darkNavbarColorModeToggle:"darkNavbarColorModeToggle_X3D1"};function Z(e){let{className:t}=e;const n=(0,w.L)().navbar.style,r=(0,w.L)().colorMode.disableSwitch,{colorMode:a,setColorMode:o}=(0,F.I)();return r?null:(0,u.jsx)(q,{className:t,buttonClassName:"dark"===n?H.darkNavbarColorModeToggle:void 0,value:a,onChange:o})}var V=n(1327);function W(){return(0,u.jsx)(V.Z,{className:"navbar__brand",imageClassName:"navbar__logo",titleClassName:"navbar__title text--truncate"})}function Q(){const e=(0,j.e)();return(0,u.jsx)("button",{type:"button","aria-label":(0,l.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(),children:(0,u.jsx)(x,{color:"var(--ifm-color-emphasis-600)"})})}function J(){return(0,u.jsxs)("div",{className:"navbar-sidebar__brand",children:[(0,u.jsx)(W,{}),(0,u.jsx)(Z,{className:"margin-right--md"}),(0,u.jsx)(Q,{})]})}var K=n(3692),Y=n(4996),X=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:a,label:o,html:i,isDropdownLink:s,prependBaseUrlToHref:l,...c}=e;const d=(0,Y.Z)(r),p=(0,Y.Z)(t),f=(0,Y.Z)(a,{forcePrependBaseUrl:!0}),m=o&&a&&!(0,X.Z)(a),h=i?{dangerouslySetInnerHTML:{__html:i}}:{children:(0,u.jsxs)(u.Fragment,{children:[o,m&&(0,u.jsx)(te.Z,{...s&&{width:12,height:12}})]})};return a?(0,u.jsx)(K.Z,{href:l?f:a,...c,...h}):(0,u.jsx)(K.Z,{to:d,isNavLink:!0,...(t||n)&&{isActive:(e,t)=>n?ee(n,t.pathname):t.pathname.startsWith(p)},...c,...h})}function re(e){let{className:t,isDropdownItem:n=!1,...r}=e;const o=(0,u.jsx)(ne,{className:(0,a.Z)(n?"dropdown__link":"navbar__item navbar__link",t),isDropdownLink:n,...r});return n?(0,u.jsx)("li",{children:o}):o}function ae(e){let{className:t,isDropdownItem:n,...r}=e;return(0,u.jsx)("li",{className:"menu__list-item",children:(0,u.jsx)(ne,{className:(0,a.Z)("menu__link",t),...r})})}function oe(e){let{mobile:t=!1,position:n,...r}=e;const a=t?ae:re;return(0,u.jsx)(a,{...r,activeClassName:r.activeClassName??(t?"menu__link--active":"navbar__link--active")})}var ie=n(6043),se=n(8596),le=n(2263);const ce={dropdownNavbarItemMobile:"dropdownNavbarItemMobile_S0Fm"};function ue(e,t){return e.some((e=>function(e,t){return!!(0,se.Mg)(e.to,t)||!!ee(e.activeBaseRegex,t)||!(!e.activeBasePath||!t.startsWith(e.activeBasePath))}(e,t)))}function de(e){let{items:t,position:n,className:o,onClick:i,...s}=e;const l=(0,r.useRef)(null),[c,d]=(0,r.useState)(!1);return(0,r.useEffect)((()=>{const e=e=>{l.current&&!l.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)}}),[l]),(0,u.jsxs)("div",{ref:l,className:(0,a.Z)("navbar__item","dropdown","dropdown--hoverable",{"dropdown--right":"right"===n,"dropdown--show":c}),children:[(0,u.jsx)(ne,{"aria-haspopup":"true","aria-expanded":c,role:"button",href:s.to?void 0:"#",className:(0,a.Z)("navbar__link",o),...s,onClick:s.to?void 0:e=>e.preventDefault(),onKeyDown:e=>{"Enter"===e.key&&(e.preventDefault(),d(!c))},children:s.children??s.label}),(0,u.jsx)("ul",{className:"dropdown__menu",children:t.map(((e,t)=>(0,r.createElement)(Ee,{isDropdownItem:!0,activeClassName:"dropdown__link--active",...e,key:t})))})]})}function pe(e){let{items:t,className:n,position:o,onClick:i,...l}=e;const c=function(){const{siteConfig:{baseUrl:e}}=(0,le.Z)(),{pathname:t}=(0,s.TH)();return t.replace(e,"/")}(),d=ue(t,c),{collapsed:p,toggleCollapsed:f,setCollapsed:m}=(0,ie.u)({initialState:()=>!d});return(0,r.useEffect)((()=>{d&&m(!d)}),[c,d,m]),(0,u.jsxs)("li",{className:(0,a.Z)("menu__list-item",{"menu__list-item--collapsed":p}),children:[(0,u.jsx)(ne,{role:"button",className:(0,a.Z)(ce.dropdownNavbarItemMobile,"menu__link menu__link--sublist menu__link--sublist-caret",n),...l,onClick:e=>{e.preventDefault(),f()},children:l.children??l.label}),(0,u.jsx)(ie.z,{lazy:!0,as:"ul",className:"menu__list",collapsed:p,children:t.map(((e,t)=>(0,r.createElement)(Ee,{mobile:!0,isDropdownItem:!0,onClick:i,activeClassName:"menu__link--active",...e,key:t})))})]})}function fe(e){let{mobile:t=!1,...n}=e;const r=t?pe:de;return(0,u.jsx)(r,{...n})}var me=n(4711);function he(e){let{width:t=20,height:n=20,...r}=e;return(0,u.jsx)("svg",{viewBox:"0 0 24 24",width:t,height:n,"aria-hidden":!0,...r,children:(0,u.jsx)("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 be=n(1875);const ye={navbarSearchContainer:"navbarSearchContainer_Bca1"};function ve(e){let{children:t,className:n}=e;return(0,u.jsx)("div",{className:(0,a.Z)(n,ye.navbarSearchContainer),children:t})}var we=n(4104),ke=n(2802);var xe=n(373);const Te=e=>e.docs.find((t=>t.id===e.mainDocId));const Se={default:oe,localeDropdown:function(e){let{mobile:t,dropdownItemsBefore:n,dropdownItemsAfter:r,queryString:a="",...o}=e;const{i18n:{currentLocale:i,locales:c,localeConfigs:d}}=(0,le.Z)(),p=(0,me.l)(),{search:f,hash:m}=(0,s.TH)(),h=[...n,...c.map((e=>{const n=`${`pathname://${p.createUrl({locale:e,fullyQualified:!1})}`}${f}${m}${a}`;return{label:d[e].label,lang:d[e].htmlLang,to:n,target:"_self",autoAddBaseUrl:!1,className:e===i?t?"menu__link--active":"dropdown__link--active":""}})),...r],g=t?(0,l.I)({message:"Languages",id:"theme.navbar.mobileLanguageDropdown.label",description:"The label for the mobile language switcher dropdown"}):d[i].label;return(0,u.jsx)(fe,{...o,mobile:t,label:(0,u.jsxs)(u.Fragment,{children:[(0,u.jsx)(he,{className:ge}),g]}),items:h})},search:function(e){let{mobile:t,className:n}=e;return t?null:(0,u.jsx)(ve,{className:n,children:(0,u.jsx)(be.Z,{})})},dropdown:fe,html:function(e){let{value:t,className:n,mobile:r=!1,isDropdownItem:o=!1}=e;const i=o?"li":"div";return(0,u.jsx)(i,{className:(0,a.Z)({navbar__item:!r&&!o,"menu__list-item":r},n),dangerouslySetInnerHTML:{__html:t}})},doc:function(e){let{docId:t,label:n,docsPluginId:r,...a}=e;const{activeDoc:o}=(0,we.Iw)(r),i=(0,ke.vY)(t,r),s=o?.path===i?.path;return null===i||i.unlisted&&!s?null:(0,u.jsx)(oe,{exact:!0,...a,isActive:()=>s||!!o?.sidebar&&o.sidebar===i.sidebar,label:n??i.id,to:i.path})},docSidebar:function(e){let{sidebarId:t,label:n,docsPluginId:r,...a}=e;const{activeDoc:o}=(0,we.Iw)(r),i=(0,ke.oz)(t,r).link;if(!i)throw new Error(`DocSidebarNavbarItem: Sidebar with ID "${t}" doesn't have anything to be linked to.`);return(0,u.jsx)(oe,{exact:!0,...a,isActive:()=>o?.sidebar===t,label:n??i.label,to:i.path})},docsVersion:function(e){let{label:t,to:n,docsPluginId:r,...a}=e;const o=(0,ke.lO)(r)[0],i=t??o.label,s=n??(e=>e.docs.find((t=>t.id===e.mainDocId)))(o).path;return(0,u.jsx)(oe,{...a,label:i,to:s})},docsVersionDropdown:function(e){let{mobile:t,docsPluginId:n,dropdownActiveClassDisabled:r,dropdownItemsBefore:a,dropdownItemsAfter:o,...i}=e;const{search:c,hash:d}=(0,s.TH)(),p=(0,we.Iw)(n),f=(0,we.gB)(n),{savePreferredVersionName:m}=(0,xe.J)(n),h=[...a,...f.map((e=>{const t=p.alternateDocVersions[e.name]??Te(e);return{label:e.label,to:`${t.path}${c}${d}`,isActive:()=>e===p.activeVersion,onClick:()=>m(e.name)}})),...o],g=(0,ke.lO)(n)[0],b=t&&h.length>1?(0,l.I)({id:"theme.navbar.mobileVersionsDropdown.label",message:"Versions",description:"The label for the navbar versions dropdown on mobile view"}):g.label,y=t&&h.length>1?void 0:Te(g).path;return h.length<=1?(0,u.jsx)(oe,{...i,mobile:t,label:b,to:y,isActive:r?()=>!1:void 0}):(0,u.jsx)(fe,{...i,mobile:t,label:b,to:y,items:h,isActive:r?()=>!1:void 0})}};function Ee(e){let{type:t,...n}=e;const r=function(e,t){return e&&"default"!==e?e:"items"in t?"dropdown":"default"}(t,n),a=Se[r];if(!a)throw new Error(`No NavbarItem component found for type "${t}".`);return(0,u.jsx)(a,{...n})}function Ce(){const e=(0,j.e)(),t=(0,w.L)().navbar.items;return(0,u.jsx)("ul",{className:"menu__list",children:t.map(((t,n)=>(0,r.createElement)(Ee,{mobile:!0,...t,onClick:()=>e.toggle(),key:n})))})}function _e(e){return(0,u.jsx)("button",{...e,type:"button",className:"clean-btn navbar-sidebar__back",children:(0,u.jsx)(l.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)",children:"\u2190 Back to main menu"})})}function Ae(){const e=0===(0,w.L)().navbar.items.length,t=L();return(0,u.jsxs)(u.Fragment,{children:[!e&&(0,u.jsx)(_e,{onClick:()=>t.hide()}),t.content]})}function je(){const e=(0,j.e)();var t;return void 0===(t=e.shown)&&(t=!0),(0,r.useEffect)((()=>(document.body.style.overflow=t?"hidden":"visible",()=>{document.body.style.overflow="visible"})),[t]),e.shouldRender?(0,u.jsx)(B,{header:(0,u.jsx)(J,{}),primaryMenu:(0,u.jsx)(Ce,{}),secondaryMenu:(0,u.jsx)(Ae,{})}):null}const Re={navbarHideable:"navbarHideable_m1mJ",navbarHidden:"navbarHidden_jGov"};function Pe(e){return(0,u.jsx)("div",{role:"presentation",...e,className:(0,a.Z)("navbar-sidebar__backdrop",e.className)})}function De(e){let{children:t}=e;const{navbar:{hideOnScroll:n,style:o}}=(0,w.L)(),i=(0,j.e)(),{navbarRef:s,isNavbarVisible:d}=function(e){const[t,n]=(0,r.useState)(e),a=(0,r.useRef)(!1),o=(0,r.useRef)(0),i=(0,r.useCallback)((e=>{null!==e&&(o.current=e.getBoundingClientRect().height)}),[]);return(0,R.RF)(((t,r)=>{let{scrollY:i}=t;if(!e)return;if(i=s?n(!1):i+c{if(!e)return;const r=t.location.hash;if(r?document.getElementById(r.substring(1)):void 0)return a.current=!0,void n(!1);n(!0)})),{navbarRef:i,isNavbarVisible:t}}(n);return(0,u.jsxs)("nav",{ref:s,"aria-label":(0,l.I)({id:"theme.NavBar.navAriaLabel",message:"Main",description:"The ARIA label for the main navigation"}),className:(0,a.Z)("navbar","navbar--fixed-top",n&&[Re.navbarHideable,!d&&Re.navbarHidden],{"navbar--dark":"dark"===o,"navbar--primary":"primary"===o,"navbar-sidebar--show":i.shown}),children:[t,(0,u.jsx)(Pe,{onClick:i.toggle}),(0,u.jsx)(je,{})]})}var Ie=n(8780);const Ne={errorBoundaryError:"errorBoundaryError_a6uf",errorBoundaryFallback:"errorBoundaryFallback_VBag"};function Oe(e){return(0,u.jsx)("button",{type:"button",...e,children:(0,u.jsx)(l.Z,{id:"theme.ErrorPageContent.tryAgain",description:"The label of the button to try again rendering when the React error boundary captures an error",children:"Try again"})})}function Le(e){let{error:t}=e;const n=(0,Ie.getErrorCausalChain)(t).map((e=>e.message)).join("\n\nCause:\n");return(0,u.jsx)("p",{className:Ne.errorBoundaryError,children:n})}class Be extends r.Component{componentDidCatch(e,t){throw this.props.onError(e,t)}render(){return this.props.children}}const Fe="right";function Ue(e){let{width:t=30,height:n=30,className:r,...a}=e;return(0,u.jsx)("svg",{className:r,width:t,height:n,viewBox:"0 0 30 30","aria-hidden":"true",...a,children:(0,u.jsx)("path",{stroke:"currentColor",strokeLinecap:"round",strokeMiterlimit:"10",strokeWidth:"2",d:"M4 7h22M4 15h22M4 23h22"})})}function Me(){const{toggle:e,shown:t}=(0,j.e)();return(0,u.jsx)("button",{onClick:e,"aria-label":(0,l.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",children:(0,u.jsx)(Ue,{})})}const $e={colorModeToggle:"colorModeToggle_DEke"};function ze(e){let{items:t}=e;return(0,u.jsx)(u.Fragment,{children:t.map(((e,t)=>(0,u.jsx)(Be,{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}),children:(0,u.jsx)(Ee,{...e})},t)))})}function Ge(e){let{left:t,right:n}=e;return(0,u.jsxs)("div",{className:"navbar__inner",children:[(0,u.jsx)("div",{className:"navbar__items",children:t}),(0,u.jsx)("div",{className:"navbar__items navbar__items--right",children:n})]})}function qe(){const e=(0,j.e)(),t=(0,w.L)().navbar.items,[n,r]=function(e){function t(e){return"left"===(e.position??Fe)}return[e.filter(t),e.filter((e=>!t(e)))]}(t),a=t.find((e=>"search"===e.type));return(0,u.jsx)(Ge,{left:(0,u.jsxs)(u.Fragment,{children:[!e.disabled&&(0,u.jsx)(Me,{}),(0,u.jsx)(W,{}),(0,u.jsx)(ze,{items:n})]}),right:(0,u.jsxs)(u.Fragment,{children:[(0,u.jsx)(ze,{items:r}),(0,u.jsx)(Z,{className:$e.colorModeToggle}),!a&&(0,u.jsx)(ve,{children:(0,u.jsx)(be.Z,{})})]})})}function He(){return(0,u.jsx)(De,{children:(0,u.jsx)(qe,{})})}function Ze(e){let{item:t}=e;const{to:n,href:r,label:a,prependBaseUrlToHref:o,...i}=t,s=(0,Y.Z)(n),l=(0,Y.Z)(r,{forcePrependBaseUrl:!0});return(0,u.jsxs)(K.Z,{className:"footer__link-item",...r?{href:o?l:r}:{to:s},...i,children:[a,r&&!(0,X.Z)(r)&&(0,u.jsx)(te.Z,{})]})}function Ve(e){let{item:t}=e;return t.html?(0,u.jsx)("li",{className:"footer__item",dangerouslySetInnerHTML:{__html:t.html}}):(0,u.jsx)("li",{className:"footer__item",children:(0,u.jsx)(Ze,{item:t})},t.href??t.to)}function We(e){let{column:t}=e;return(0,u.jsxs)("div",{className:"col footer__col",children:[(0,u.jsx)("div",{className:"footer__title",children:t.title}),(0,u.jsx)("ul",{className:"footer__items clean-list",children:t.items.map(((e,t)=>(0,u.jsx)(Ve,{item:e},t)))})]})}function Qe(e){let{columns:t}=e;return(0,u.jsx)("div",{className:"row footer__links",children:t.map(((e,t)=>(0,u.jsx)(We,{column:e},t)))})}function Je(){return(0,u.jsx)("span",{className:"footer__link-separator",children:"\xb7"})}function Ke(e){let{item:t}=e;return t.html?(0,u.jsx)("span",{className:"footer__link-item",dangerouslySetInnerHTML:{__html:t.html}}):(0,u.jsx)(Ze,{item:t})}function Ye(e){let{links:t}=e;return(0,u.jsx)("div",{className:"footer__links text--center",children:(0,u.jsx)("div",{className:"footer__links",children:t.map(((e,n)=>(0,u.jsxs)(r.Fragment,{children:[(0,u.jsx)(Ke,{item:e}),t.length!==n+1&&(0,u.jsx)(Je,{})]},n)))})})}function Xe(e){let{links:t}=e;return function(e){return"title"in e[0]}(t)?(0,u.jsx)(Qe,{columns:t}):(0,u.jsx)(Ye,{links:t})}var et=n(9965);const tt={footerLogoLink:"footerLogoLink_BH7S"};function nt(e){let{logo:t}=e;const{withBaseUrl:n}=(0,Y.C)(),r={light:n(t.src),dark:n(t.srcDark??t.src)};return(0,u.jsx)(et.Z,{className:(0,a.Z)("footer__logo",t.className),alt:t.alt,sources:r,width:t.width,height:t.height,style:t.style})}function rt(e){let{logo:t}=e;return t.href?(0,u.jsx)(K.Z,{href:t.href,className:tt.footerLogoLink,target:t.target,children:(0,u.jsx)(nt,{logo:t})}):(0,u.jsx)(nt,{logo:t})}function at(e){let{copyright:t}=e;return(0,u.jsx)("div",{className:"footer__copyright",dangerouslySetInnerHTML:{__html:t}})}function ot(e){let{style:t,links:n,logo:r,copyright:o}=e;return(0,u.jsx)("footer",{className:(0,a.Z)("footer",{"footer--dark":"dark"===t}),children:(0,u.jsxs)("div",{className:"container container-fluid",children:[n,(r||o)&&(0,u.jsxs)("div",{className:"footer__bottom text--center",children:[r&&(0,u.jsx)("div",{className:"margin-bottom--sm",children:r}),o]})]})})}function it(){const{footer:e}=(0,w.L)();if(!e)return null;const{copyright:t,links:n,logo:r,style:a}=e;return(0,u.jsx)(ot,{style:a,links:n&&n.length>0&&(0,u.jsx)(Xe,{links:n}),logo:r&&(0,u.jsx)(rt,{logo:r}),copyright:t&&(0,u.jsx)(at,{copyright:t})})}const st=r.memo(it),lt=(0,P.Qc)([F.S,k.pl,R.OC,xe.L5,i.VC,function(e){let{children:t}=e;return(0,u.jsx)(D.n2,{children:(0,u.jsx)(j.M,{children:(0,u.jsx)(N,{children:t})})})}]);function ct(e){let{children:t}=e;return(0,u.jsx)(lt,{children:t})}var ut=n(2503);function dt(e){let{error:t,tryAgain:n}=e;return(0,u.jsx)("main",{className:"container margin-vert--xl",children:(0,u.jsx)("div",{className:"row",children:(0,u.jsxs)("div",{className:"col col--6 col--offset-3",children:[(0,u.jsx)(ut.Z,{as:"h1",className:"hero__title",children:(0,u.jsx)(l.Z,{id:"theme.ErrorPageContent.title",description:"The title of the fallback page when the page crashed",children:"This page crashed."})}),(0,u.jsx)("div",{className:"margin-vert--lg",children:(0,u.jsx)(Oe,{onClick:n,className:"button button--primary shadow--lw"})}),(0,u.jsx)("hr",{}),(0,u.jsx)("div",{className:"margin-vert--md",children:(0,u.jsx)(Le,{error:t})})]})})})}const pt={mainWrapper:"mainWrapper_z2l0"};function ft(e){const{children:t,noFooter:n,wrapperClassName:r,title:s,description:l}=e;return(0,b.t)(),(0,u.jsxs)(ct,{children:[(0,u.jsx)(i.d,{title:s,description:l}),(0,u.jsx)(v,{}),(0,u.jsx)(A,{}),(0,u.jsx)(He,{}),(0,u.jsx)("div",{id:d,className:(0,a.Z)(g.k.wrapper.main,pt.mainWrapper,r),children:(0,u.jsx)(o.Z,{fallback:e=>(0,u.jsx)(dt,{...e}),children:t})}),!n&&(0,u.jsx)(st,{})]})}},1327:(e,t,n)=>{"use strict";n.d(t,{Z:()=>u});n(7294);var r=n(3692),a=n(4996),o=n(2263),i=n(6668),s=n(9965),l=n(5893);function c(e){let{logo:t,alt:n,imageClassName:r}=e;const o={light:(0,a.Z)(t.src),dark:(0,a.Z)(t.srcDark||t.src)},i=(0,l.jsx)(s.Z,{className:t.className,sources:o,height:t.height,width:t.width,alt:n,style:t.style});return r?(0,l.jsx)("div",{className:r,children:i}):i}function u(e){const{siteConfig:{title:t}}=(0,o.Z)(),{navbar:{title:n,logo:s}}=(0,i.L)(),{imageClassName:u,titleClassName:d,...p}=e,f=(0,a.Z)(s?.href||"/"),m=n?"":t,h=s?.alt??m;return(0,l.jsxs)(r.Z,{to:f,...p,...s?.target&&{target:s.target},children:[s&&(0,l.jsx)(c,{logo:s,alt:h,imageClassName:u}),null!=n&&(0,l.jsx)("b",{className:d,children:n})]})}},197:(e,t,n)=>{"use strict";n.d(t,{Z:()=>o});n(7294);var r=n(5742),a=n(5893);function o(e){let{locale:t,version:n,tag:o}=e;const i=t;return(0,a.jsxs)(r.Z,{children:[t&&(0,a.jsx)("meta",{name:"docusaurus_locale",content:t}),n&&(0,a.jsx)("meta",{name:"docusaurus_version",content:n}),o&&(0,a.jsx)("meta",{name:"docusaurus_tag",content:o}),i&&(0,a.jsx)("meta",{name:"docsearch:language",content:i}),n&&(0,a.jsx)("meta",{name:"docsearch:version",content:n}),o&&(0,a.jsx)("meta",{name:"docsearch:docusaurus_tag",content:o})]})}},9965:(e,t,n)=>{"use strict";n.d(t,{Z:()=>u});var r=n(7294),a=n(512),o=n(2389),i=n(2949);const s={themedComponent:"themedComponent_mlkZ","themedComponent--light":"themedComponent--light_NVdE","themedComponent--dark":"themedComponent--dark_xIcU"};var l=n(5893);function c(e){let{className:t,children:n}=e;const c=(0,o.Z)(),{colorMode:u}=(0,i.I)();return(0,l.jsx)(l.Fragment,{children:(c?"dark"===u?["dark"]:["light"]:["light","dark"]).map((e=>{const o=n({theme:e,className:(0,a.Z)(t,s.themedComponent,s[`themedComponent--${e}`])});return(0,l.jsx)(r.Fragment,{children:o},e)}))})}function u(e){const{sources:t,className:n,alt:r,...a}=e;return(0,l.jsx)(c,{className:n,children:e=>{let{theme:n,className:o}=e;return(0,l.jsx)("img",{src:t[n],alt:r,className:o,...a})}})}},6043:(e,t,n)=>{"use strict";n.d(t,{u:()=>c,z:()=>b});var r=n(7294),a=n(412),o=n(469),i=n(1442),s=n(5893);const l="ease-in-out";function c(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 u={display:"none",overflow:"hidden",height:"0px"},d={display:"block",overflow:"visible",height:"auto"};function p(e,t){const n=t?u:d;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,i.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??l}`,height:`${t}px`}}function s(){const t=r();e.style.transition=t.transition,e.style.height=t.height}if(!o.current)return p(e,n),void(o.current=!0);return e.style.willChange="height",function(){const t=requestAnimationFrame((()=>{n?(s(),requestAnimationFrame((()=>{e.style.height=u.height,e.style.overflow=u.overflow}))):(e.style.display="block",requestAnimationFrame((()=>{s()})))}));return()=>cancelAnimationFrame(t)}()}),[t,n,a])}function m(e){if(!a.default.canUseDOM)return e?u:d}function h(e){let{as:t="div",collapsed:n,children:a,animation:o,onCollapseTransitionEnd:i,className:l,disableSSRStyle:c}=e;const u=(0,r.useRef)(null);return f({collapsibleRef:u,collapsed:n,animation:o}),(0,s.jsx)(t,{ref:u,style:c?void 0:m(n),onTransitionEnd:e=>{"height"===e.propertyName&&(p(u.current,n),i?.(n))},className:l,children:a})}function g(e){let{collapsed:t,...n}=e;const[a,i]=(0,r.useState)(!t),[l,c]=(0,r.useState)(t);return(0,o.Z)((()=>{t||i(!0)}),[t]),(0,o.Z)((()=>{a&&c(t)}),[a,t]),a?(0,s.jsx)(h,{...n,collapsed:l}):null}function b(e){let{lazy:t,...n}=e;const r=t?g:h;return(0,s.jsx)(r,{...n})}},9689:(e,t,n)=>{"use strict";n.d(t,{nT:()=>h,pl:()=>m});var r=n(7294),a=n(2389),o=n(12),i=n(902),s=n(6668),l=n(5893);const c=(0,o.WA)("docusaurus.announcement.dismiss"),u=(0,o.WA)("docusaurus.announcement.id"),d=()=>"true"===c.get(),p=e=>c.set(String(e)),f=r.createContext(null);function m(e){let{children:t}=e;const n=function(){const{announcementBar:e}=(0,s.L)(),t=(0,a.Z)(),[n,o]=(0,r.useState)((()=>!!t&&d()));(0,r.useEffect)((()=>{o(d())}),[]);const i=(0,r.useCallback)((()=>{p(!0),o(!0)}),[]);return(0,r.useEffect)((()=>{if(!e)return;const{id:t}=e;let n=u.get();"annoucement-bar"===n&&(n="announcement-bar");const r=t!==n;u.set(t),r&&p(!1),!r&&d()||o(!1)}),[e]),(0,r.useMemo)((()=>({isActive:!!e&&!n,close:i})),[e,n,i])}();return(0,l.jsx)(f.Provider,{value:n,children:t})}function h(){const e=(0,r.useContext)(f);if(!e)throw new i.i6("AnnouncementBarProvider");return e}},2949:(e,t,n)=>{"use strict";n.d(t,{I:()=>b,S:()=>g});var r=n(7294),a=n(412),o=n(902),i=n(12),s=n(6668),l=n(5893);const c=r.createContext(void 0),u="theme",d=(0,i.WA)(u),p={light:"light",dark:"dark"},f=e=>e===p.dark?p.dark:p.light,m=e=>a.default.canUseDOM?f(document.documentElement.getAttribute("data-theme")):f(e),h=e=>{d.set(f(e))};function g(e){let{children:t}=e;const n=function(){const{colorMode:{defaultMode:e,disableSwitch:t,respectPrefersColorScheme:n}}=(0,s.L)(),[a,o]=(0,r.useState)(m(e));(0,r.useEffect)((()=>{t&&d.del()}),[t]);const i=(0,r.useCallback)((function(t,r){void 0===r&&(r={});const{persist:a=!0}=r;t?(o(t),a&&h(t)):(o(n?window.matchMedia("(prefers-color-scheme: dark)").matches?p.dark:p.light:e),d.del())}),[n,e]);(0,r.useEffect)((()=>{document.documentElement.setAttribute("data-theme",f(a))}),[a]),(0,r.useEffect)((()=>{if(t)return;const e=e=>{if(e.key!==u)return;const t=d.get();null!==t&&i(f(t))};return window.addEventListener("storage",e),()=>window.removeEventListener("storage",e)}),[t,i]);const l=(0,r.useRef)(!1);return(0,r.useEffect)((()=>{if(t&&!n)return;const e=window.matchMedia("(prefers-color-scheme: dark)"),r=()=>{window.matchMedia("print").matches||l.current?l.current=window.matchMedia("print").matches:i(null)};return e.addListener(r),()=>e.removeListener(r)}),[i,t,n]),(0,r.useMemo)((()=>({colorMode:a,setColorMode:i,get isDarkTheme(){return a===p.dark},setLightTheme(){i(p.light)},setDarkTheme(){i(p.dark)}})),[a,i])}();return(0,l.jsx)(c.Provider,{value:n,children:t})}function b(){const e=(0,r.useContext)(c);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:()=>b});var r=n(7294),a=n(4104),o=n(9935),i=n(6668),s=n(2802),l=n(902),c=n(12),u=n(5893);const d=e=>`docs-preferred-version-${e}`,p={save:(e,t,n)=>{(0,c.WA)(d(e),{persistence:t}).set(n)},read:(e,t)=>(0,c.WA)(d(e),{persistence:t}).get(),clear:(e,t)=>{(0,c.WA)(d(e),{persistence:t}).del()}},f=e=>Object.fromEntries(e.map((e=>[e,{preferredVersionName:null}])));const m=r.createContext(null);function h(){const e=(0,a._r)(),t=(0,i.L)().docs.versionPersistence,n=(0,r.useMemo)((()=>Object.keys(e)),[e]),[o,s]=(0,r.useState)((()=>f(n)));(0,r.useEffect)((()=>{s(function(e){let{pluginIds:t,versionPersistence:n,allDocsData:r}=e;function a(e){const t=p.read(e,n);return r[e].versions.some((e=>e.name===t))?{preferredVersionName:t}:(p.clear(e,n),{preferredVersionName:null})}return Object.fromEntries(t.map((e=>[e,a(e)])))}({allDocsData:e,versionPersistence:t,pluginIds:n}))}),[e,t,n]);return[o,(0,r.useMemo)((()=>({savePreferredVersion:function(e,n){p.save(e,t,n),s((t=>({...t,[e]:{preferredVersionName:n}})))}})),[t])]}function g(e){let{children:t}=e;const n=h();return(0,u.jsx)(m.Provider,{value:n,children:t})}function b(e){let{children:t}=e;return s.cE?(0,u.jsx)(g,{children:t}):(0,u.jsx)(u.Fragment,{children:t})}function y(){const e=(0,r.useContext)(m);if(!e)throw new l.i6("DocsPreferredVersionContextProvider");return e}function v(e){void 0===e&&(e=o.m);const t=(0,a.zh)(e),[n,i]=y(),{preferredVersionName:s}=n[e];return{preferredVersion:t.versions.find((e=>e.name===s))??null,savePreferredVersionName:(0,r.useCallback)((t=>{i.savePreferredVersion(e,t)}),[i,e])}}},1116:(e,t,n)=>{"use strict";n.d(t,{V:()=>c,b:()=>l});var r=n(7294),a=n(902),o=n(5893);const i=Symbol("EmptyContext"),s=r.createContext(i);function l(e){let{children:t,name:n,items:a}=e;const i=(0,r.useMemo)((()=>n&&a?{name:n,items:a}:null),[n,a]);return(0,o.jsx)(s.Provider,{value:i,children:t})}function c(){const e=(0,r.useContext)(s);if(e===i)throw new a.i6("DocsSidebarProvider");return e}},4477:(e,t,n)=>{"use strict";n.d(t,{E:()=>l,q:()=>s});var r=n(7294),a=n(902),o=n(5893);const i=r.createContext(null);function s(e){let{children:t,version:n}=e;return(0,o.jsx)(i.Provider,{value:n,children:t})}function l(){const e=(0,r.useContext)(i);if(null===e)throw new a.i6("DocsVersionProvider");return e}},2961:(e,t,n)=>{"use strict";n.d(t,{M:()=>f,e:()=>m});var r=n(7294),a=n(3102),o=n(7524),i=n(6550),s=n(902);function l(e){!function(e){const t=(0,i.k6)(),n=(0,s.zX)(e);(0,r.useEffect)((()=>t.block(((e,t)=>n(e,t)))),[t,n])}(((t,n)=>{if("POP"===n)return e(t,n)}))}var c=n(6668),u=n(5893);const d=r.createContext(void 0);function p(){const e=function(){const e=(0,a.HY)(),{items:t}=(0,c.L)().navbar;return 0===t.length&&!e.component}(),t=(0,o.i)(),n=!e&&"mobile"===t,[i,s]=(0,r.useState)(!1);l((()=>{if(i)return s(!1),!1}));const u=(0,r.useCallback)((()=>{s((e=>!e))}),[]);return(0,r.useEffect)((()=>{"desktop"===t&&s(!1)}),[t]),(0,r.useMemo)((()=>({disabled:e,shouldRender:n,toggle:u,shown:i})),[e,n,u,i])}function f(e){let{children:t}=e;const n=p();return(0,u.jsx)(d.Provider,{value:n,children:t})}function m(){const e=r.useContext(d);if(void 0===e)throw new s.i6("NavbarMobileSidebarProvider");return e}},3102:(e,t,n)=>{"use strict";n.d(t,{HY:()=>l,Zo:()=>c,n2:()=>s});var r=n(7294),a=n(902),o=n(5893);const i=r.createContext(null);function s(e){let{children:t}=e;const n=(0,r.useState)({component:null,props:null});return(0,o.jsx)(i.Provider,{value:n,children:t})}function l(){const e=(0,r.useContext)(i);if(!e)throw new a.i6("NavbarSecondaryMenuContentProvider");return e[0]}function c(e){let{component:t,props:n}=e;const o=(0,r.useContext)(i);if(!o)throw new a.i6("NavbarSecondaryMenuContentProvider");const[,s]=o,l=(0,a.Ql)(n);return(0,r.useEffect)((()=>{s({component:t,props:l})}),[s,t,l]),(0,r.useEffect)((()=>()=>s({component:null,props:null})),[s]),null}},9727:(e,t,n)=>{"use strict";n.d(t,{h:()=>a,t:()=>o});var r=n(7294);const a="navigation-with-keyboard";function o(){(0,r.useEffect)((()=>{function e(e){"keydown"===e.type&&"Tab"===e.key&&document.body.classList.add(a),"mousedown"===e.type&&document.body.classList.remove(a)}return document.addEventListener("keydown",e),document.addEventListener("mousedown",e),()=>{document.body.classList.remove(a),document.removeEventListener("keydown",e),document.removeEventListener("mousedown",e)}}),[])}},7524:(e,t,n)=>{"use strict";n.d(t,{i:()=>s});var r=n(7294),a=n(412);const o={desktop:"desktop",mobile:"mobile",ssr:"ssr"},i=996;function s(e){let{desktopBreakpoint:t=i}=void 0===e?{}:e;const[n,s]=(0,r.useState)((()=>"ssr"));return(0,r.useEffect)((()=>{function e(){s(function(e){if(!a.default.canUseDOM)throw new Error("getWindowSize() should only be called after React hydration");return window.innerWidth>e?o.desktop:o.mobile}(t))}return e(),window.addEventListener("resize",e),()=>{window.removeEventListener("resize",e)}}),[t]),n}},5281:(e,t,n)=>{"use strict";n.d(t,{k:()=>r});const r={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",unlistedBanner:"theme-unlisted-banner",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 r(){return window.matchMedia("(prefers-reduced-motion: reduce)").matches}n.d(t,{n:()=>r})},2802:(e,t,n)=>{"use strict";n.d(t,{MN:()=>_,LM:()=>m,_F:()=>y,cE:()=>p,jA:()=>h,xz:()=>f,SN:()=>C,lO:()=>T,vY:()=>E,oz:()=>S,s1:()=>x,f:()=>w});var r=n(7294),a=n(6550),o=n(8790),i=n(4104),s=n(373),l=n(4477),c=n(1116);function u(e){return Array.from(new Set(e))}var d=n(8596);const p=!!i._r;function f(e){const t=(0,l.E)();if(!e)return;const n=t.docs[e];if(!n)throw new Error(`no version doc found by id=${e}`);return n}function m(e){return"link"!==e.type||e.unlisted?"category"===e.type?function(e){if(e.href&&!e.linkUnlisted)return e.href;for(const t of e.items){const e=m(t);if(e)return e}}(e):void 0:e.href}function h(){const{pathname:e}=(0,a.TH)(),t=(0,c.V)();if(!t)throw new Error("Unexpected: cant find current sidebar in context");const n=k({sidebarItems:t.items,pathname:e,onlyCategories:!0}).slice(-1)[0];if(!n)throw new Error(`${e} is not associated with a category. useCurrentSidebarCategory() should only be used on category index pages.`);return n}const g=(e,t)=>void 0!==e&&(0,d.Mg)(e,t),b=(e,t)=>e.some((e=>y(e,t)));function y(e,t){return"link"===e.type?g(e.href,t):"category"===e.type&&(g(e.href,t)||b(e.items,t))}function v(e,t){switch(e.type){case"category":return y(e,t)||e.items.some((e=>v(e,t)));case"link":return!e.unlisted||y(e,t);default:return!0}}function w(e,t){return(0,r.useMemo)((()=>e.filter((e=>v(e,t)))),[e,t])}function k(e){let{sidebarItems:t,pathname:n,onlyCategories:r=!1}=e;const a=[];return function e(t){for(const o of t)if("category"===o.type&&((0,d.Mg)(o.href,n)||e(o.items))||"link"===o.type&&(0,d.Mg)(o.href,n)){return r&&"category"!==o.type||a.unshift(o),!0}return!1}(t),a}function x(){const e=(0,c.V)(),{pathname:t}=(0,a.TH)(),n=(0,i.gA)()?.pluginData.breadcrumbs;return!1!==n&&e?k({sidebarItems:e.items,pathname:t}):null}function T(e){const{activeVersion:t}=(0,i.Iw)(e),{preferredVersion:n}=(0,s.J)(e),a=(0,i.yW)(e);return(0,r.useMemo)((()=>u([t,n,a].filter(Boolean))),[t,n,a])}function S(e,t){const n=T(t);return(0,r.useMemo)((()=>{const t=n.flatMap((e=>e.sidebars?Object.entries(e.sidebars):[])),r=t.find((t=>t[0]===e));if(!r)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 r[1]}),[e,n])}function E(e,t){const n=T(t);return(0,r.useMemo)((()=>{const t=n.flatMap((e=>e.docs)),r=t.find((t=>t.id===e));if(!r){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- ${u(t.map((e=>e.id))).join("\n- ")}`)}return r}),[e,n])}function C(e){let{route:t}=e;const n=(0,a.TH)(),r=(0,l.E)(),i=t.routes,s=i.find((e=>(0,a.LX)(n.pathname,e)));if(!s)return null;const c=s.sidebar,u=c?r.docsSidebars[c]:void 0;return{docElement:(0,o.H)(i),sidebarName:c,sidebarItems:u}}function _(e){return e.filter((e=>!("category"===e.type||"link"===e.type)||!!m(e)))}},1944:(e,t,n)=>{"use strict";n.d(t,{FG:()=>f,d:()=>d,VC:()=>m});var r=n(7294),a=n(512),o=n(5742),i=n(226);function s(){const e=r.useContext(i._);if(!e)throw new Error("Unexpected: no Docusaurus route context found");return e}var l=n(4996),c=n(2263);var u=n(5893);function d(e){let{title:t,description:n,keywords:r,image:a,children:i}=e;const s=function(e){const{siteConfig:t}=(0,c.Z)(),{title:n,titleDelimiter:r}=t;return e?.trim().length?`${e.trim()} ${r} ${n}`:n}(t),{withBaseUrl:d}=(0,l.C)(),p=a?d(a,{absolute:!0}):void 0;return(0,u.jsxs)(o.Z,{children:[t&&(0,u.jsx)("title",{children:s}),t&&(0,u.jsx)("meta",{property:"og:title",content:s}),n&&(0,u.jsx)("meta",{name:"description",content:n}),n&&(0,u.jsx)("meta",{property:"og:description",content:n}),r&&(0,u.jsx)("meta",{name:"keywords",content:Array.isArray(r)?r.join(","):r}),p&&(0,u.jsx)("meta",{property:"og:image",content:p}),p&&(0,u.jsx)("meta",{name:"twitter:image",content:p}),i]})}const p=r.createContext(void 0);function f(e){let{className:t,children:n}=e;const i=r.useContext(p),s=(0,a.Z)(i,t);return(0,u.jsxs)(p.Provider,{value:s,children:[(0,u.jsx)(o.Z,{children:(0,u.jsx)("html",{className:s})}),n]})}function m(e){let{children:t}=e;const n=s(),r=`plugin-${n.plugin.name.replace(/docusaurus-(?:plugin|theme)-(?:content-)?/gi,"")}`;const o=`plugin-id-${n.plugin.id}`;return(0,u.jsx)(f,{className:(0,a.Z)(r,o),children:t})}},902:(e,t,n)=>{"use strict";n.d(t,{D9:()=>s,Qc:()=>u,Ql:()=>c,i6:()=>l,zX:()=>i});var r=n(7294),a=n(469),o=n(5893);function i(e){const t=(0,r.useRef)(e);return(0,a.Z)((()=>{t.current=e}),[e]),(0,r.useCallback)((function(){return t.current(...arguments)}),[])}function s(e){const t=(0,r.useRef)();return(0,a.Z)((()=>{t.current=e})),t.current}class l extends Error{constructor(e,t){super(),this.name="ReactContextError",this.message=`Hook ${this.stack?.split("\n")[1]?.match(/at (?:\w+\.)?(?\w+)/)?.groups.name??""} is called outside the <${e}>. ${t??""}`}}function c(e){const t=Object.entries(e);return t.sort(((e,t)=>e[0].localeCompare(t[0]))),(0,r.useMemo)((()=>e),t.flat())}function u(e){return t=>{let{children:n}=t;return(0,o.jsx)(o.Fragment,{children:e.reduceRight(((e,t)=>(0,o.jsx)(t,{children:e})),n)})}}},8596:(e,t,n)=>{"use strict";n.d(t,{Mg:()=>i,Ns:()=>s});var r=n(7294),a=n(723),o=n(2263);function i(e,t){const n=e=>(!e||e.endsWith("/")?e:`${e}/`)?.toLowerCase();return n(e)===n(t)}function s(){const{baseUrl:e}=(0,o.Z)().siteConfig;return(0,r.useMemo)((()=>function(e){let{baseUrl:t,routes:n}=e;function r(e){return e.path===t&&!0===e.exact}function a(e){return e.path===t&&!e.exact}return function e(t){if(0===t.length)return;return t.find(r)||e(t.filter(a).flatMap((e=>e.routes??[])))}(n)}({routes:a.Z,baseUrl:e})),[e])}},2466:(e,t,n)=>{"use strict";n.d(t,{Ct:()=>f,OC:()=>c,RF:()=>p});var r=n(7294),a=n(412),o=n(2389),i=(n(469),n(902)),s=n(5893);const l=r.createContext(void 0);function c(e){let{children:t}=e;const n=function(){const e=(0,r.useRef)(!0);return(0,r.useMemo)((()=>({scrollEventsEnabledRef:e,enableScrollEvents:()=>{e.current=!0},disableScrollEvents:()=>{e.current=!1}})),[])}();return(0,s.jsx)(l.Provider,{value:n,children:t})}function u(){const e=(0,r.useContext)(l);if(null==e)throw new i.i6("ScrollControllerProvider");return e}const d=()=>a.default.canUseDOM?{scrollX:window.pageXOffset,scrollY:window.pageYOffset}:null;function p(e,t){void 0===t&&(t=[]);const{scrollEventsEnabledRef:n}=u(),a=(0,r.useRef)(d()),o=(0,i.zX)(e);(0,r.useEffect)((()=>{const e=()=>{if(!n.current)return;const e=d();o(e,a.current),a.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,r.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 r(){const a=document.documentElement.scrollTop;(n&&a>e||!n&&at&&cancelAnimationFrame(t)}(n)},cancelScroll:()=>e.current?.()}}},3320:(e,t,n)=>{"use strict";n.d(t,{HX:()=>r,os:()=>a});n(2263);const r="default";function a(e,t){return`docs-${e}-${t}`}},12:(e,t,n)=>{"use strict";n.d(t,{WA:()=>l});n(7294);const r="localStorage";function a(e){let{key:t,oldValue:n,newValue:r,storage:a}=e;if(n===r)return;const o=document.createEvent("StorageEvent");o.initStorageEvent("storage",!1,!1,t,n,r,window.location.href,a),window.dispatchEvent(o)}function o(e){if(void 0===e&&(e=r),"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,i||(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),i=!0),null}var t}let i=!1;const s={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?s:{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 r=n.getItem(e);n.setItem(e,t),a({key:e,oldValue:r,newValue:t,storage:n})}catch(r){console.error(`Docusaurus storage error, can't set ${e}=${t}`,r)}},del:()=>{try{const t=n.getItem(e);n.removeItem(e),a({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 r=r=>{r.storageArea===n&&r.key===e&&t(r)};return window.addEventListener("storage",r),()=>window.removeEventListener("storage",r)}catch(r){return console.error(`Docusaurus storage error, can't listen for changes of key=${e}`,r),()=>{}}}}}},4711:(e,t,n)=>{"use strict";n.d(t,{l:()=>i});var r=n(2263),a=n(6550),o=n(8780);function i(){const{siteConfig:{baseUrl:e,url:t,trailingSlash:n},i18n:{defaultLocale:i,currentLocale:s}}=(0,r.Z)(),{pathname:l}=(0,a.TH)(),c=(0,o.applyTrailingSlash)(l,{trailingSlash:n,baseUrl:e}),u=s===i?e:e.replace(`/${s}/`,"/"),d=c.replace(e,"");return{createUrl:function(e){let{locale:n,fullyQualified:r}=e;return`${r?t:""}${function(e){return e===i?`${u}`:`${u}${e}/`}(n)}${d}`}}}},5936:(e,t,n)=>{"use strict";n.d(t,{S:()=>i});var r=n(7294),a=n(6550),o=n(902);function i(e){const t=(0,a.TH)(),n=(0,o.D9)(t),i=(0,o.zX)(e);(0,r.useEffect)((()=>{n&&t!==n&&i({location:t,previousLocation:n})}),[i,t,n])}},6668:(e,t,n)=>{"use strict";n.d(t,{L:()=>a});var r=n(2263);function a(){return(0,r.Z)().siteConfig.themeConfig}},8802:(e,t)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(e,t){const{trailingSlash:n,baseUrl:r}=t;if(e.startsWith("#"))return e;if(void 0===n)return e;const[a]=e.split(/[#?]/),o="/"===a||a===r?a:(i=a,n?function(e){return e.endsWith("/")?e:`${e}/`}(i):function(e){return e.endsWith("/")?e.slice(0,-1):e}(i));var i;return e.replace(a,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 r=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 a=n(8802);Object.defineProperty(t,"applyTrailingSlash",{enumerable:!0,get:function(){return r(a).default}});var o=n(4143);Object.defineProperty(t,"getErrorCausalChain",{enumerable:!0,get:function(){return o.getErrorCausalChain}})},4750:function(e,t,n){"use strict";var r=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});r(n(412)).default.canUseDOM&&(window.Prism=window.Prism||{},window.Prism.manual=!0)},9318:(e,t,n)=>{"use strict";n.d(t,{lX:()=>w,q_:()=>C,ob:()=>f,PP:()=>A,Ep:()=>p});var r=n(7462);function a(e){return"/"===e.charAt(0)}function o(e,t){for(var n=t,r=n+1,a=e.length;r=0;p--){var f=i[p];"."===f?o(i,p):".."===f?(o(i,p),d++):d&&(o(i,p),d--)}if(!c)for(;d--;d)i.unshift("..");!c||""===i[0]||i[0]&&a(i[0])||i.unshift("");var m=i.join("/");return n&&"/"!==m.substr(-1)&&(m+="/"),m};var s=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 p(e){var t=e.pathname,n=e.search,r=e.hash,a=t||"/";return n&&"?"!==n&&(a+="?"===n.charAt(0)?n:"?"+n),r&&"#"!==r&&(a+="#"===r.charAt(0)?r:"#"+r),a}function f(e,t,n,a){var o;"string"==typeof e?(o=function(e){var t=e||"/",n="",r="",a=t.indexOf("#");-1!==a&&(r=t.substr(a),t=t.substr(0,a));var o=t.indexOf("?");return-1!==o&&(n=t.substr(o),t=t.substr(0,o)),{pathname:t,search:"?"===n?"":n,hash:"#"===r?"":r}}(e),o.state=t):(void 0===(o=(0,r.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(s){throw s instanceof URIError?new URIError('Pathname "'+o.pathname+'" could not be decoded. This is likely caused by an invalid percent-encoding.'):s}return n&&(o.key=n),a?o.pathname?"/"!==o.pathname.charAt(0)&&(o.pathname=i(o.pathname,a.pathname)):o.pathname=a.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,r,a){if(null!=e){var o="function"==typeof e?e(t,n):e;"string"==typeof o?"function"==typeof r?r(o,a):a(!0):a(!1!==o)}else a(!0)},appendListener:function(e){var n=!0;function r(){n&&e.apply(void 0,arguments)}return t.push(r),function(){n=!1,t=t.filter((function(e){return e!==r}))}},notifyListeners:function(){for(var e=arguments.length,n=new Array(e),r=0;rt?n.splice(t,n.length-t,a):n.push(a),d({action:r,location:a,index:t,entries:n})}}))},replace:function(e,t){var r="REPLACE",a=f(e,t,h(),w.location);u.confirmTransitionTo(a,r,n,(function(e){e&&(w.entries[w.index]=a,d({action:r,location:a}))}))},go:v,goBack:function(){v(-1)},goForward:function(){v(1)},canGo:function(e){var t=w.index+e;return t>=0&&t{"use strict";var r=n(9864),a={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},i={$$typeof:!0,compare:!0,defaultProps:!0,displayName:!0,propTypes:!0,type:!0},s={};function l(e){return r.isMemo(e)?i:s[e.$$typeof]||a}s[r.ForwardRef]={$$typeof:!0,render:!0,defaultProps:!0,displayName:!0,propTypes:!0},s[r.Memo]=i;var c=Object.defineProperty,u=Object.getOwnPropertyNames,d=Object.getOwnPropertySymbols,p=Object.getOwnPropertyDescriptor,f=Object.getPrototypeOf,m=Object.prototype;e.exports=function e(t,n,r){if("string"!=typeof n){if(m){var a=f(n);a&&a!==m&&e(t,a,r)}var i=u(n);d&&(i=i.concat(d(n)));for(var s=l(t),h=l(n),g=0;g{"use strict";e.exports=function(e,t,n,r,a,o,i,s){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,r,a,o,i,s],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)}},1304:(e,t,n)=>{"use strict";n.r(t)},2497:(e,t,n)=>{"use strict";n.r(t)},2295:(e,t,n)=>{"use strict";n.r(t)},4865:function(e,t,n){var r,a;r=function(){var e,t,n={version:"0.2.0"},r=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:'
'};function a(e,t,n){return en?n:e}function o(e){return 100*(-1+e)}function i(e,t,n){var a;return(a="translate3d"===r.positionUsing?{transform:"translate3d("+o(e)+"%,0,0)"}:"translate"===r.positionUsing?{transform:"translate("+o(e)+"%,0)"}:{"margin-left":o(e)+"%"}).transition="all "+t+"ms "+n,a}n.configure=function(e){var t,n;for(t in e)void 0!==(n=e[t])&&e.hasOwnProperty(t)&&(r[t]=n);return this},n.status=null,n.set=function(e){var t=n.isStarted();e=a(e,r.minimum,1),n.status=1===e?null:e;var o=n.render(!t),c=o.querySelector(r.barSelector),u=r.speed,d=r.easing;return o.offsetWidth,s((function(t){""===r.positionUsing&&(r.positionUsing=n.getPositioningCSS()),l(c,i(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())}),r.trickleSpeed)};return r.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)*a(Math.random()*t,.1,.95)),t=a(t+e,0,.994),n.set(t)):n.start()},n.trickle=function(){return n.inc(Math.random()*r.trickleRate)},e=0,t=0,n.promise=function(r){return r&&"resolved"!==r.state()?(0===t&&n.start(),e++,t++,r.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=r.template;var a,i=t.querySelector(r.barSelector),s=e?"-100":o(n.status||0),c=document.querySelector(r.parent);return l(i,{transition:"all 0 linear",transform:"translate3d("+s+"%,0,0)"}),r.showSpinner||(a=t.querySelector(r.spinnerSelector))&&f(a),c!=document.body&&u(c,"nprogress-custom-parent"),c.appendChild(t),t},n.remove=function(){d(document.documentElement,"nprogress-busy"),d(document.querySelector(r.parent),"nprogress-custom-parent");var e=document.getElementById("nprogress");e&&f(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 s=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 r(t){var n=document.body.style;if(t in n)return t;for(var r,a=e.length,o=t.charAt(0).toUpperCase()+t.slice(1);a--;)if((r=e[a]+o)in n)return r;return t}function a(e){return e=n(e),t[e]||(t[e]=r(e))}function o(e,t,n){t=a(t),e.style[t]=n}return function(e,t){var n,r,a=arguments;if(2==a.length)for(n in t)void 0!==(r=t[n])&&t.hasOwnProperty(n)&&o(e,n,r);else o(e,a[1],a[2])}}();function c(e,t){return("string"==typeof e?e:p(e)).indexOf(" "+t+" ")>=0}function u(e,t){var n=p(e),r=n+t;c(n,t)||(e.className=r.substring(1))}function d(e,t){var n,r=p(e);c(e,t)&&(n=r.replace(" "+t+" "," "),e.className=n.substring(1,n.length-1))}function p(e){return(" "+(e.className||"")+" ").replace(/\s+/gi," ")}function f(e){e&&e.parentNode&&e.parentNode.removeChild(e)}return n},void 0===(a="function"==typeof r?r.call(t,n,t,e):r)||(e.exports=a)},4779:(e,t,n)=>{var r=n(5826);e.exports=f,e.exports.parse=o,e.exports.compile=function(e,t){return s(o(e,t),t)},e.exports.tokensToFunction=s,e.exports.tokensToRegExp=p;var a=new RegExp(["(\\\\.)","([\\/.])?(?:(?:\\:(\\w+)(?:\\(((?:\\\\.|[^\\\\()])+)\\))?|\\(((?:\\\\.|[^\\\\()])+)\\))([+*?])?|(\\*))"].join("|"),"g");function o(e,t){for(var n,r=[],o=0,i=0,s="",u=t&&t.delimiter||"/";null!=(n=a.exec(e));){var d=n[0],p=n[1],f=n.index;if(s+=e.slice(i,f),i=f+d.length,p)s+=p[1];else{var m=e[i],h=n[2],g=n[3],b=n[4],y=n[5],v=n[6],w=n[7];s&&(r.push(s),s="");var k=null!=h&&null!=m&&m!==h,x="+"===v||"*"===v,T="?"===v||"*"===v,S=n[2]||u,E=b||y;r.push({name:g||o++,prefix:h||"",delimiter:S,optional:T,repeat:x,partial:k,asterisk:!!w,pattern:E?c(E):w?".*":"[^"+l(S)+"]+?"})}}return i{e.exports&&(e.exports={core:{meta:{path:"components/prism-core.js",option:"mandatory"},core:"Core"},themes:{meta:{path:"themes/{id}.css",link:"index.html?theme={id}",exclusive:!0},prism:{title:"Default",option:"default"},"prism-dark":"Dark","prism-funky":"Funky","prism-okaidia":{title:"Okaidia",owner:"ocodia"},"prism-twilight":{title:"Twilight",owner:"remybach"},"prism-coy":{title:"Coy",owner:"tshedor"},"prism-solarizedlight":{title:"Solarized Light",owner:"hectormatos2011 "},"prism-tomorrow":{title:"Tomorrow Night",owner:"Rosey"}},languages:{meta:{path:"components/prism-{id}",noCSS:!0,examplesPath:"examples/prism-{id}",addCheckAll:!0},markup:{title:"Markup",alias:["html","xml","svg","mathml","ssml","atom","rss"],aliasTitles:{html:"HTML",xml:"XML",svg:"SVG",mathml:"MathML",ssml:"SSML",atom:"Atom",rss:"RSS"},option:"default"},css:{title:"CSS",option:"default",modify:"markup"},clike:{title:"C-like",option:"default"},javascript:{title:"JavaScript",require:"clike",modify:"markup",optional:"regex",alias:"js",option:"default"},abap:{title:"ABAP",owner:"dellagustin"},abnf:{title:"ABNF",owner:"RunDevelopment"},actionscript:{title:"ActionScript",require:"javascript",modify:"markup",owner:"Golmote"},ada:{title:"Ada",owner:"Lucretia"},agda:{title:"Agda",owner:"xy-ren"},al:{title:"AL",owner:"RunDevelopment"},antlr4:{title:"ANTLR4",alias:"g4",owner:"RunDevelopment"},apacheconf:{title:"Apache Configuration",owner:"GuiTeK"},apex:{title:"Apex",require:["clike","sql"],owner:"RunDevelopment"},apl:{title:"APL",owner:"ngn"},applescript:{title:"AppleScript",owner:"Golmote"},aql:{title:"AQL",owner:"RunDevelopment"},arduino:{title:"Arduino",require:"cpp",alias:"ino",owner:"dkern"},arff:{title:"ARFF",owner:"Golmote"},armasm:{title:"ARM Assembly",alias:"arm-asm",owner:"RunDevelopment"},arturo:{title:"Arturo",alias:"art",optional:["bash","css","javascript","markup","markdown","sql"],owner:"drkameleon"},asciidoc:{alias:"adoc",title:"AsciiDoc",owner:"Golmote"},aspnet:{title:"ASP.NET (C#)",require:["markup","csharp"],owner:"nauzilus"},asm6502:{title:"6502 Assembly",owner:"kzurawel"},asmatmel:{title:"Atmel AVR Assembly",owner:"cerkit"},autohotkey:{title:"AutoHotkey",owner:"aviaryan"},autoit:{title:"AutoIt",owner:"Golmote"},avisynth:{title:"AviSynth",alias:"avs",owner:"Zinfidel"},"avro-idl":{title:"Avro IDL",alias:"avdl",owner:"RunDevelopment"},awk:{title:"AWK",alias:"gawk",aliasTitles:{gawk:"GAWK"},owner:"RunDevelopment"},bash:{title:"Bash",alias:["sh","shell"],aliasTitles:{sh:"Shell",shell:"Shell"},owner:"zeitgeist87"},basic:{title:"BASIC",owner:"Golmote"},batch:{title:"Batch",owner:"Golmote"},bbcode:{title:"BBcode",alias:"shortcode",aliasTitles:{shortcode:"Shortcode"},owner:"RunDevelopment"},bbj:{title:"BBj",owner:"hyyan"},bicep:{title:"Bicep",owner:"johnnyreilly"},birb:{title:"Birb",require:"clike",owner:"Calamity210"},bison:{title:"Bison",require:"c",owner:"Golmote"},bnf:{title:"BNF",alias:"rbnf",aliasTitles:{rbnf:"RBNF"},owner:"RunDevelopment"},bqn:{title:"BQN",owner:"yewscion"},brainfuck:{title:"Brainfuck",owner:"Golmote"},brightscript:{title:"BrightScript",owner:"RunDevelopment"},bro:{title:"Bro",owner:"wayward710"},bsl:{title:"BSL (1C:Enterprise)",alias:"oscript",aliasTitles:{oscript:"OneScript"},owner:"Diversus23"},c:{title:"C",require:"clike",owner:"zeitgeist87"},csharp:{title:"C#",require:"clike",alias:["cs","dotnet"],owner:"mvalipour"},cpp:{title:"C++",require:"c",owner:"zeitgeist87"},cfscript:{title:"CFScript",require:"clike",alias:"cfc",owner:"mjclemente"},chaiscript:{title:"ChaiScript",require:["clike","cpp"],owner:"RunDevelopment"},cil:{title:"CIL",owner:"sbrl"},cilkc:{title:"Cilk/C",require:"c",alias:"cilk-c",owner:"OpenCilk"},cilkcpp:{title:"Cilk/C++",require:"cpp",alias:["cilk-cpp","cilk"],owner:"OpenCilk"},clojure:{title:"Clojure",owner:"troglotit"},cmake:{title:"CMake",owner:"mjrogozinski"},cobol:{title:"COBOL",owner:"RunDevelopment"},coffeescript:{title:"CoffeeScript",require:"javascript",alias:"coffee",owner:"R-osey"},concurnas:{title:"Concurnas",alias:"conc",owner:"jasontatton"},csp:{title:"Content-Security-Policy",owner:"ScottHelme"},cooklang:{title:"Cooklang",owner:"ahue"},coq:{title:"Coq",owner:"RunDevelopment"},crystal:{title:"Crystal",require:"ruby",owner:"MakeNowJust"},"css-extras":{title:"CSS Extras",require:"css",modify:"css",owner:"milesj"},csv:{title:"CSV",owner:"RunDevelopment"},cue:{title:"CUE",owner:"RunDevelopment"},cypher:{title:"Cypher",owner:"RunDevelopment"},d:{title:"D",require:"clike",owner:"Golmote"},dart:{title:"Dart",require:"clike",owner:"Golmote"},dataweave:{title:"DataWeave",owner:"machaval"},dax:{title:"DAX",owner:"peterbud"},dhall:{title:"Dhall",owner:"RunDevelopment"},diff:{title:"Diff",owner:"uranusjr"},django:{title:"Django/Jinja2",require:"markup-templating",alias:"jinja2",owner:"romanvm"},"dns-zone-file":{title:"DNS zone file",owner:"RunDevelopment",alias:"dns-zone"},docker:{title:"Docker",alias:"dockerfile",owner:"JustinBeckwith"},dot:{title:"DOT (Graphviz)",alias:"gv",optional:"markup",owner:"RunDevelopment"},ebnf:{title:"EBNF",owner:"RunDevelopment"},editorconfig:{title:"EditorConfig",owner:"osipxd"},eiffel:{title:"Eiffel",owner:"Conaclos"},ejs:{title:"EJS",require:["javascript","markup-templating"],owner:"RunDevelopment",alias:"eta",aliasTitles:{eta:"Eta"}},elixir:{title:"Elixir",owner:"Golmote"},elm:{title:"Elm",owner:"zwilias"},etlua:{title:"Embedded Lua templating",require:["lua","markup-templating"],owner:"RunDevelopment"},erb:{title:"ERB",require:["ruby","markup-templating"],owner:"Golmote"},erlang:{title:"Erlang",owner:"Golmote"},"excel-formula":{title:"Excel Formula",alias:["xlsx","xls"],owner:"RunDevelopment"},fsharp:{title:"F#",require:"clike",owner:"simonreynolds7"},factor:{title:"Factor",owner:"catb0t"},false:{title:"False",owner:"edukisto"},"firestore-security-rules":{title:"Firestore security rules",require:"clike",owner:"RunDevelopment"},flow:{title:"Flow",require:"javascript",owner:"Golmote"},fortran:{title:"Fortran",owner:"Golmote"},ftl:{title:"FreeMarker Template Language",require:"markup-templating",owner:"RunDevelopment"},gml:{title:"GameMaker Language",alias:"gamemakerlanguage",require:"clike",owner:"LiarOnce"},gap:{title:"GAP (CAS)",owner:"RunDevelopment"},gcode:{title:"G-code",owner:"RunDevelopment"},gdscript:{title:"GDScript",owner:"RunDevelopment"},gedcom:{title:"GEDCOM",owner:"Golmote"},gettext:{title:"gettext",alias:"po",owner:"RunDevelopment"},gherkin:{title:"Gherkin",owner:"hason"},git:{title:"Git",owner:"lgiraudel"},glsl:{title:"GLSL",require:"c",owner:"Golmote"},gn:{title:"GN",alias:"gni",owner:"RunDevelopment"},"linker-script":{title:"GNU Linker Script",alias:"ld",owner:"RunDevelopment"},go:{title:"Go",require:"clike",owner:"arnehormann"},"go-module":{title:"Go module",alias:"go-mod",owner:"RunDevelopment"},gradle:{title:"Gradle",require:"clike",owner:"zeabdelkhalek-badido18"},graphql:{title:"GraphQL",optional:"markdown",owner:"Golmote"},groovy:{title:"Groovy",require:"clike",owner:"robfletcher"},haml:{title:"Haml",require:"ruby",optional:["css","css-extras","coffeescript","erb","javascript","less","markdown","scss","textile"],owner:"Golmote"},handlebars:{title:"Handlebars",require:"markup-templating",alias:["hbs","mustache"],aliasTitles:{mustache:"Mustache"},owner:"Golmote"},haskell:{title:"Haskell",alias:"hs",owner:"bholst"},haxe:{title:"Haxe",require:"clike",optional:"regex",owner:"Golmote"},hcl:{title:"HCL",owner:"outsideris"},hlsl:{title:"HLSL",require:"c",owner:"RunDevelopment"},hoon:{title:"Hoon",owner:"matildepark"},http:{title:"HTTP",optional:["csp","css","hpkp","hsts","javascript","json","markup","uri"],owner:"danielgtaylor"},hpkp:{title:"HTTP Public-Key-Pins",owner:"ScottHelme"},hsts:{title:"HTTP Strict-Transport-Security",owner:"ScottHelme"},ichigojam:{title:"IchigoJam",owner:"BlueCocoa"},icon:{title:"Icon",owner:"Golmote"},"icu-message-format":{title:"ICU Message Format",owner:"RunDevelopment"},idris:{title:"Idris",alias:"idr",owner:"KeenS",require:"haskell"},ignore:{title:".ignore",owner:"osipxd",alias:["gitignore","hgignore","npmignore"],aliasTitles:{gitignore:".gitignore",hgignore:".hgignore",npmignore:".npmignore"}},inform7:{title:"Inform 7",owner:"Golmote"},ini:{title:"Ini",owner:"aviaryan"},io:{title:"Io",owner:"AlesTsurko"},j:{title:"J",owner:"Golmote"},java:{title:"Java",require:"clike",owner:"sherblot"},javadoc:{title:"JavaDoc",require:["markup","java","javadoclike"],modify:"java",optional:"scala",owner:"RunDevelopment"},javadoclike:{title:"JavaDoc-like",modify:["java","javascript","php"],owner:"RunDevelopment"},javastacktrace:{title:"Java stack trace",owner:"RunDevelopment"},jexl:{title:"Jexl",owner:"czosel"},jolie:{title:"Jolie",require:"clike",owner:"thesave"},jq:{title:"JQ",owner:"RunDevelopment"},jsdoc:{title:"JSDoc",require:["javascript","javadoclike","typescript"],modify:"javascript",optional:["actionscript","coffeescript"],owner:"RunDevelopment"},"js-extras":{title:"JS Extras",require:"javascript",modify:"javascript",optional:["actionscript","coffeescript","flow","n4js","typescript"],owner:"RunDevelopment"},json:{title:"JSON",alias:"webmanifest",aliasTitles:{webmanifest:"Web App Manifest"},owner:"CupOfTea696"},json5:{title:"JSON5",require:"json",owner:"RunDevelopment"},jsonp:{title:"JSONP",require:"json",owner:"RunDevelopment"},jsstacktrace:{title:"JS stack trace",owner:"sbrl"},"js-templates":{title:"JS Templates",require:"javascript",modify:"javascript",optional:["css","css-extras","graphql","markdown","markup","sql"],owner:"RunDevelopment"},julia:{title:"Julia",owner:"cdagnino"},keepalived:{title:"Keepalived Configure",owner:"dev-itsheng"},keyman:{title:"Keyman",owner:"mcdurdin"},kotlin:{title:"Kotlin",alias:["kt","kts"],aliasTitles:{kts:"Kotlin Script"},require:"clike",owner:"Golmote"},kumir:{title:"KuMir (\u041a\u0443\u041c\u0438\u0440)",alias:"kum",owner:"edukisto"},kusto:{title:"Kusto",owner:"RunDevelopment"},latex:{title:"LaTeX",alias:["tex","context"],aliasTitles:{tex:"TeX",context:"ConTeXt"},owner:"japborst"},latte:{title:"Latte",require:["clike","markup-templating","php"],owner:"nette"},less:{title:"Less",require:"css",optional:"css-extras",owner:"Golmote"},lilypond:{title:"LilyPond",require:"scheme",alias:"ly",owner:"RunDevelopment"},liquid:{title:"Liquid",require:"markup-templating",owner:"cinhtau"},lisp:{title:"Lisp",alias:["emacs","elisp","emacs-lisp"],owner:"JuanCaicedo"},livescript:{title:"LiveScript",owner:"Golmote"},llvm:{title:"LLVM IR",owner:"porglezomp"},log:{title:"Log file",optional:"javastacktrace",owner:"RunDevelopment"},lolcode:{title:"LOLCODE",owner:"Golmote"},lua:{title:"Lua",owner:"Golmote"},magma:{title:"Magma (CAS)",owner:"RunDevelopment"},makefile:{title:"Makefile",owner:"Golmote"},markdown:{title:"Markdown",require:"markup",optional:"yaml",alias:"md",owner:"Golmote"},"markup-templating":{title:"Markup templating",require:"markup",owner:"Golmote"},mata:{title:"Mata",owner:"RunDevelopment"},matlab:{title:"MATLAB",owner:"Golmote"},maxscript:{title:"MAXScript",owner:"RunDevelopment"},mel:{title:"MEL",owner:"Golmote"},mermaid:{title:"Mermaid",owner:"RunDevelopment"},metafont:{title:"METAFONT",owner:"LaeriExNihilo"},mizar:{title:"Mizar",owner:"Golmote"},mongodb:{title:"MongoDB",owner:"airs0urce",require:"javascript"},monkey:{title:"Monkey",owner:"Golmote"},moonscript:{title:"MoonScript",alias:"moon",owner:"RunDevelopment"},n1ql:{title:"N1QL",owner:"TMWilds"},n4js:{title:"N4JS",require:"javascript",optional:"jsdoc",alias:"n4jsd",owner:"bsmith-n4"},"nand2tetris-hdl":{title:"Nand To Tetris HDL",owner:"stephanmax"},naniscript:{title:"Naninovel Script",owner:"Elringus",alias:"nani"},nasm:{title:"NASM",owner:"rbmj"},neon:{title:"NEON",owner:"nette"},nevod:{title:"Nevod",owner:"nezaboodka"},nginx:{title:"nginx",owner:"volado"},nim:{title:"Nim",owner:"Golmote"},nix:{title:"Nix",owner:"Golmote"},nsis:{title:"NSIS",owner:"idleberg"},objectivec:{title:"Objective-C",require:"c",alias:"objc",owner:"uranusjr"},ocaml:{title:"OCaml",owner:"Golmote"},odin:{title:"Odin",owner:"edukisto"},opencl:{title:"OpenCL",require:"c",modify:["c","cpp"],owner:"Milania1"},openqasm:{title:"OpenQasm",alias:"qasm",owner:"RunDevelopment"},oz:{title:"Oz",owner:"Golmote"},parigp:{title:"PARI/GP",owner:"Golmote"},parser:{title:"Parser",require:"markup",owner:"Golmote"},pascal:{title:"Pascal",alias:"objectpascal",aliasTitles:{objectpascal:"Object Pascal"},owner:"Golmote"},pascaligo:{title:"Pascaligo",owner:"DefinitelyNotAGoat"},psl:{title:"PATROL Scripting Language",owner:"bertysentry"},pcaxis:{title:"PC-Axis",alias:"px",owner:"RunDevelopment"},peoplecode:{title:"PeopleCode",alias:"pcode",owner:"RunDevelopment"},perl:{title:"Perl",owner:"Golmote"},php:{title:"PHP",require:"markup-templating",owner:"milesj"},phpdoc:{title:"PHPDoc",require:["php","javadoclike"],modify:"php",owner:"RunDevelopment"},"php-extras":{title:"PHP Extras",require:"php",modify:"php",owner:"milesj"},"plant-uml":{title:"PlantUML",alias:"plantuml",owner:"RunDevelopment"},plsql:{title:"PL/SQL",require:"sql",owner:"Golmote"},powerquery:{title:"PowerQuery",alias:["pq","mscript"],owner:"peterbud"},powershell:{title:"PowerShell",owner:"nauzilus"},processing:{title:"Processing",require:"clike",owner:"Golmote"},prolog:{title:"Prolog",owner:"Golmote"},promql:{title:"PromQL",owner:"arendjr"},properties:{title:".properties",owner:"Golmote"},protobuf:{title:"Protocol Buffers",require:"clike",owner:"just-boris"},pug:{title:"Pug",require:["markup","javascript"],optional:["coffeescript","ejs","handlebars","less","livescript","markdown","scss","stylus","twig"],owner:"Golmote"},puppet:{title:"Puppet",owner:"Golmote"},pure:{title:"Pure",optional:["c","cpp","fortran"],owner:"Golmote"},purebasic:{title:"PureBasic",require:"clike",alias:"pbfasm",owner:"HeX0R101"},purescript:{title:"PureScript",require:"haskell",alias:"purs",owner:"sriharshachilakapati"},python:{title:"Python",alias:"py",owner:"multipetros"},qsharp:{title:"Q#",require:"clike",alias:"qs",owner:"fedonman"},q:{title:"Q (kdb+ database)",owner:"Golmote"},qml:{title:"QML",require:"javascript",owner:"RunDevelopment"},qore:{title:"Qore",require:"clike",owner:"temnroegg"},r:{title:"R",owner:"Golmote"},racket:{title:"Racket",require:"scheme",alias:"rkt",owner:"RunDevelopment"},cshtml:{title:"Razor C#",alias:"razor",require:["markup","csharp"],optional:["css","css-extras","javascript","js-extras"],owner:"RunDevelopment"},jsx:{title:"React JSX",require:["markup","javascript"],optional:["jsdoc","js-extras","js-templates"],owner:"vkbansal"},tsx:{title:"React TSX",require:["jsx","typescript"]},reason:{title:"Reason",require:"clike",owner:"Golmote"},regex:{title:"Regex",owner:"RunDevelopment"},rego:{title:"Rego",owner:"JordanSh"},renpy:{title:"Ren'py",alias:"rpy",owner:"HyuchiaDiego"},rescript:{title:"ReScript",alias:"res",owner:"vmarcosp"},rest:{title:"reST (reStructuredText)",owner:"Golmote"},rip:{title:"Rip",owner:"ravinggenius"},roboconf:{title:"Roboconf",owner:"Golmote"},robotframework:{title:"Robot Framework",alias:"robot",owner:"RunDevelopment"},ruby:{title:"Ruby",require:"clike",alias:"rb",owner:"samflores"},rust:{title:"Rust",owner:"Golmote"},sas:{title:"SAS",optional:["groovy","lua","sql"],owner:"Golmote"},sass:{title:"Sass (Sass)",require:"css",optional:"css-extras",owner:"Golmote"},scss:{title:"Sass (SCSS)",require:"css",optional:"css-extras",owner:"MoOx"},scala:{title:"Scala",require:"java",owner:"jozic"},scheme:{title:"Scheme",owner:"bacchus123"},"shell-session":{title:"Shell session",require:"bash",alias:["sh-session","shellsession"],owner:"RunDevelopment"},smali:{title:"Smali",owner:"RunDevelopment"},smalltalk:{title:"Smalltalk",owner:"Golmote"},smarty:{title:"Smarty",require:"markup-templating",optional:"php",owner:"Golmote"},sml:{title:"SML",alias:"smlnj",aliasTitles:{smlnj:"SML/NJ"},owner:"RunDevelopment"},solidity:{title:"Solidity (Ethereum)",alias:"sol",require:"clike",owner:"glachaud"},"solution-file":{title:"Solution file",alias:"sln",owner:"RunDevelopment"},soy:{title:"Soy (Closure Template)",require:"markup-templating",owner:"Golmote"},sparql:{title:"SPARQL",require:"turtle",owner:"Triply-Dev",alias:"rq"},"splunk-spl":{title:"Splunk SPL",owner:"RunDevelopment"},sqf:{title:"SQF: Status Quo Function (Arma 3)",require:"clike",owner:"RunDevelopment"},sql:{title:"SQL",owner:"multipetros"},squirrel:{title:"Squirrel",require:"clike",owner:"RunDevelopment"},stan:{title:"Stan",owner:"RunDevelopment"},stata:{title:"Stata Ado",require:["mata","java","python"],owner:"RunDevelopment"},iecst:{title:"Structured Text (IEC 61131-3)",owner:"serhioromano"},stylus:{title:"Stylus",owner:"vkbansal"},supercollider:{title:"SuperCollider",alias:"sclang",owner:"RunDevelopment"},swift:{title:"Swift",owner:"chrischares"},systemd:{title:"Systemd configuration file",owner:"RunDevelopment"},"t4-templating":{title:"T4 templating",owner:"RunDevelopment"},"t4-cs":{title:"T4 Text Templates (C#)",require:["t4-templating","csharp"],alias:"t4",owner:"RunDevelopment"},"t4-vb":{title:"T4 Text Templates (VB)",require:["t4-templating","vbnet"],owner:"RunDevelopment"},tap:{title:"TAP",owner:"isaacs",require:"yaml"},tcl:{title:"Tcl",owner:"PeterChaplin"},tt2:{title:"Template Toolkit 2",require:["clike","markup-templating"],owner:"gflohr"},textile:{title:"Textile",require:"markup",optional:"css",owner:"Golmote"},toml:{title:"TOML",owner:"RunDevelopment"},tremor:{title:"Tremor",alias:["trickle","troy"],owner:"darach",aliasTitles:{trickle:"trickle",troy:"troy"}},turtle:{title:"Turtle",alias:"trig",aliasTitles:{trig:"TriG"},owner:"jakubklimek"},twig:{title:"Twig",require:"markup-templating",owner:"brandonkelly"},typescript:{title:"TypeScript",require:"javascript",optional:"js-templates",alias:"ts",owner:"vkbansal"},typoscript:{title:"TypoScript",alias:"tsconfig",aliasTitles:{tsconfig:"TSConfig"},owner:"dkern"},unrealscript:{title:"UnrealScript",alias:["uscript","uc"],owner:"RunDevelopment"},uorazor:{title:"UO Razor Script",owner:"jaseowns"},uri:{title:"URI",alias:"url",aliasTitles:{url:"URL"},owner:"RunDevelopment"},v:{title:"V",require:"clike",owner:"taggon"},vala:{title:"Vala",require:"clike",optional:"regex",owner:"TemplarVolk"},vbnet:{title:"VB.Net",require:"basic",owner:"Bigsby"},velocity:{title:"Velocity",require:"markup",owner:"Golmote"},verilog:{title:"Verilog",owner:"a-rey"},vhdl:{title:"VHDL",owner:"a-rey"},vim:{title:"vim",owner:"westonganger"},"visual-basic":{title:"Visual Basic",alias:["vb","vba"],aliasTitles:{vba:"VBA"},owner:"Golmote"},warpscript:{title:"WarpScript",owner:"RunDevelopment"},wasm:{title:"WebAssembly",owner:"Golmote"},"web-idl":{title:"Web IDL",alias:"webidl",owner:"RunDevelopment"},wgsl:{title:"WGSL",owner:"Dr4gonthree"},wiki:{title:"Wiki markup",require:"markup",owner:"Golmote"},wolfram:{title:"Wolfram language",alias:["mathematica","nb","wl"],aliasTitles:{mathematica:"Mathematica",nb:"Mathematica Notebook"},owner:"msollami"},wren:{title:"Wren",owner:"clsource"},xeora:{title:"Xeora",require:"markup",alias:"xeoracube",aliasTitles:{xeoracube:"XeoraCube"},owner:"freakmaxi"},"xml-doc":{title:"XML doc (.net)",require:"markup",modify:["csharp","fsharp","vbnet"],owner:"RunDevelopment"},xojo:{title:"Xojo (REALbasic)",owner:"Golmote"},xquery:{title:"XQuery",require:"markup",owner:"Golmote"},yaml:{title:"YAML",alias:"yml",owner:"hason"},yang:{title:"YANG",owner:"RunDevelopment"},zig:{title:"Zig",owner:"RunDevelopment"}},plugins:{meta:{path:"plugins/{id}/prism-{id}",link:"plugins/{id}/"},"line-highlight":{title:"Line Highlight",description:"Highlights specific lines and/or line ranges."},"line-numbers":{title:"Line Numbers",description:"Line number at the beginning of code lines.",owner:"kuba-kubula"},"show-invisibles":{title:"Show Invisibles",description:"Show hidden characters such as tabs and line breaks.",optional:["autolinker","data-uri-highlight"]},autolinker:{title:"Autolinker",description:"Converts URLs and emails in code to clickable links. Parses Markdown links in comments."},wpd:{title:"WebPlatform Docs",description:'Makes tokens link to WebPlatform.org documentation. The links open in a new tab.'},"custom-class":{title:"Custom Class",description:"This plugin allows you to prefix Prism's default classes (.comment can become .namespace--comment) or replace them with your defined ones (like .editor__comment). You can even add new classes.",owner:"dvkndn",noCSS:!0},"file-highlight":{title:"File Highlight",description:"Fetch external files and highlight them with Prism. Used on the Prism website itself.",noCSS:!0},"show-language":{title:"Show Language",description:"Display the highlighted language in code blocks (inline code does not show the label).",owner:"nauzilus",noCSS:!0,require:"toolbar"},"jsonp-highlight":{title:"JSONP Highlight",description:"Fetch content with JSONP and highlight some interesting content (e.g. GitHub/Gists or Bitbucket API).",noCSS:!0,owner:"nauzilus"},"highlight-keywords":{title:"Highlight Keywords",description:"Adds special CSS classes for each keyword for fine-grained highlighting.",owner:"vkbansal",noCSS:!0},"remove-initial-line-feed":{title:"Remove initial line feed",description:"Removes the initial line feed in code blocks.",owner:"Golmote",noCSS:!0},"inline-color":{title:"Inline color",description:"Adds a small inline preview for colors in style sheets.",require:"css-extras",owner:"RunDevelopment"},previewers:{title:"Previewers",description:"Previewers for angles, colors, gradients, easing and time.",require:"css-extras",owner:"Golmote"},autoloader:{title:"Autoloader",description:"Automatically loads the needed languages to highlight the code blocks.",owner:"Golmote",noCSS:!0},"keep-markup":{title:"Keep Markup",description:"Prevents custom markup from being dropped out during highlighting.",owner:"Golmote",optional:"normalize-whitespace",noCSS:!0},"command-line":{title:"Command Line",description:"Display a command line with a prompt and, optionally, the output/response from the commands.",owner:"chriswells0"},"unescaped-markup":{title:"Unescaped Markup",description:"Write markup without having to escape anything."},"normalize-whitespace":{title:"Normalize Whitespace",description:"Supports multiple operations to normalize whitespace in code blocks.",owner:"zeitgeist87",optional:"unescaped-markup",noCSS:!0},"data-uri-highlight":{title:"Data-URI Highlight",description:"Highlights data-URI contents.",owner:"Golmote",noCSS:!0},toolbar:{title:"Toolbar",description:"Attach a toolbar for plugins to easily register buttons on the top of a code block.",owner:"mAAdhaTTah"},"copy-to-clipboard":{title:"Copy to Clipboard Button",description:"Add a button that copies the code block to the clipboard when clicked.",owner:"mAAdhaTTah",require:"toolbar",noCSS:!0},"download-button":{title:"Download Button",description:"A button in the toolbar of a code block adding a convenient way to download a code file.",owner:"Golmote",require:"toolbar",noCSS:!0},"match-braces":{title:"Match braces",description:"Highlights matching braces.",owner:"RunDevelopment"},"diff-highlight":{title:"Diff Highlight",description:"Highlights the code inside diff blocks.",owner:"RunDevelopment",require:"diff"},"filter-highlight-all":{title:"Filter highlightAll",description:"Filters the elements the highlightAll and highlightAllUnder methods actually highlight.",owner:"RunDevelopment",noCSS:!0},treeview:{title:"Treeview",description:"A language with special styles to highlight file system tree structures.",owner:"Golmote"}}})},2885:(e,t,n)=>{const r=n(9901),a=n(9642),o=new Set;function i(e){void 0===e?e=Object.keys(r.languages).filter((e=>"meta"!=e)):Array.isArray(e)||(e=[e]);const t=[...o,...Object.keys(Prism.languages)];a(r,e,t).load((e=>{if(!(e in r.languages))return void(i.silent||console.warn("Language does not exist: "+e));const t="./prism-"+e;delete n.c[n(6500).resolve(t)],delete Prism.languages[e],n(6500)(t),o.add(e)}))}i.silent=!1,e.exports=i},6854:()=>{!function(e){function t(e,t){return"___"+e.toUpperCase()+t+"___"}Object.defineProperties(e.languages["markup-templating"]={},{buildPlaceholders:{value:function(n,r,a,o){if(n.language===r){var i=n.tokenStack=[];n.code=n.code.replace(a,(function(e){if("function"==typeof o&&!o(e))return e;for(var a,s=i.length;-1!==n.code.indexOf(a=t(r,s));)++s;return i[s]=e,a})),n.grammar=e.languages.markup}}},tokenizePlaceholders:{value:function(n,r){if(n.language===r&&n.tokenStack){n.grammar=e.languages[r];var a=0,o=Object.keys(n.tokenStack);!function i(s){for(var l=0;l=o.length);l++){var c=s[l];if("string"==typeof c||c.content&&"string"==typeof c.content){var u=o[a],d=n.tokenStack[u],p="string"==typeof c?c:c.content,f=t(r,u),m=p.indexOf(f);if(m>-1){++a;var h=p.substring(0,m),g=new e.Token(r,e.tokenize(d,n.grammar),"language-"+r,d),b=p.substring(m+f.length),y=[];h&&y.push.apply(y,i([h])),y.push(g),b&&y.push.apply(y,i([b])),"string"==typeof c?s.splice.apply(s,[l,1].concat(y)):c.content=y}}else c.content&&i(c.content)}return s}(n.tokens)}}}})}(Prism)},6726:(e,t,n)=>{var r={"./":2885};function a(e){var t=o(e);return n(t)}function o(e){if(!n.o(r,e)){var t=new Error("Cannot find module '"+e+"'");throw t.code="MODULE_NOT_FOUND",t}return r[e]}a.keys=function(){return Object.keys(r)},a.resolve=o,e.exports=a,a.id=6726},6500:(e,t,n)=>{var r={"./":2885};function a(e){var t=o(e);return n(t)}function o(e){if(!n.o(r,e)){var t=new Error("Cannot find module '"+e+"'");throw t.code="MODULE_NOT_FOUND",t}return r[e]}a.keys=function(){return Object.keys(r)},a.resolve=o,e.exports=a,a.id=6500},9642:e=>{"use strict";var t=function(){var e=function(){};function t(e,t){Array.isArray(e)?e.forEach(t):null!=e&&t(e,0)}function n(e){for(var t={},n=0,r=e.length;n "));var s={},l=e[r];if(l){function c(t){if(!(t in e))throw new Error(r+" depends on an unknown component "+t);if(!(t in s))for(var i in a(t,o),s[t]=!0,n[t])s[i]=!0}t(l.require,c),t(l.optional,c),t(l.modify,c)}n[r]=s,o.pop()}}return function(e){var t=n[e];return t||(a(e,r),t=n[e]),t}}function a(e){for(var t in e)return!0;return!1}return function(o,i,s){var l=function(e){var t={};for(var n in e){var r=e[n];for(var a in r)if("meta"!=a){var o=r[a];t[a]="string"==typeof o?{title:o}:o}}return t}(o),c=function(e){var n;return function(r){if(r in e)return r;if(!n)for(var a in n={},e){var o=e[a];t(o&&o.alias,(function(t){if(t in n)throw new Error(t+" cannot be alias for both "+a+" and "+n[t]);if(t in e)throw new Error(t+" cannot be alias of "+a+" because it is a component.");n[t]=a}))}return n[r]||r}}(l);i=i.map(c),s=(s||[]).map(c);var u=n(i),d=n(s);i.forEach((function e(n){var r=l[n];t(r&&r.require,(function(t){t in d||(u[t]=!0,e(t))}))}));for(var p,f=r(l),m=u;a(m);){for(var h in p={},m){var g=l[h];t(g&&g.modify,(function(e){e in d&&(p[e]=!0)}))}for(var b in d)if(!(b in u))for(var y in f(b))if(y in u){p[b]=!0;break}for(var v in m=p)u[v]=!0}var w={getIds:function(){var e=[];return w.load((function(t){e.push(t)})),e},load:function(t,n){return function(t,n,r,a){var o=a?a.series:void 0,i=a?a.parallel:e,s={},l={};function c(e){if(e in s)return s[e];l[e]=!0;var a,u=[];for(var d in t(e))d in n&&u.push(d);if(0===u.length)a=r(e);else{var p=i(u.map((function(e){var t=c(e);return delete l[e],t})));o?a=o(p,(function(){return r(e)})):r(e)}return s[e]=a}for(var u in n)c(u);var d=[];for(var p in l)d.push(s[p]);return i(d)}(f,u,t,n)}};return w}}();e.exports=t},2703:(e,t,n)=>{"use strict";var r=n(414);function a(){}function o(){}o.resetWarningCache=a,e.exports=function(){function e(e,t,n,a,o,i){if(i!==r){var s=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 s.name="Invariant Violation",s}}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:a};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 r=n(7294),a=n(3840);function o(e){for(var t="https://reactjs.org/docs/error-decoder.html?invariant="+e,n=1;n