set null, various fixes

This commit is contained in:
Jan Prochazka
2020-05-13 19:42:33 +02:00
parent c49119a4b8
commit d31b756b0e
6 changed files with 76 additions and 14 deletions

View File

@@ -33,9 +33,12 @@ class SqlDumper {
this.putRaw("'"); this.putRaw("'");
} }
putValue(value) { putValue(value) {
if (_.isString(value)) this.putStringValue(value); if (value === null) this.putRaw('NULL');
if (_.isNumber(value)) this.putRaw(value.toString()); if (value === true) this.putRaw('1');
if (_.isDate(value)) this.putStringValue(moment(value).toISOString()); if (value === false) this.putRaw('0');
else if (_.isString(value)) this.putStringValue(value);
else if (_.isNumber(value)) this.putRaw(value.toString());
else if (_.isDate(value)) this.putStringValue(moment(value).toISOString());
} }
putCmd(format, ...args) { putCmd(format, ...args) {
this.put(format, ...args); this.put(format, ...args);
@@ -77,7 +80,7 @@ class SqlDumper {
} }
putFormattedList(c, collection) { putFormattedList(c, collection) {
if (!collection) return; if (!collection) return;
this.putCollection(', ', collection, item => this.putFormattedValue(c, item)); this.putCollection(', ', collection, (item) => this.putFormattedValue(c, item));
} }
/** @param format {string} */ /** @param format {string} */
put(format, ...args) { put(format, ...args) {
@@ -198,7 +201,7 @@ class SqlDumper {
/** @param table {import('@dbgate/types').TableInfo} */ /** @param table {import('@dbgate/types').TableInfo} */
createTable(table) { createTable(table) {
this.put('^create ^table %f ( &>&n', table); this.put('^create ^table %f ( &>&n', table);
this.putCollection(',&n', table.columns, col => { this.putCollection(',&n', table.columns, (col) => {
this.put('%i ', col.columnName); this.put('%i ', col.columnName);
this.columnDefinition(col); this.columnDefinition(col);
}); });
@@ -209,11 +212,11 @@ class SqlDumper {
} }
this.put( this.put(
' ^primary ^key (%,i)', ' ^primary ^key (%,i)',
table.primaryKey.columns.map(x => x.columnName) table.primaryKey.columns.map((x) => x.columnName)
); );
} }
if (table.foreignKeys) { if (table.foreignKeys) {
table.foreignKeys.forEach(fk => { table.foreignKeys.forEach((fk) => {
this.put(',&n'); this.put(',&n');
this.createForeignKeyFore(fk); this.createForeignKeyFore(fk);
}); });
@@ -243,9 +246,9 @@ class SqlDumper {
if (fk.constraintName != null) this.put('^constraint %i ', fk.constraintName); if (fk.constraintName != null) this.put('^constraint %i ', fk.constraintName);
this.put( this.put(
'^foreign ^key (%,i) ^references %f (%,i)', '^foreign ^key (%,i) ^references %f (%,i)',
fk.columns.map(x => x.columnName), fk.columns.map((x) => x.columnName),
{ schemaName: fk.refSchemaName, pureName: fk.refTableName }, { schemaName: fk.refSchemaName, pureName: fk.refTableName },
fk.columns.map(x => x.refColumnName) fk.columns.map((x) => x.refColumnName)
); );
if (fk.deleteAction) this.put(' ^on ^delete %k', fk.deleteAction); if (fk.deleteAction) this.put(' ^on ^delete %k', fk.deleteAction);
if (fk.updateAction) this.put(' ^on ^update %k', fk.updateAction); if (fk.updateAction) this.put(' ^on ^update %k', fk.updateAction);

View File

@@ -1,7 +1,14 @@
import React from 'react'; import React from 'react';
import { DropDownMenuItem, DropDownMenuDivider } from '../modals/DropDownMenu'; import { DropDownMenuItem, DropDownMenuDivider } from '../modals/DropDownMenu';
export default function DataGridContextMenu({ copy, revertRowChanges, deleteSelectedRows, insertNewRow, reload }) { export default function DataGridContextMenu({
copy,
revertRowChanges,
deleteSelectedRows,
insertNewRow,
setNull,
reload,
}) {
return ( return (
<> <>
<DropDownMenuItem onClick={reload} keyText="F5"> <DropDownMenuItem onClick={reload} keyText="F5">
@@ -20,6 +27,10 @@ export default function DataGridContextMenu({ copy, revertRowChanges, deleteSele
<DropDownMenuItem onClick={insertNewRow} keyText="Insert"> <DropDownMenuItem onClick={insertNewRow} keyText="Insert">
Insert new row Insert new row
</DropDownMenuItem> </DropDownMenuItem>
<DropDownMenuDivider />
<DropDownMenuItem onClick={setNull} keyText="Ctrl+0">
Set NULL
</DropDownMenuItem>
</> </>
); );
} }

View File

@@ -530,6 +530,7 @@ export default function DataGridCore(props) {
deleteSelectedRows={deleteSelectedRows} deleteSelectedRows={deleteSelectedRows}
insertNewRow={insertNewRow} insertNewRow={insertNewRow}
reload={() => display.reload()} reload={() => display.reload()}
setNull={setNull}
/> />
); );
}; };
@@ -654,6 +655,22 @@ export default function DataGridCore(props) {
setChangeSet(chs); setChangeSet(chs);
} }
function setNull() {
let chs = changeSet;
selectedCells.filter(isRegularCell).forEach((cell) => {
chs = setChangeSetValue(
chs,
display.getChangeSetField(
loadedAndInsertedRows[cell[0]],
realColumnUniqueNames[cell[1]],
cell[0] >= loadedRows.length ? cell[0] - loadedRows.length : null
),
null
);
});
setChangeSet(chs);
}
function copyToClipboard() { function copyToClipboard() {
const rowIndexes = _.uniq(selectedCells.map((x) => x[0])).sort(); const rowIndexes = _.uniq(selectedCells.map((x) => x[0])).sort();
const lines = rowIndexes.map((rowIndex) => { const lines = rowIndexes.map((rowIndex) => {
@@ -844,6 +861,11 @@ export default function DataGridCore(props) {
// this.saveAndFocus(); // this.saveAndFocus();
} }
if (event.keyCode == keycodes.n0 && event.ctrlKey) {
event.preventDefault();
setNull();
}
if (event.keyCode == keycodes.r && event.ctrlKey) { if (event.keyCode == keycodes.r && event.ctrlKey) {
event.preventDefault(); event.preventDefault();
revertRowChanges(); revertRowChanges();

View File

@@ -68,8 +68,7 @@ const TableBodyCell = styled.td`
`} `}
${(props) => ${(props) =>
props.isFocusedColumn props.isFocusedColumn &&
&&
` `
background-color: lightgoldenrodyellow; background-color: lightgoldenrodyellow;
`} `}
@@ -123,11 +122,31 @@ const AutoFillPoint = styled.div`
cursor: crosshair; cursor: crosshair;
`; `;
function makeBulletString(value) {
return _.pad('', value.length, '•');
}
function highlightSpecialCharacters(value) {
value = value.replace(/\n/g, '↲');
value = value.replace(/\r/g, '');
value = value.replace(/^(\s+)/, makeBulletString);
value = value.replace(/(\s+)$/, makeBulletString);
value = value.replace(/(\s\s+)/g, makeBulletString);
return value;
}
const dateTimeRegex = /\d\d\d\d-\d\d-\d\dT\d\d:\d\d:\d\d(\.\d\d\d)?Z?/;
function CellFormattedValue({ value }) { function CellFormattedValue({ value }) {
if (value == null) return <NullSpan>(NULL)</NullSpan>; if (value == null) return <NullSpan>(NULL)</NullSpan>;
if (_.isDate(value)) return moment(value).format('YYYY-MM-DD HH:mm:ss'); if (_.isDate(value)) return moment(value).format('YYYY-MM-DD HH:mm:ss');
if (value === true) return '1'; if (value === true) return '1';
if (value === false) return '0'; if (value === false) return '0';
if (_.isNumber(value)) return value.toLocaleString();
if (_.isString(value)) {
if (dateTimeRegex.test(value)) return moment(value).format('YYYY-MM-DD HH:mm:ss');
return highlightSpecialCharacters(value);
}
return value; return value;
} }

View File

@@ -29,14 +29,18 @@ export const VerticalSplitHandle = styled.div`
background-color: #ccc; background-color: #ccc;
height: ${theme.splitter.thickness}px; height: ${theme.splitter.thickness}px;
cursor: row-resize; cursor: row-resize;
z-index: 1; &:hover {
background-color: #AAA;
}
`; `;
export const HorizontalSplitHandle = styled.div` export const HorizontalSplitHandle = styled.div`
background-color: #ccc; background-color: #ccc;
width: ${theme.splitter.thickness}px; width: ${theme.splitter.thickness}px;
cursor: col-resize; cursor: col-resize;
z-index: 1; &:hover {
background-color: #AAA;
}
`; `;
const ChildContainer1 = styled.div` const ChildContainer1 = styled.div`
@@ -45,6 +49,7 @@ const ChildContainer1 = styled.div`
// flex-grow: 1; // flex-grow: 1;
display: flex; display: flex;
position: relative; position: relative;
overflow: hidden;
`; `;
const ChildContainer2 = styled.div` const ChildContainer2 = styled.div`
@@ -54,6 +59,7 @@ const ChildContainer2 = styled.div`
// flex-grow: 1; // flex-grow: 1;
display: flex; display: flex;
position: relative; position: relative;
overflow: hidden;
`; `;
export function useSplitterDrag(axes, onResize) { export function useSplitterDrag(axes, onResize) {

View File

@@ -38,6 +38,7 @@ const StyledIconSpan = styled.span`
const ButtonDivInner = styled.div` const ButtonDivInner = styled.div`
position: relative; position: relative;
top: ${(props) => props.patchY}px; top: ${(props) => props.patchY}px;
white-space: nowrap;
`; `;
export default function ToolbarButton({ children, onClick, icon = undefined, disabled = undefined, patchY = 2 }) { export default function ToolbarButton({ children, onClick, icon = undefined, disabled = undefined, patchY = 2 }) {