mirror of
https://github.com/apache/superset.git
synced 2026-07-28 17:42:40 +00:00
763 lines
30 KiB
TypeScript
763 lines
30 KiB
TypeScript
/**
|
|
* Licensed to the Apache Software Foundation (ASF) under one
|
|
* or more contributor license agreements. See the NOTICE file
|
|
* distributed with this work for additional information
|
|
* regarding copyright ownership. The ASF licenses this file
|
|
* to you under the Apache License, Version 2.0 (the
|
|
* "License"); you may not use this file except in compliance
|
|
* with the License. You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing,
|
|
* software distributed under the License is distributed on an
|
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
* KIND, either express or implied. See the License for the
|
|
* specific language governing permissions and limitations
|
|
* under the License.
|
|
*/
|
|
import { ChangeEvent, EventHandler, useState, useEffect } from 'react';
|
|
import cx from 'classnames';
|
|
import {
|
|
t,
|
|
DatabaseConnectionExtension,
|
|
isFeatureEnabled,
|
|
useTheme,
|
|
FeatureFlag,
|
|
} from '@superset-ui/core';
|
|
import {
|
|
Input,
|
|
Checkbox,
|
|
Collapse,
|
|
InfoTooltip,
|
|
CollapseLabelInModal,
|
|
type CheckboxChangeEvent,
|
|
} from '@superset-ui/core/components';
|
|
import { useJsonValidation } from '@superset-ui/core/components/AsyncAceEditor';
|
|
import {
|
|
StyledInputContainer,
|
|
StyledJsonEditor,
|
|
StyledExpandableForm,
|
|
no_margin_bottom,
|
|
} from './styles';
|
|
import { DatabaseObject, ExtraJson } from '../types';
|
|
|
|
const ExtraOptions = ({
|
|
db,
|
|
onInputChange,
|
|
onTextChange,
|
|
onEditorChange,
|
|
onExtraInputChange,
|
|
onExtraEditorChange,
|
|
extraExtension,
|
|
}: {
|
|
db: DatabaseObject | null;
|
|
onInputChange: (
|
|
e: CheckboxChangeEvent | React.ChangeEvent<HTMLInputElement>,
|
|
) => void;
|
|
onTextChange: EventHandler<ChangeEvent<HTMLTextAreaElement>>;
|
|
onEditorChange: Function;
|
|
onExtraInputChange: (
|
|
e: CheckboxChangeEvent | ChangeEvent<HTMLInputElement>,
|
|
) => void;
|
|
onExtraEditorChange: Function;
|
|
extraExtension: DatabaseConnectionExtension | undefined;
|
|
}) => {
|
|
const expandableModalIsOpen = !!db?.expose_in_sqllab;
|
|
const createAsOpen = !!(db?.allow_ctas || db?.allow_cvas);
|
|
const isFileUploadSupportedByEngine =
|
|
db?.engine_information?.supports_file_upload;
|
|
const supportsDynamicCatalog =
|
|
db?.engine_information?.supports_dynamic_catalog;
|
|
|
|
// JSON.parse will deep parse engine_params
|
|
// if it's an object, and we want to keep it a string
|
|
const extraJson: ExtraJson = JSON.parse(db?.extra || '{}', (key, value) => {
|
|
if (key === 'engine_params' && typeof value === 'object') {
|
|
// keep this as a string
|
|
return JSON.stringify(value);
|
|
}
|
|
return value;
|
|
});
|
|
|
|
// JSON validation hooks for the three editors
|
|
const secureExtraAnnotations = useJsonValidation(db?.masked_encrypted_extra, {
|
|
errorPrefix: 'Invalid secure extra JSON',
|
|
});
|
|
|
|
const metadataParamsValue = !Object.keys(extraJson?.metadata_params || {})
|
|
.length
|
|
? ''
|
|
: typeof extraJson?.metadata_params === 'string'
|
|
? extraJson?.metadata_params
|
|
: JSON.stringify(extraJson?.metadata_params);
|
|
const metadataParamsAnnotations = useJsonValidation(metadataParamsValue, {
|
|
errorPrefix: 'Invalid metadata parameters JSON',
|
|
});
|
|
|
|
const engineParamsValue = !Object.keys(extraJson?.engine_params || {}).length
|
|
? ''
|
|
: typeof extraJson?.engine_params === 'string'
|
|
? extraJson?.engine_params
|
|
: JSON.stringify(extraJson?.engine_params);
|
|
const engineParamsAnnotations = useJsonValidation(engineParamsValue, {
|
|
errorPrefix: 'Invalid engine parameters JSON',
|
|
});
|
|
|
|
const theme = useTheme();
|
|
const ExtraExtensionComponent = extraExtension?.component;
|
|
const ExtraExtensionLogo = extraExtension?.logo;
|
|
const ExtensionDescription = extraExtension?.description;
|
|
const allowRunAsync = isFeatureEnabled(FeatureFlag.ForceSqlLabRunAsync)
|
|
? true
|
|
: !!db?.allow_run_async;
|
|
const isAllowRunAsyncDisabled = isFeatureEnabled(
|
|
FeatureFlag.ForceSqlLabRunAsync,
|
|
);
|
|
const [activeKey, setActiveKey] = useState<string[] | undefined>();
|
|
|
|
useEffect(() => {
|
|
if (!expandableModalIsOpen && activeKey !== undefined) {
|
|
setActiveKey(undefined);
|
|
}
|
|
// See issue #34630 for why we omit `activeKey` from the dependency array
|
|
}, [expandableModalIsOpen]);
|
|
|
|
return (
|
|
<Collapse
|
|
expandIconPosition="end"
|
|
accordion
|
|
modalMode
|
|
activeKey={activeKey}
|
|
onChange={key => setActiveKey(key)}
|
|
items={[
|
|
{
|
|
key: 'sql-lab',
|
|
label: (
|
|
<CollapseLabelInModal
|
|
title={t('SQL Lab')}
|
|
subtitle={t(
|
|
'Adjust how this database will interact with SQL Lab.',
|
|
)}
|
|
testId="sql-lab-label-test"
|
|
/>
|
|
),
|
|
children: (
|
|
<>
|
|
<StyledInputContainer css={no_margin_bottom}>
|
|
<div className="input-container">
|
|
<Checkbox
|
|
id="expose_in_sqllab"
|
|
name="expose_in_sqllab"
|
|
indeterminate={false}
|
|
checked={!!db?.expose_in_sqllab}
|
|
onChange={onInputChange}
|
|
>
|
|
{t('Expose database in SQL Lab')}
|
|
</Checkbox>
|
|
<InfoTooltip
|
|
tooltip={t('Allow this database to be queried in SQL Lab')}
|
|
/>
|
|
</div>
|
|
<StyledExpandableForm
|
|
className={cx('expandable', {
|
|
open: expandableModalIsOpen,
|
|
'ctas-open': createAsOpen,
|
|
})}
|
|
>
|
|
<StyledInputContainer css={no_margin_bottom}>
|
|
<div className="input-container">
|
|
<Checkbox
|
|
id="allow_ctas"
|
|
name="allow_ctas"
|
|
indeterminate={false}
|
|
checked={!!db?.allow_ctas}
|
|
onChange={onInputChange}
|
|
>
|
|
{t('Allow CREATE TABLE AS')}
|
|
</Checkbox>
|
|
<InfoTooltip
|
|
tooltip={t(
|
|
'Allow creation of new tables based on queries',
|
|
)}
|
|
/>
|
|
</div>
|
|
</StyledInputContainer>
|
|
<StyledInputContainer css={no_margin_bottom}>
|
|
<div className="input-container">
|
|
<Checkbox
|
|
id="allow_cvas"
|
|
name="allow_cvas"
|
|
indeterminate={false}
|
|
checked={!!db?.allow_cvas}
|
|
onChange={onInputChange}
|
|
>
|
|
{t('Allow CREATE VIEW AS')}
|
|
</Checkbox>
|
|
<InfoTooltip
|
|
tooltip={t(
|
|
'Allow creation of new views based on queries',
|
|
)}
|
|
/>
|
|
</div>
|
|
<StyledInputContainer
|
|
className={cx('expandable', { open: createAsOpen })}
|
|
>
|
|
<div className="control-label">
|
|
{t('CTAS & CVAS SCHEMA')}
|
|
</div>
|
|
<div className="input-container">
|
|
<Input
|
|
type="text"
|
|
name="force_ctas_schema"
|
|
placeholder={t('Create or select schema...')}
|
|
onChange={onInputChange}
|
|
value={db?.force_ctas_schema || ''}
|
|
/>
|
|
</div>
|
|
<div className="helper">
|
|
{t(
|
|
'Force all tables and views to be created in this schema when clicking CTAS or CVAS in SQL Lab.',
|
|
)}
|
|
</div>
|
|
</StyledInputContainer>
|
|
</StyledInputContainer>
|
|
<StyledInputContainer css={no_margin_bottom}>
|
|
<div className="input-container">
|
|
<Checkbox
|
|
id="allow_dml"
|
|
name="allow_dml"
|
|
indeterminate={false}
|
|
checked={!!db?.allow_dml}
|
|
onChange={onInputChange}
|
|
>
|
|
{t('Allow DDL and DML')}
|
|
</Checkbox>
|
|
<InfoTooltip
|
|
tooltip={t(
|
|
'Allow the execution of DDL (Data Definition Language: CREATE, DROP, TRUNCATE, etc.) and DML (Data Modification Language: INSERT, UPDATE, DELETE, etc)',
|
|
)}
|
|
/>
|
|
</div>
|
|
</StyledInputContainer>
|
|
<StyledInputContainer css={no_margin_bottom}>
|
|
<div className="input-container">
|
|
<Checkbox
|
|
id="cost_estimate_enabled"
|
|
name="cost_estimate_enabled"
|
|
indeterminate={false}
|
|
checked={!!extraJson?.cost_estimate_enabled}
|
|
onChange={onExtraInputChange}
|
|
>
|
|
{t('Enable query cost estimation')}
|
|
</Checkbox>
|
|
<InfoTooltip
|
|
tooltip={t(
|
|
'For Bigquery, Presto and Postgres, shows a button to compute cost before running a query.',
|
|
)}
|
|
/>
|
|
</div>
|
|
</StyledInputContainer>
|
|
<StyledInputContainer css={no_margin_bottom}>
|
|
<div className="input-container">
|
|
<Checkbox
|
|
id="allows_virtual_table_explore"
|
|
name="allows_virtual_table_explore"
|
|
indeterminate={false}
|
|
// when `allows_virtual_table_explore` is not present in `extra` it defaults to true
|
|
checked={
|
|
extraJson?.allows_virtual_table_explore !== false
|
|
}
|
|
onChange={onExtraInputChange}
|
|
>
|
|
{t('Allow this database to be explored')}
|
|
</Checkbox>
|
|
<InfoTooltip
|
|
tooltip={t(
|
|
'When enabled, users are able to visualize SQL Lab results in Explore.',
|
|
)}
|
|
/>
|
|
</div>
|
|
</StyledInputContainer>
|
|
<StyledInputContainer css={no_margin_bottom}>
|
|
<div className="input-container">
|
|
<Checkbox
|
|
id="disable_data_preview"
|
|
name="disable_data_preview"
|
|
indeterminate={false}
|
|
checked={!!extraJson?.disable_data_preview}
|
|
onChange={onExtraInputChange}
|
|
>
|
|
{t('Disable SQL Lab data preview queries')}
|
|
</Checkbox>
|
|
<InfoTooltip
|
|
tooltip={t(
|
|
'Disable data preview when fetching table metadata in SQL Lab. ' +
|
|
' Useful to avoid browser performance issues when using ' +
|
|
' databases with very wide tables.',
|
|
)}
|
|
/>
|
|
</div>
|
|
</StyledInputContainer>
|
|
<StyledInputContainer>
|
|
<div className="input-container">
|
|
<Checkbox
|
|
id="expand_rows"
|
|
name="expand_rows"
|
|
indeterminate={false}
|
|
checked={!!extraJson?.schema_options?.expand_rows}
|
|
onChange={onExtraInputChange}
|
|
>
|
|
{t('Enable row expansion in schemas')}
|
|
</Checkbox>
|
|
<InfoTooltip
|
|
tooltip={t(
|
|
'For Trino, describe full schemas of nested ROW types, expanding them with dotted paths',
|
|
)}
|
|
/>
|
|
</div>
|
|
</StyledInputContainer>
|
|
</StyledExpandableForm>
|
|
</StyledInputContainer>
|
|
</>
|
|
),
|
|
},
|
|
{
|
|
key: 'performance',
|
|
label: (
|
|
<CollapseLabelInModal
|
|
title={t('Performance')}
|
|
subtitle={t('Adjust performance settings of this database.')}
|
|
testId="performance-label-test"
|
|
/>
|
|
),
|
|
children: (
|
|
<>
|
|
<StyledInputContainer className="mb-8">
|
|
<div className="control-label">{t('Chart cache timeout')}</div>
|
|
<div className="input-container">
|
|
<Input
|
|
type="number"
|
|
name="cache_timeout"
|
|
value={db?.cache_timeout || ''}
|
|
placeholder={t('Enter duration in seconds')}
|
|
onChange={onInputChange}
|
|
data-test="cache-timeout-test"
|
|
/>
|
|
</div>
|
|
<div className="helper">
|
|
{t(
|
|
'Duration (in seconds) of the caching timeout for charts of this database.' +
|
|
' A timeout of 0 indicates that the cache never expires, and -1 bypasses the cache.' +
|
|
' Note this defaults to the global timeout if undefined.',
|
|
)}
|
|
</div>
|
|
</StyledInputContainer>
|
|
<StyledInputContainer>
|
|
<div className="control-label">{t('Schema cache timeout')}</div>
|
|
<div className="input-container">
|
|
<Input
|
|
type="number"
|
|
name="schema_cache_timeout"
|
|
value={
|
|
extraJson?.metadata_cache_timeout?.schema_cache_timeout ||
|
|
''
|
|
}
|
|
placeholder={t('Enter duration in seconds')}
|
|
onChange={onExtraInputChange}
|
|
data-test="schema-cache-timeout-test"
|
|
/>
|
|
</div>
|
|
<div className="helper">
|
|
{t(
|
|
'Duration (in seconds) of the metadata caching timeout for schemas of ' +
|
|
'this database. If left unset, the cache never expires.',
|
|
)}
|
|
</div>
|
|
</StyledInputContainer>
|
|
<StyledInputContainer>
|
|
<div className="control-label">{t('Table cache timeout')}</div>
|
|
<div className="input-container">
|
|
<Input
|
|
type="number"
|
|
name="table_cache_timeout"
|
|
value={
|
|
extraJson?.metadata_cache_timeout?.table_cache_timeout ||
|
|
''
|
|
}
|
|
placeholder={t('Enter duration in seconds')}
|
|
onChange={onExtraInputChange}
|
|
data-test="table-cache-timeout-test"
|
|
/>
|
|
</div>
|
|
<div className="helper">
|
|
{t(
|
|
'Duration (in seconds) of the metadata caching timeout for tables of ' +
|
|
'this database. If left unset, the cache never expires. ',
|
|
)}
|
|
</div>
|
|
</StyledInputContainer>
|
|
<StyledInputContainer css={{ no_margin_bottom }}>
|
|
<div className="input-container">
|
|
<Checkbox
|
|
id="allow_run_async"
|
|
name="allow_run_async"
|
|
indeterminate={false}
|
|
checked={allowRunAsync}
|
|
onChange={onInputChange}
|
|
>
|
|
{t('Asynchronous query execution')}
|
|
</Checkbox>
|
|
<InfoTooltip
|
|
tooltip={t(
|
|
'Operate the database in asynchronous mode, meaning that the queries ' +
|
|
'are executed on remote workers as opposed to on the web server itself. ' +
|
|
'This assumes that you have a Celery worker setup as well as a results ' +
|
|
'backend. Refer to the installation docs for more information.',
|
|
)}
|
|
/>
|
|
{isAllowRunAsyncDisabled && (
|
|
<InfoTooltip
|
|
iconStyle={{ color: theme.colorError }}
|
|
tooltip={t(
|
|
'This option has been disabled by the administrator.',
|
|
)}
|
|
/>
|
|
)}
|
|
</div>
|
|
</StyledInputContainer>
|
|
<StyledInputContainer css={{ no_margin_bottom }}>
|
|
<div className="input-container">
|
|
<Checkbox
|
|
id="cancel_query_on_windows_unload"
|
|
name="cancel_query_on_windows_unload"
|
|
indeterminate={false}
|
|
checked={!!extraJson?.cancel_query_on_windows_unload}
|
|
onChange={onExtraInputChange}
|
|
>
|
|
{t('Cancel query on window unload event')}
|
|
</Checkbox>
|
|
<InfoTooltip
|
|
tooltip={t(
|
|
'Terminate running queries when browser window closed or navigated ' +
|
|
'to another page. Available for Presto, Hive, MySQL, Postgres and ' +
|
|
'Snowflake databases.',
|
|
)}
|
|
/>
|
|
</div>
|
|
</StyledInputContainer>
|
|
</>
|
|
),
|
|
},
|
|
{
|
|
key: 'security',
|
|
label: (
|
|
<CollapseLabelInModal
|
|
title={t('Security')}
|
|
testId="security-label-test"
|
|
subtitle={t('Add extra connection information.')}
|
|
/>
|
|
),
|
|
children: (
|
|
<>
|
|
<StyledInputContainer
|
|
css={!isFileUploadSupportedByEngine ? no_margin_bottom : {}}
|
|
>
|
|
<div className="input-container">
|
|
<Checkbox
|
|
id="per_user_caching"
|
|
name="per_user_caching"
|
|
indeterminate={false}
|
|
checked={!!extraJson?.per_user_caching}
|
|
onChange={onExtraInputChange}
|
|
>
|
|
{t('Per user caching')}
|
|
</Checkbox>
|
|
<InfoTooltip
|
|
tooltip={t(
|
|
'Cache data separately for each user based on their data access roles and permissions. ' +
|
|
'When disabled, a single cache will be used for all users.',
|
|
)}
|
|
/>
|
|
</div>
|
|
</StyledInputContainer>
|
|
<StyledInputContainer
|
|
css={!isFileUploadSupportedByEngine ? no_margin_bottom : {}}
|
|
>
|
|
<div className="input-container">
|
|
<Checkbox
|
|
id="impersonate_user"
|
|
name="impersonate_user"
|
|
indeterminate={false}
|
|
checked={!!db?.impersonate_user}
|
|
onChange={onInputChange}
|
|
>
|
|
{t(
|
|
'Impersonate logged in user (Presto, Trino, Drill, Hive, and Google Sheets)',
|
|
)}
|
|
</Checkbox>
|
|
<InfoTooltip
|
|
tooltip={t(
|
|
'If Presto or Trino, all the queries in SQL Lab are going to be executed as the ' +
|
|
'currently logged on user who must have permission to run them. If Hive ' +
|
|
'and hive.server2.enable.doAs is enabled, will run the queries as ' +
|
|
'service account, but impersonate the currently logged on user via ' +
|
|
'hive.server2.proxy.user property.',
|
|
)}
|
|
/>
|
|
</div>
|
|
</StyledInputContainer>
|
|
{isFileUploadSupportedByEngine && (
|
|
<StyledInputContainer
|
|
css={!db?.allow_file_upload ? no_margin_bottom : {}}
|
|
>
|
|
<div className="input-container">
|
|
<Checkbox
|
|
id="allow_file_upload"
|
|
name="allow_file_upload"
|
|
indeterminate={false}
|
|
checked={!!db?.allow_file_upload}
|
|
onChange={onInputChange}
|
|
>
|
|
{t('Allow file uploads to database')}
|
|
</Checkbox>
|
|
</div>
|
|
</StyledInputContainer>
|
|
)}
|
|
{isFileUploadSupportedByEngine && !!db?.allow_file_upload && (
|
|
<StyledInputContainer css={no_margin_bottom}>
|
|
<div className="control-label">
|
|
{t('Schemas allowed for File upload')}
|
|
</div>
|
|
<div className="input-container">
|
|
<Input
|
|
type="text"
|
|
name="schemas_allowed_for_file_upload"
|
|
value={(
|
|
extraJson?.schemas_allowed_for_file_upload || []
|
|
).join(',')}
|
|
placeholder="schema1,schema2"
|
|
onChange={onExtraInputChange}
|
|
/>
|
|
</div>
|
|
<div className="helper">
|
|
{t(
|
|
'A comma-separated list of schemas that files are allowed to upload to.',
|
|
)}
|
|
</div>
|
|
</StyledInputContainer>
|
|
)}
|
|
<StyledInputContainer>
|
|
<div className="control-label">{t('Secure extra')}</div>
|
|
<div className="input-container">
|
|
<StyledJsonEditor
|
|
name="masked_encrypted_extra"
|
|
value={db?.masked_encrypted_extra || ''}
|
|
placeholder={t('Secure extra')}
|
|
onChange={(json: string) =>
|
|
onEditorChange({ json, name: 'masked_encrypted_extra' })
|
|
}
|
|
width="100%"
|
|
height="160px"
|
|
annotations={secureExtraAnnotations}
|
|
/>
|
|
</div>
|
|
<div className="helper">
|
|
<div>
|
|
{t(
|
|
'JSON string containing additional connection configuration. ' +
|
|
'This is used to provide connection information for systems ' +
|
|
'like Hive, Presto and BigQuery which do not conform to the ' +
|
|
'username:password syntax normally used by SQLAlchemy.',
|
|
)}
|
|
</div>
|
|
</div>
|
|
</StyledInputContainer>
|
|
<StyledInputContainer>
|
|
<div className="control-label">{t('Root certificate')}</div>
|
|
<div className="input-container">
|
|
<Input.TextArea
|
|
name="server_cert"
|
|
value={db?.server_cert || ''}
|
|
placeholder={t('Enter CA_BUNDLE')}
|
|
onChange={onTextChange}
|
|
/>
|
|
</div>
|
|
<div className="helper">
|
|
{t(
|
|
'Optional CA_BUNDLE contents to validate HTTPS requests. Only ' +
|
|
'available on certain database engines.',
|
|
)}
|
|
</div>
|
|
</StyledInputContainer>
|
|
</>
|
|
),
|
|
},
|
|
...(extraExtension && ExtraExtensionComponent && ExtensionDescription
|
|
? [
|
|
{
|
|
key: extraExtension?.title,
|
|
collapsible: extraExtension.enabled?.()
|
|
? ('icon' as const)
|
|
: ('disabled' as const),
|
|
label: (
|
|
<CollapseLabelInModal
|
|
key={extraExtension?.title}
|
|
title={
|
|
<>
|
|
{ExtraExtensionLogo && <ExtraExtensionLogo />}
|
|
{extraExtension?.title}
|
|
</>
|
|
}
|
|
subtitle={<ExtensionDescription />}
|
|
/>
|
|
),
|
|
children: (
|
|
<StyledInputContainer css={no_margin_bottom}>
|
|
<ExtraExtensionComponent
|
|
db={db}
|
|
onEdit={extraExtension.onEdit}
|
|
/>
|
|
</StyledInputContainer>
|
|
),
|
|
},
|
|
]
|
|
: []),
|
|
{
|
|
key: 'other',
|
|
label: (
|
|
<CollapseLabelInModal
|
|
title={t('Other')}
|
|
subtitle={t('Additional settings.')}
|
|
testId="other-label-test"
|
|
/>
|
|
),
|
|
children: (
|
|
<>
|
|
<StyledInputContainer>
|
|
<div className="control-label">{t('Metadata Parameters')}</div>
|
|
<div className="input-container">
|
|
<StyledJsonEditor
|
|
name="metadata_params"
|
|
placeholder={t('Metadata Parameters')}
|
|
onChange={(json: string) =>
|
|
onExtraEditorChange({ json, name: 'metadata_params' })
|
|
}
|
|
width="100%"
|
|
height="160px"
|
|
value={
|
|
!Object.keys(extraJson?.metadata_params || {}).length
|
|
? ''
|
|
: typeof extraJson?.metadata_params === 'string'
|
|
? extraJson?.metadata_params
|
|
: JSON.stringify(extraJson?.metadata_params)
|
|
}
|
|
annotations={metadataParamsAnnotations}
|
|
/>
|
|
</div>
|
|
<div className="helper">
|
|
<div>
|
|
{t(
|
|
'The metadata_params object gets unpacked into the sqlalchemy.MetaData call.',
|
|
)}
|
|
</div>
|
|
</div>
|
|
</StyledInputContainer>
|
|
<StyledInputContainer>
|
|
<div className="control-label">{t('Engine Parameters')}</div>
|
|
<div className="input-container">
|
|
<StyledJsonEditor
|
|
name="engine_params"
|
|
placeholder={t('Engine Parameters')}
|
|
onChange={(json: string) =>
|
|
onExtraEditorChange({ json, name: 'engine_params' })
|
|
}
|
|
width="100%"
|
|
height="160px"
|
|
value={
|
|
!Object.keys(extraJson?.engine_params || {}).length
|
|
? ''
|
|
: extraJson?.engine_params
|
|
}
|
|
annotations={engineParamsAnnotations}
|
|
/>
|
|
</div>
|
|
<div className="helper">
|
|
<div>
|
|
{t(
|
|
'The engine_params object gets unpacked into the sqlalchemy.create_engine call.',
|
|
)}
|
|
</div>
|
|
</div>
|
|
</StyledInputContainer>
|
|
<StyledInputContainer>
|
|
<div className="control-label" data-test="version-label-test">
|
|
{t('Version')}
|
|
</div>
|
|
<div
|
|
className="input-container"
|
|
data-test="version-spinbutton-test"
|
|
>
|
|
<Input
|
|
type="text"
|
|
name="version"
|
|
placeholder={t('Version number')}
|
|
onChange={onExtraInputChange}
|
|
value={extraJson?.version || ''}
|
|
/>
|
|
</div>
|
|
<div className="helper">
|
|
{t(
|
|
'Specify the database version. This is used with Presto for query cost ' +
|
|
'estimation, and Dremio for syntax changes, among others.',
|
|
)}
|
|
</div>
|
|
</StyledInputContainer>
|
|
<StyledInputContainer css={no_margin_bottom}>
|
|
<div className="input-container">
|
|
<Checkbox
|
|
id="disable_drill_to_detail"
|
|
name="disable_drill_to_detail"
|
|
indeterminate={false}
|
|
checked={!!extraJson?.disable_drill_to_detail}
|
|
onChange={onExtraInputChange}
|
|
>
|
|
{t('Disable drill to detail')}
|
|
</Checkbox>
|
|
<InfoTooltip
|
|
tooltip={t(
|
|
'Disables the drill to detail feature for this database.',
|
|
)}
|
|
/>
|
|
</div>
|
|
</StyledInputContainer>
|
|
{supportsDynamicCatalog && (
|
|
<StyledInputContainer css={no_margin_bottom}>
|
|
<div className="input-container">
|
|
<Checkbox
|
|
id="allow_multi_catalog"
|
|
name="allow_multi_catalog"
|
|
indeterminate={false}
|
|
checked={!!extraJson?.allow_multi_catalog}
|
|
onChange={onExtraInputChange}
|
|
>
|
|
{t('Allow changing catalogs')}
|
|
</Checkbox>
|
|
<InfoTooltip
|
|
tooltip={t(
|
|
'Give access to multiple catalogs in a single database connection.',
|
|
)}
|
|
/>
|
|
</div>
|
|
</StyledInputContainer>
|
|
)}
|
|
</>
|
|
),
|
|
},
|
|
]}
|
|
/>
|
|
);
|
|
};
|
|
|
|
export default ExtraOptions;
|