vitess.io/vitess@v0.16.2/web/vtadmin/src/components/routes/schema/Schema.tsx (about) 1 /** 2 * Copyright 2021 The Vitess Authors. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 import * as React from 'react'; 17 import { Link, useParams } from 'react-router-dom'; 18 19 import style from './Schema.module.scss'; 20 import { useSchema, useVSchema } from '../../../hooks/api'; 21 import { Code } from '../../Code'; 22 import { useDocumentTitle } from '../../../hooks/useDocumentTitle'; 23 import { getVindexesForTable } from '../../../util/vschemas'; 24 import { ContentContainer } from '../../layout/ContentContainer'; 25 import { NavCrumbs } from '../../layout/NavCrumbs'; 26 import { WorkspaceHeader } from '../../layout/WorkspaceHeader'; 27 import { WorkspaceTitle } from '../../layout/WorkspaceTitle'; 28 import { Tooltip } from '../../tooltip/Tooltip'; 29 import { KeyspaceLink } from '../../links/KeyspaceLink'; 30 31 interface RouteParams { 32 clusterID: string; 33 keyspace: string; 34 table: string; 35 } 36 37 export const Schema = () => { 38 const { clusterID, keyspace, table } = useParams<RouteParams>(); 39 useDocumentTitle(`${table} (${keyspace})`); 40 41 const { data, error, isError, isLoading, isSuccess } = useSchema({ clusterID, keyspace, table }); 42 const vschemaQuery = useVSchema({ clusterID, keyspace }); 43 44 const tableDefinition = React.useMemo( 45 () => 46 data && Array.isArray(data.table_definitions) 47 ? data?.table_definitions.find((t) => t.name === table) 48 : null, 49 [data, table] 50 ); 51 52 const tableVindexes = React.useMemo( 53 () => (vschemaQuery.data ? getVindexesForTable(vschemaQuery.data, table) : []), 54 [vschemaQuery.data, table] 55 ); 56 57 const is404 = isSuccess && !tableDefinition; 58 59 return ( 60 <div> 61 {!is404 && !isError && ( 62 <WorkspaceHeader> 63 <NavCrumbs> 64 <Link to="/schemas">Schemas</Link> 65 </NavCrumbs> 66 67 <WorkspaceTitle className="font-mono">{table}</WorkspaceTitle> 68 69 <div className={style.headingMeta}> 70 <span> 71 Cluster: <code>{clusterID}</code> 72 </span> 73 <span> 74 Keyspace:{' '} 75 <KeyspaceLink clusterID={clusterID} name={keyspace}> 76 <code>{keyspace}</code> 77 </KeyspaceLink> 78 </span> 79 </div> 80 </WorkspaceHeader> 81 )} 82 83 <ContentContainer> 84 {/* TODO: skeleton placeholder */} 85 {isLoading && <div className={style.loadingPlaceholder}>Loading...</div>} 86 87 {isError && ( 88 <div className={style.errorPlaceholder}> 89 <span className={style.errorEmoji}>😰</span> 90 <h1>An error occurred</h1> 91 <code>{(error as any).response?.error?.message || error?.message}</code> 92 <p> 93 <Link to="/schemas">← All schemas</Link> 94 </p> 95 </div> 96 )} 97 98 {is404 && ( 99 <div className={style.errorPlaceholder}> 100 <span className={style.errorEmoji}>😖</span> 101 <h1>Schema not found</h1> 102 <p> 103 No schema found with table <code>{table}</code> in keyspace <code>{keyspace}</code> (cluster{' '} 104 <code>{clusterID}</code>). 105 </p> 106 <p> 107 <Link to="/schemas">← All schemas</Link> 108 </p> 109 </div> 110 )} 111 112 {!is404 && !isError && tableDefinition && ( 113 <div className={style.container}> 114 <section className={style.panel}> 115 <h3 className="my-8">Table Definition</h3> 116 <Code code={tableDefinition.schema} /> 117 </section> 118 119 {!!tableVindexes.length && ( 120 <section className={style.panel}> 121 <h3 className="my-8">Vindexes</h3> 122 <p> 123 A Vindex provides a way to map a column value to a keyspace ID. Since each shard in 124 Vitess covers a range of keyspace ID values, this mapping can be used to identify 125 which shard contains a row.{' '} 126 <a 127 href="https://vitess.io/docs/reference/features/vindexes/" 128 target="_blank" 129 rel="noopen noreferrer" 130 > 131 Learn more about Vindexes in the Vitess documentation. 132 </a> 133 </p> 134 135 <table> 136 <thead> 137 <tr> 138 <th>Vindex</th> 139 <th>Columns</th> 140 <th>Type</th> 141 <th>Params</th> 142 </tr> 143 </thead> 144 <tbody className="font-mono"> 145 {tableVindexes.map((v, vdx) => { 146 const columns = v.column ? [v.column] : v.columns; 147 return ( 148 <tr key={v.name}> 149 <td> 150 {v.name} 151 152 {vdx === 0 && ( 153 <Tooltip text="A table's Primary Vindex maps a column value to a keyspace ID."> 154 <span className={style.skBadge}>Primary</span> 155 </Tooltip> 156 )} 157 </td> 158 <td>{(columns || []).join(', ')}</td> 159 <td>{v.meta?.type}</td> 160 <td> 161 {v.meta?.params ? ( 162 Object.entries(v.meta.params).map(([k, val]) => ( 163 <div key={k}> 164 <strong>{k}: </strong> {val} 165 </div> 166 )) 167 ) : ( 168 <span className="text-sm text-secondary">N/A</span> 169 )} 170 </td> 171 </tr> 172 ); 173 })} 174 </tbody> 175 </table> 176 </section> 177 )} 178 </div> 179 )} 180 </ContentContainer> 181 </div> 182 ); 183 };