Fixed following issues for query tool after react porting:

1) Add New Server Connection > Server options keep loading(For empty Server group).
 2) After clicking indent/Unindent(for all operations) for large query option left as it is till operation completes
 3) Check sign beside options in Execute Option/Copy Header is little bit big
 4) In explain > Analysis tab does not show ROWS column
 5) In explain > Explain > analysis previous explain output is NOT cleared. New rows are appended. Same applies to the statistics tab.
 6) Update new query tool connection tool tip. Fixes #7289
 7) Explain-Analyze > Loops column is empty.
 8) Explain-Analyze with Verbose & Costs > in ROW X columns upward arrows are missing.
 9) Explain-Analyze with all option checked > background colors are missing for timing.
 10) Explain-Analyze > Additional bullet is added before Hash Cond.
 11) Browser Tree > Filtered rows icon is not working.
 12) Create table with timestamp and default value as function now() > Add new row > Enter mandatory columns except column where default value is function(now()) > Click Save > New row added but column with default value has value [default]. not updated to actual value. / Default values are not considered for any column while adding a new entry.
 13) Disable execute options in View/Edit data.
 14) The Boolean column always shows null.
 15) In Query history Remove & Remove all buttons are stuck to each other.
 16) On Remove all, the right panel is empty.
 17) Create a column with boolean[]/ text[], Try to add a new entry from data grid, enter “” quotes > Click Ok > Now try edit cell > You can not change value.
 18) In query history - Select queries are suffixed by ’Save Data’ icon
 19) Edit any table with PK > Try to insert duplicate PK > Error thrown > Correct pK value > Still old error shown > Not able to add new entry (This works when focus is moved from edited cell)
 20) Clicking arrows after opening dropdown options, does not collapse dropdown.

refs #6131
This commit is contained in:
Aditya Toshniwal
2022-04-18 12:50:51 +05:30
committed by Akshay Joshi
parent 74e3f976c1
commit 9c30d983bd
22 changed files with 343 additions and 185 deletions
+27 -30
View File
@@ -24,16 +24,19 @@ const useStyles = makeStyles((theme)=>({
borderBottom: '2px dashed '+theme.palette.primary.main,
},
level2: {
backgroundColor: '#fff',
color: '#000',
backgroundColor: theme.otherVars.explain.sev2.bg,
color: theme.otherVars.explain.sev2.color,
},
level3: {
backgroundColor: '#fff',
color: '#000',
backgroundColor: theme.otherVars.explain.sev3.bg,
color: theme.otherVars.explain.sev3.color,
},
level4: {
backgroundColor: '#fff',
color: '#000',
backgroundColor: theme.otherVars.explain.sev4.bg,
color: theme.otherVars.explain.sev4.color,
},
textRight: {
textAlign: 'right',
},
}));
@@ -43,15 +46,6 @@ function getRowClassname(data, collapseParent) {
if(data['Plans']?.length > 0) {
className.push(classes.collapsible);
}
if(!_.isEmpty(data['exclusive_flag'])) {
className.push(classes['level'+data['exclusive_flag']]);
}
if(!_.isEmpty(data['inclusive_flag'])) {
className.push(classes['level'+data['inclusive_flag']]);
}
if(!_.isEmpty(data['rowsx_flag'])) {
className.push(classes['level'+data['rowsx_flag']]);
}
if(collapseParent) {
className.push(classes.collapseParent);
}
@@ -61,10 +55,10 @@ function getRowClassname(data, collapseParent) {
function NodeText({displayText, extraInfo}) {
return (
<>
<ArrowRightAltIcon fontSize="small" /> {displayText}
{extraInfo?.length > 0 && <ul>
<ArrowRightAltIcon fontSize="small" style={{marginLeft: '-24px'}} /> {displayText}
{extraInfo?.length > 0 && <ul style={{fontSize: '13px'}}>
{extraInfo.map((item, i)=>{
return <li key={i}>{HTMLReactParse(item)}</li>;
return <li key={i} style={{opacity: '0.8'}}>{HTMLReactParse(item)}</li>;
})}
</ul>}
</>);
@@ -76,6 +70,7 @@ NodeText.propTypes = {
function ExplainRow({row, show, activeExId, setActiveExId, collapsedExId, toggleCollapseExId}) {
let data = row['data'];
const classes = useStyles();
const exId = `pga_ex_${data['level'].join('_')}`;
const parentExId = `pga_ex_${data['parent_node']}`;
const collapsed = collapsedExId.findIndex((v)=>parentExId.startsWith(v)) > -1;
@@ -94,29 +89,28 @@ function ExplainRow({row, show, activeExId, setActiveExId, collapsedExId, toggle
<td>
<FiberManualRecordIcon fontSize="small" style={{visibility: activeExId==parentExId ? 'visible' : 'hidden'}} />
</td>
<td>{data['_serial']}.</td>
<td className={classes.textRight}>{data['_serial']}.</td>
<td style={{paddingLeft: data['level'].length*30+'px'}} title={row['tooltip_text']}>
<NodeText displayText={row['display_text']} extraInfo={row['node_extra_info']} />
</td>
<td style={show.show_timings ? {} : {display: 'none'}}>
<td className={clsx(classes.textRight, classes['level'+data['exclusive_flag']])} style={show.show_timings ? {} : {display: 'none'}}>
{data['exclusive'] && (data['exclusive']+' ms')}
</td>
<td style={show.show_timings ? {} : {display: 'none'}}>
<td className={clsx(classes.textRight, classes['level'+data['inclusive_flag']])} style={show.show_timings ? {} : {display: 'none'}}>
{data['inclusive'] && (data['inclusive']+' ms')}
</td>
<td style={{display: 'none'}}>{!_.isUndefined(data['rowsx_flag'])
&& (data['rowsx_direction'] == 'positive' ? '&uarr;' : '&darr;')
}</td>
<td style={show.show_rowsx ? {} : {display: 'none'}}>
{data['rowsx']}
<td className={clsx(classes.textRight, classes['level'+data['rowsx_flag']])} style={show.show_rowsx ? {} : {display: 'none'}}>
{!_.isUndefined(data['rowsx_flag'])
&& (data['rowsx_direction'] == 'positive' ? <>&uarr;</> : <>&darr;</>)
}&nbsp;{data['rowsx']}
</td>
<td style={(show.show_rowsx || show.show_rows) ? {} : {display: 'none'}}>
<td className={classes.textRight} style={(show.show_rowsx || show.show_rows) ? {} : {display: 'none'}}>
{data['Actual Rows']}
</td>
<td style={(show.show_rowsx || show.show_plan_rows) ? {} : {display: 'none'}}>
<td className={classes.textRight} style={(show.show_rowsx || show.show_plan_rows) ? {} : {display: 'none'}}>
{data['Plan Rows']}
</td>
<td style={(show.show_rowsx || show.show_rows) ? {} : {display: 'none'}}>
<td className={classes.textRight} style={(show.show_rowsx || show.show_rows) ? {} : {display: 'none'}}>
{data['Actual Loops']}
</td>
</tr>
@@ -130,7 +124,9 @@ ExplainRow.propTypes = {
_serial: PropTypes.number,
parent_node: PropTypes.number,
exclusive: PropTypes.number,
exclusive_flag: PropTypes.string,
inclusive: PropTypes.number,
inclusive_flag: PropTypes.string,
rowsx_direction: PropTypes.string,
rowsx: PropTypes.number,
rowsx_flag: PropTypes.number,
@@ -178,7 +174,8 @@ export default function Analysis({explainTable}) {
<th colSpan="2" style={explainTable.show_timings ? {} : {display: 'none'}}>
<button disabled="">Timings</button>
</th>
<th style={(explainTable.show_rowsx || explainTable.show_rows) ? {} : {display: 'none'}} colSpan="3">
<th style={(explainTable.show_rowsx || explainTable.show_rows) ? {} : {display: 'none'}}
colSpan={(explainTable.show_rowsx) ? '3' : '1'}>
<button disabled="">Rows</button>
</th>
<th style={(explainTable.show_rowsx || explainTable.show_rows) ? {} : {display: 'none'}} rowSpan="2">
@@ -250,6 +250,7 @@ function PlanContent({plan, pXpos, pYpos, ...props}) {
strokeWidth={1.2}
fill="gray"
fillOpacity={0.2}
pointerEvents="none"
/>
<tspan x={currentXpos + pWIDTH - (plan.width / 2) - xMargin}
y={currentYpos + pHEIGHT - (plan.height / 2) - yMargin}
+63 -27
View File
@@ -23,7 +23,7 @@ const useStyles = makeStyles((theme)=>({
tabPanel: {
padding: 0,
backgroundColor: theme.palette.background.default,
}
},
}));
// Some predefined constants used to calculate image location and its border
@@ -261,7 +261,11 @@ function parsePlan(data, ctx) {
totalCost = data['Total Cost'];
if (startCost != undefined && totalCost != undefined) {
arrowSize = Math.round(Math.log((startCost + totalCost) / 2 + startCost));
arrowSize = arrowSize < 1 ? 1 : arrowSize > 10 ? 10 : arrowSize;
if (arrowSize < 1) {
arrowSize = 1;
} else if (arrowSize > 10) {
arrowSize = 10;
}
}
data['arr_id'] = _.uniqueId('arr');
ctx.arrows[data['arr_id']] = arrowSize;
@@ -292,15 +296,21 @@ function parsePlan(data, ctx) {
if ('Actual Total Time' in data && 'Actual Loops' in data) {
data['inclusive'] = Math.ceil10(
data['Actual Total Time'] * data['Actual Loops'], -3
data['Actual Total Time'], -3
);
data['exclusive'] = data['inclusive'];
data['inclusive_factor'] = data['inclusive'] / (
data['total_time'] || data['Actual Total Time']
);
data['inclusive_flag'] = data['inclusive_factor'] <= 0.1 ? '1' :
data['inclusive_factor'] < 0.5 ? '2' :
data['inclusive_factor'] <= 0.9 ? '3' : '4';
if (data['inclusive_factor'] <= 0.1) {
data['inclusive_flag'] = '1';
} else if (data['inclusive_factor'] < 0.5) {
data['inclusive_flag'] = '2';
} else if (data['inclusive_factor'] <= 0.9) {
data['inclusive_flag'] = '3';
} else {
data['inclusive_flag'] = '4';
}
}
if ('Actual Rows' in data && 'Plan Rows' in data) {
@@ -316,10 +326,20 @@ function parsePlan(data, ctx) {
);
data['rowsx_direction'] = 'positive';
}
data['rowsx_flag'] = data['rowsx'] <= 10 ? '1' : (
data['rowsx'] <= 100 ? '2' : (data['rowsx'] <= 1000 ? '3' : '4')
);
data['rowsx'] = Math.ceil10(data['rowsx'], -2);
if (data['rowsx'] <= 10) {
data['rowsx_flag'] = '1';
} else if (data['rowsx'] <= 100 ) {
data['rowsx_flag'] = '2';
} else if (data['rowsx'] <= 1000 ) {
data['rowsx_flag'] = '3';
} else {
data['rowsx_flag'] = '4';
}
if('loops' in data) {
data['rowsx'] = Math.ceil10(data['rowsx'] / data['loops'] || 1, -2);
} else {
data['rowsx'] = Math.ceil10(data['rowsx'], -2);
}
}
// Start calculating xpos, ypos, width and height for child plans if any
@@ -337,6 +357,7 @@ function parsePlan(data, ctx) {
ypos: ypos,
total_time: data['total_time'] || data['Actual Total Time'],
parent_node: lvl.join('_'),
loops: data['Actual Loops']
}, ctx);
if (maxChildWidth < plan.width) {
@@ -344,7 +365,7 @@ function parsePlan(data, ctx) {
}
if ('exclusive' in data) {
if (plan.inclusive) {
if (plan.inclusive < data['exclusive']) {
data['exclusive'] -= plan.inclusive;
}
}
@@ -361,6 +382,11 @@ function parsePlan(data, ctx) {
plans.push(plan);
idx++;
});
} else{
if('loops' in data && 'exclusive' in data) {
data['inclusive'] = Math.ceil10(data['Actual Total Time'] / data['loops'] || 1, -3);
data['exclusive'] = data['inclusive'];
}
}
if ('exclusive' in data) {
@@ -368,9 +394,15 @@ function parsePlan(data, ctx) {
data['exclusive_factor'] = (
data['exclusive'] / (data['total_time'] || data['Actual Total Time'])
);
data['exclusive_flag'] = data['exclusive_factor'] <= 0.1 ? '1' :
data['exclusive_factor'] < 0.5 ? '2' :
data['exclusive_factor'] <= 0.9 ? '3' : '4';
if (data['exclusive_factor'] <= 0.1) {
data['exclusive_flag'] = '1';
} else if (data['exclusive_factor'] < 0.5) {
data['exclusive_flag'] = '2';
} else if (data['exclusive_factor'] <= 0.9) {
data['exclusive_flag'] = '3';
} else {
data['exclusive_flag'] = '4';
}
}
// Final Width and Height of current node
@@ -389,6 +421,7 @@ function parsePlanData(data, ctx) {
...data['Plan'],
xpos: 0,
ypos: 0,
loops: 1,
}, ctx);
retPlan['Plan'] = plan;
retPlan['xpos'] = 0;
@@ -431,20 +464,23 @@ export default function Explain({plans=[]}) {
const classes = useStyles();
const [tabValue, setTabValue] = React.useState(0);
let ctx = React.useRef({
totalNodes: 0,
totalDownloadedNodes: 0,
isDownloaded: 0,
explainTable: {
rows: [],
statistics: {
tables: {},
nodes: {},
let ctx = React.useRef({});
let planData = React.useMemo(()=>{
ctx.current = {
totalNodes: 0,
totalDownloadedNodes: 0,
isDownloaded: 0,
explainTable: {
rows: [],
statistics: {
tables: {},
nodes: {},
},
},
},
arrows: {},
});
let planData = React.useMemo(()=>(plans && parsePlanData(plans[0], ctx.current)), [plans]);
arrows: {},
};
return plans && parsePlanData(plans[0], ctx.current);
}, [plans]);
if(_.isEmpty(plans)) {
return <Box height="100%" display="flex" flexDirection="column">