fix query to fetch list of postgres types, change filter (close #2314) (#2339)

This commit is contained in:
Karthik Venkateswaran 2019-06-07 19:58:02 +05:30 committed by Rikin Kachhia
parent de09c29003
commit 0b3defd314
9 changed files with 89 additions and 60 deletions

View File

@ -1,5 +1,5 @@
import React from 'react'; import React from 'react';
import Select, { components } from 'react-select'; import Select, { components, createFilter } from 'react-select';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
/* /*
@ -16,6 +16,14 @@ const CustomOption = props => {
); );
}; };
const getPrefixFilter = () => {
const prefixFilterOptions = {
matchFrom: 'start',
};
return createFilter(prefixFilterOptions);
};
/* /*
* Searchable select box component * Searchable select box component
* 1) options: Accepts options * 1) options: Accepts options
@ -30,6 +38,7 @@ const SearchableSelectBox = ({
value, value,
bsClass, bsClass,
styleOverrides, styleOverrides,
filterOption,
}) => { }) => {
/* Select element style customization */ /* Select element style customization */
@ -45,6 +54,15 @@ const SearchableSelectBox = ({
}); });
} }
let customFilter;
switch (filterOption) {
case 'prefix':
customFilter = getPrefixFilter();
break;
default:
customFilter = {};
}
return ( return (
<Select <Select
isSearchable isSearchable
@ -55,6 +73,7 @@ const SearchableSelectBox = ({
onChange={onChange} onChange={onChange}
value={value} value={value}
styles={customStyles} styles={customStyles}
filterOption={customFilter}
/> />
); );
}; };
@ -65,6 +84,7 @@ SearchableSelectBox.propTypes = {
options: PropTypes.array.isRequired, options: PropTypes.array.isRequired,
bsClass: PropTypes.string, bsClass: PropTypes.string,
customStyle: PropTypes.object, customStyle: PropTypes.object,
filterOption: PropTypes.object,
}; };
export default SearchableSelectBox; export default SearchableSelectBox;

View File

@ -91,6 +91,7 @@ const TableColumn = props => {
value={column.type && columnTypeValueMap[column.type]} value={column.type && columnTypeValueMap[column.type]}
bsClass={`col-type-${i} add_table_column_selector`} bsClass={`col-type-${i} add_table_column_selector`}
styleOverrides={customSelectBoxStyles} styleOverrides={customSelectBoxStyles}
filterOption={'prefix'}
/> />
</span> </span>
<input <input

View File

@ -34,23 +34,27 @@ const getAllDataTypeMap = allDataTypes => {
return dTIndex; return dTIndex;
}; };
const getDataTypeInfo = (row, categoryInfo, colId) => { const getDataTypeInfo = (row, categoryInfo, colId, cached = {}) => {
const columnTypeValueMap = {}; const columnTypeValueMap = {};
const { typInfo, typDisplayName, typDescription } = splitDbRow(row); const { typInfo, typDisplayName, typDescription } = splitDbRow(row);
// Create option object for every valid type // Create option object for every valid type
const currTypeObj = typInfo.map((t, i) => { const currTypeObj = [];
const optObj = { typInfo.forEach((t, i) => {
value: t, /* Don't add types which are part of frequently used types */
label: typDisplayName[i], if (!(t in cached)) {
key: `${categoryInfo}_${i}`, const optObj = {
colIdentifier: colId, value: t,
description: typDescription[i], label: typDisplayName[i],
}; key: `${categoryInfo}_${i}`,
// Memoizing option for later use colIdentifier: colId,
columnTypeValueMap[t] = optObj; description: typDescription[i],
return optObj; };
// Memoizing option for later use
columnTypeValueMap[t] = optObj;
currTypeObj.push(optObj);
}
}); });
return { typInfo: currTypeObj, typValueMap: columnTypeValueMap }; return { typInfo: currTypeObj, typValueMap: columnTypeValueMap };
}; };
@ -99,7 +103,8 @@ const getDataOptions = (commonDataTypes, restTypes, identifier) => {
const { typInfo, typValueMap } = getDataTypeInfo( const { typInfo, typValueMap } = getDataTypeInfo(
categoryRow[0], categoryRow[0],
pgCategoryCode[category], pgCategoryCode[category],
identifier identifier,
columnTypeValueMap
); );
columnTypeValueMap = { ...columnTypeValueMap, ...typValueMap }; columnTypeValueMap = { ...columnTypeValueMap, ...typValueMap };
columnDataTypes.push({ columnDataTypes.push({

View File

@ -697,7 +697,7 @@ const dataReducer = (state = defaultState, action) => {
return { return {
...state, ...state,
columnDataTypes: action.data, columnDataTypes: action.data,
columnDataTypeFetchErr: 'Error fetching data', columnDataTypeFetchErr: defaultState.columnDataTypeFetchErr,
}; };
case FETCH_COLUMN_TYPE_LIST_FAIL: case FETCH_COLUMN_TYPE_LIST_FAIL:
@ -710,7 +710,7 @@ const dataReducer = (state = defaultState, action) => {
return { return {
...state, ...state,
columnDataTypes: [...defaultState.columnDataTypes], columnDataTypes: [...defaultState.columnDataTypes],
columnDataTypeFetchErr: defaultState.columnDataTypes, columnDataTypeFetchErr: defaultState.columnDataTypeFetchErr,
}; };
default: default:
return state; return state;

View File

@ -152,6 +152,7 @@ const ColumnCreator = ({ dispatch, tableName, dataTypes: restTypes = [] }) => {
value={colType.value && columnTypeValueMap[colType.value]} value={colType.value && columnTypeValueMap[colType.value]}
bsClass={`col-type-${0} modify_select`} bsClass={`col-type-${0} modify_select`}
styleOverrides={customSelectBoxStyles} styleOverrides={customSelectBoxStyles}
filterOption={'prefix'}
/> />
</span> </span>
<input <input

View File

@ -2,20 +2,6 @@ import React, { useEffect } from 'react';
import SearchableSelectBox from '../../../Common/SearchableSelect/SearchableSelect'; import SearchableSelectBox from '../../../Common/SearchableSelect/SearchableSelect';
/*
import {
INTEGER,
SERIAL,
BIGINT,
BIGSERIAL,
UUID,
JSONDTYPE,
JSONB,
TIMESTAMP,
TIME,
} from '../../../../constants';
*/
import { getValidAlterOptions } from './utils'; import { getValidAlterOptions } from './utils';
const ColumnEditor = ({ const ColumnEditor = ({
@ -113,6 +99,7 @@ const ColumnEditor = ({
value={columnTypePG && alterOptionsValueMap[columnTypePG]} value={columnTypePG && alterOptionsValueMap[columnTypePG]}
bsClass={`col-type-${0} modify_select`} bsClass={`col-type-${0} modify_select`}
styleOverrides={customSelectBoxStyles} styleOverrides={customSelectBoxStyles}
filterOption={'prefix'}
/> />
</div> </div>
</div> </div>

View File

@ -34,10 +34,10 @@ const getValidAlterOptions = (alterTypeOptions, colName) => {
const fetchColumnCastsQuery = ` const fetchColumnCastsQuery = `
SELECT ts.typname AS "Source Type", SELECT ts.typname AS "Source Type",
pg_catalog.format_type(castsource, NULL) AS "Source Info", pg_catalog.format_type(castsource, NULL) AS "Source Info",
pg_catalog.obj_description(castsource, 'pg_type') as "Source Descriptions", coalesce(pg_catalog.obj_description(castsource, 'pg_type'), '') as "Source Descriptions",
string_agg(tt.typname, ',') AS "Target Type", string_agg(tt.typname, ',') AS "Target Type",
string_agg(pg_catalog.format_type(casttarget, NULL), ',') AS "Target Info", string_agg(pg_catalog.format_type(casttarget, NULL), ',') AS "Target Info",
string_agg(pg_catalog.obj_description(casttarget, 'pg_type'), ':') as "Target Descriptions", string_agg(coalesce(pg_catalog.obj_description(casttarget, 'pg_type'), ''), ':') as "Target Descriptions",
string_agg(CASE WHEN castfunc = 0 THEN '(binary coercible)' string_agg(CASE WHEN castfunc = 0 THEN '(binary coercible)'
ELSE p.proname ELSE p.proname
END, ',') as "Function" END, ',') as "Function"
@ -59,15 +59,26 @@ ORDER BY 1, 2;
`; `;
const getCreatePkSql = ({ schemaName, tableName, selectedPkColumns, constraintName }) => { const getCreatePkSql = ({
schemaName,
tableName,
selectedPkColumns,
constraintName,
}) => {
return `alter table "${schemaName}"."${tableName}" return `alter table "${schemaName}"."${tableName}"
add constraint "${constraintName}" primary key ( ${selectedPkColumns add constraint "${constraintName}" primary key ( ${selectedPkColumns
.map(pkc => `"${pkc}"`) .map(pkc => `"${pkc}"`)
.join(', ')} );`; .join(', ')} );`;
}; };
const getDropPkSql = ({ schemaName, tableName, constraintName }) => { const getDropPkSql = ({ schemaName, tableName, constraintName }) => {
return `alter table "${schemaName}"."${tableName}" drop constraint "${constraintName}";`; return `alter table "${schemaName}"."${tableName}" drop constraint "${constraintName}";`;
}; };
export { convertArrayToJson, getValidAlterOptions, fetchColumnCastsQuery, getCreatePkSql, getDropPkSql }; export {
convertArrayToJson,
getValidAlterOptions,
fetchColumnCastsQuery,
getCreatePkSql,
getDropPkSql,
};

View File

@ -569,11 +569,15 @@ export const commonDataTypes = [
}, },
]; ];
/*
* Fetch non-composite types, primitive types like text, varchar etc,
* Filter types whose typename is unknown and type category is not 'Pseudo' and it is valid and available to be used
* */
export const fetchColumnTypesQuery = ` export const fetchColumnTypesQuery = `
SELECT SELECT
string_agg(t.typname, ',') as "Type Name", string_agg(t.typname, ',') as "Type Name",
string_agg(pg_catalog.format_type(t.oid, NULL), ',') as "Display Name", string_agg(pg_catalog.format_type(t.oid, NULL), ',') as "Display Name",
string_agg(pg_catalog.obj_description(t.oid, 'pg_type'), ':') as "Descriptions", string_agg(coalesce(pg_catalog.obj_description(t.oid, 'pg_type'), ''), ':') as "Descriptions",
t.typcategory t.typcategory
FROM pg_catalog.pg_type t FROM pg_catalog.pg_type t
LEFT JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace LEFT JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace

View File

@ -225,7 +225,7 @@ const ViewRows = ({
}; };
const successIcon = ( const successIcon = (
<i className={styles.invocationSuccess + 'fa fa-check'} /> <i className={styles.invocationSuccess + ' fa fa-check'} />
); );
const failureIcon = ( const failureIcon = (
@ -437,26 +437,26 @@ const ViewRows = ({
> >
{finalResponse.status_code {finalResponse.status_code
? [ ? [
'Status Code: ', 'Status Code: ',
verifySuccessStatus( verifySuccessStatus(
finalResponse.status_code finalResponse.status_code
) )
? successIcon ? successIcon
: failureIcon, : failureIcon,
finalResponse.status_code, finalResponse.status_code,
' ', ' ',
<OverlayTrigger <OverlayTrigger
placement="top" placement="top"
overlay={ overlay={
tooltip.statusCodeDescription tooltip.statusCodeDescription
} }
> >
<i <i
className="fa fa-question-circle" className="fa fa-question-circle"
aria-hidden="true" aria-hidden="true"
/> />
</OverlayTrigger>, </OverlayTrigger>,
] ]
: null} : null}
</div> </div>
<AceEditor <AceEditor