mirror of
https://github.com/dbgate/dbgate
synced 2024-11-22 16:27:18 +00:00
table grid display, SQL for browse table is generated on FE
This commit is contained in:
parent
bbc969fa71
commit
aad9512951
@ -66,4 +66,12 @@ module.exports = {
|
||||
tables: _.sortBy(tables, x => `${x.schemaName}.${x.pureName}`),
|
||||
}; // .map(fp.pick(['tableName', 'schemaName']));
|
||||
},
|
||||
|
||||
queryData_meta: 'post',
|
||||
async queryData({ conid, database, sql }) {
|
||||
console.log(`Processing query, conid=${conid}, database=${database}, sql=${sql}`);
|
||||
const opened = await this.ensureOpened(conid, database);
|
||||
const res = await this.sendRequest(opened, { msgtype: 'queryData', sql });
|
||||
return res;
|
||||
},
|
||||
};
|
||||
|
@ -2,12 +2,12 @@ const _ = require('lodash');
|
||||
const databaseConnections = require('./databaseConnections');
|
||||
|
||||
module.exports = {
|
||||
tableData_meta: 'get',
|
||||
async tableData({ conid, database, schemaName, pureName }) {
|
||||
const opened = await databaseConnections.ensureOpened(conid, database);
|
||||
const res = await databaseConnections.sendRequest(opened, { msgtype: 'tableData', schemaName, pureName });
|
||||
return res;
|
||||
},
|
||||
// tableData_meta: 'get',
|
||||
// async tableData({ conid, database, schemaName, pureName }) {
|
||||
// const opened = await databaseConnections.ensureOpened(conid, database);
|
||||
// const res = await databaseConnections.sendRequest(opened, { msgtype: 'tableData', schemaName, pureName });
|
||||
// return res;
|
||||
// },
|
||||
|
||||
tableInfo_meta: 'get',
|
||||
async tableInfo({ conid, database, schemaName, pureName }) {
|
||||
|
@ -32,24 +32,23 @@ function waitConnected() {
|
||||
});
|
||||
}
|
||||
|
||||
async function handleTableData({ msgid, schemaName, pureName }) {
|
||||
async function handleQueryData({ msgid, sql }) {
|
||||
// const select = new Select();
|
||||
// if (driver.dialect.limitSelect) select.topRecords = 100;
|
||||
// if (driver.dialect.rangeSelect) select.range = { offset: 0, limit: 100 };
|
||||
// select.from = { schemaName, pureName };
|
||||
// select.selectAll = true;
|
||||
// const sql = select.toSql(driver);
|
||||
|
||||
await waitConnected();
|
||||
const driver = engines(storedConnection);
|
||||
|
||||
const select = new Select();
|
||||
if (driver.dialect.limitSelect) select.topRecords = 100;
|
||||
if (driver.dialect.rangeSelect) select.range = { offset: 0, limit: 100 };
|
||||
select.from = { schemaName, pureName };
|
||||
select.selectAll = true;
|
||||
const sql = select.toSql(driver);
|
||||
const res = await driver.query(systemConnection, sql);
|
||||
|
||||
process.send({ msgtype: 'response', msgid, ...res });
|
||||
}
|
||||
|
||||
const messageHandlers = {
|
||||
connect: handleConnect,
|
||||
tableData: handleTableData,
|
||||
queryData: handleQueryData,
|
||||
};
|
||||
|
||||
async function handleMessage({ msgtype, ...other }) {
|
||||
|
1
packages/datalib/.gitignore
vendored
Normal file
1
packages/datalib/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
lib
|
22
packages/datalib/package.json
Normal file
22
packages/datalib/package.json
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
"version": "0.1.0",
|
||||
"name": "@dbgate/datalib",
|
||||
"main": "lib/index.js",
|
||||
"typings": "lib/index.d.ts",
|
||||
"scripts": {
|
||||
"prepare": "yarn build",
|
||||
"build": "tsc",
|
||||
"start": "tsc --watch"
|
||||
},
|
||||
"files": [
|
||||
"lib"
|
||||
],
|
||||
"dependencies": {
|
||||
"@dbgate/sqltree": "^0.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@dbgate/types": "^0.1.0",
|
||||
"@types/node": "^13.7.0",
|
||||
"typescript": "^3.7.5"
|
||||
}
|
||||
}
|
5
packages/datalib/src/GridDisplay.ts
Normal file
5
packages/datalib/src/GridDisplay.ts
Normal file
@ -0,0 +1,5 @@
|
||||
import {Select} from '@dbgate/sqltree'
|
||||
|
||||
export default abstract class GridDisplay {
|
||||
abstract getPageQuery(offse: number, count: number): string;
|
||||
}
|
20
packages/datalib/src/TableGridDisplay.ts
Normal file
20
packages/datalib/src/TableGridDisplay.ts
Normal file
@ -0,0 +1,20 @@
|
||||
import GridDisplay from "./GridDisplay";
|
||||
import { Select } from "@dbgate/sqltree";
|
||||
import { TableInfo, EngineDriver } from "@dbgate/types";
|
||||
|
||||
export default class TableGridDisplay extends GridDisplay {
|
||||
constructor(public table: TableInfo, public driver: EngineDriver) {
|
||||
super();
|
||||
}
|
||||
|
||||
getPageQuery(offset: number, count: number) {
|
||||
const select = new Select();
|
||||
if (this.driver.dialect.limitSelect) select.topRecords = count;
|
||||
if (this.driver.dialect.rangeSelect)
|
||||
select.range = { offset: offset, limit: count };
|
||||
select.from = this.table;
|
||||
select.selectAll = true;
|
||||
const sql = select.toSql(this.driver);
|
||||
return sql;
|
||||
}
|
||||
}
|
2
packages/datalib/src/index.ts
Normal file
2
packages/datalib/src/index.ts
Normal file
@ -0,0 +1,2 @@
|
||||
export { default as GridDisplay } from "./GridDisplay";
|
||||
export { default as TableGridDisplay } from "./TableGridDisplay";
|
12
packages/datalib/tsconfig.json
Normal file
12
packages/datalib/tsconfig.json
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2015",
|
||||
"module": "commonjs",
|
||||
"declaration": true,
|
||||
"skipLibCheck": true,
|
||||
"outDir": "lib"
|
||||
},
|
||||
"include": [
|
||||
"src/**/*"
|
||||
]
|
||||
}
|
@ -30,7 +30,9 @@ class SqlDumper {
|
||||
break;
|
||||
case "k":
|
||||
{
|
||||
this.putRaw(value.toUpperCase());
|
||||
if (value) {
|
||||
this.putRaw(value.toUpperCase());
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "f":
|
||||
@ -46,6 +48,7 @@ class SqlDumper {
|
||||
}
|
||||
}
|
||||
putFormattedList(c, collection) {
|
||||
if (!collection) return;
|
||||
this.putCollection(", ", collection, item =>
|
||||
this.putFormattedValue(c, item)
|
||||
);
|
||||
@ -130,7 +133,7 @@ class SqlDumper {
|
||||
if (column.isPersisted) this.put(" ^persisted");
|
||||
return;
|
||||
}
|
||||
if (column.dataType) this.put("%k", column.dataType);
|
||||
this.put("%k", column.dataType);
|
||||
if (column.autoIncrement) {
|
||||
this.autoIncrement();
|
||||
}
|
||||
|
@ -22,6 +22,8 @@
|
||||
"socket.io-client": "^2.3.0",
|
||||
"styled-components": "^4.4.1",
|
||||
"uuid": "^3.4.0",
|
||||
"@dbgate/sqltree": "^0.1.0",
|
||||
"@dbgate/datalib": "^0.1.0",
|
||||
"@dbgate/engines": "^0.1.0"
|
||||
},
|
||||
"scripts": {
|
||||
|
@ -63,10 +63,26 @@ const TableBodyCell = styled.td`
|
||||
overflow: hidden;
|
||||
`;
|
||||
|
||||
export default function DataGrid({ params }) {
|
||||
/**
|
||||
* @param {object} props
|
||||
* @param {number} props.conid
|
||||
* @param {string} props.database
|
||||
* @param {import('@dbgate/datalib').GridDisplay} props.display
|
||||
*/
|
||||
export default function DataGrid(props) {
|
||||
const { conid, database, display } = props;
|
||||
const sql = display.getPageQuery(0, 100);
|
||||
|
||||
console.log(`GRID, conid=${conid}, database=${database}, sql=${sql}`);
|
||||
|
||||
const data = useFetch({
|
||||
url: 'tables/table-data',
|
||||
params,
|
||||
url: 'database-connections/query-data',
|
||||
method: 'post',
|
||||
params: {
|
||||
conid,
|
||||
database,
|
||||
},
|
||||
data: { sql },
|
||||
});
|
||||
const { rows, columns } = data || {};
|
||||
const [firstVisibleRowScrollIndex, setFirstVisibleRowScrollIndex] = React.useState(0);
|
||||
@ -116,21 +132,21 @@ export default function DataGrid({ params }) {
|
||||
columnSizes.setExtraordinaryIndexes([], []);
|
||||
|
||||
for (let colIndex = 0; colIndex < columns.length; colIndex++) {
|
||||
//this.columnSizes.PutSizeOverride(col, this.columns[col].Name.length * 8);
|
||||
let column = columns[colIndex];
|
||||
//this.columnSizes.PutSizeOverride(col, this.columns[col].Name.length * 8);
|
||||
let column = columns[colIndex];
|
||||
|
||||
// if (column.columnClientObject != null && column.columnClientObject.notNull) context.font = "bold 14px Helvetica";
|
||||
// else context.font = "14px Helvetica";
|
||||
context.font = "bold 14px Helvetica";
|
||||
// if (column.columnClientObject != null && column.columnClientObject.notNull) context.font = "bold 14px Helvetica";
|
||||
// else context.font = "14px Helvetica";
|
||||
context.font = 'bold 14px Helvetica';
|
||||
|
||||
let text = column.name;
|
||||
let headerWidth = context.measureText(text).width + 32;
|
||||
let text = column.name;
|
||||
let headerWidth = context.measureText(text).width + 32;
|
||||
|
||||
// if (column.columnClientObject != null && column.columnClientObject.icon != null) headerWidth += 16;
|
||||
// if (this.getFilterOnColumn(column.uniquePath)) headerWidth += 16;
|
||||
// if (this.getSortOrder(column.uniquePath)) headerWidth += 16;
|
||||
// if (column.columnClientObject != null && column.columnClientObject.icon != null) headerWidth += 16;
|
||||
// if (this.getFilterOnColumn(column.uniquePath)) headerWidth += 16;
|
||||
// if (this.getSortOrder(column.uniquePath)) headerWidth += 16;
|
||||
|
||||
columnSizes.putSizeOverride(colIndex, headerWidth);
|
||||
columnSizes.putSizeOverride(colIndex, headerWidth);
|
||||
}
|
||||
|
||||
// let headerWidth = this.rowHeaderWidthDefault;
|
||||
|
@ -3,7 +3,22 @@ import useFetch from '../utility/useFetch';
|
||||
import styled from 'styled-components';
|
||||
import theme from '../theme';
|
||||
import DataGrid from '../datagrid/DataGrid';
|
||||
import { TableGridDisplay } from '@dbgate/datalib';
|
||||
import useTableInfo from '../utility/useTableInfo';
|
||||
import useConnectionInfo from '../utility/useConnectionInfo';
|
||||
import engines from '@dbgate/engines';
|
||||
|
||||
export default function TableDataTab({ conid, database, schemaName, pureName }) {
|
||||
return <DataGrid params={{ conid, database, schemaName, pureName }} />;
|
||||
const tableInfo = useTableInfo({ conid, database, schemaName, pureName });
|
||||
const connection = useConnectionInfo(conid);
|
||||
if (!tableInfo || !connection) return null;
|
||||
const display = new TableGridDisplay(tableInfo, engines(connection));
|
||||
return (
|
||||
<DataGrid
|
||||
// key={`${conid}, ${database}, ${schemaName}, ${pureName}`}
|
||||
conid={conid}
|
||||
database={database}
|
||||
display={display}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
@ -1,16 +1,18 @@
|
||||
import React from 'react';
|
||||
import _ from 'lodash';
|
||||
import axios from './axios';
|
||||
import useSocket from './SocketProvider';
|
||||
import stableStringify from 'json-stable-stringify';
|
||||
|
||||
export default function useFetch({
|
||||
url,
|
||||
data = undefined,
|
||||
params = undefined,
|
||||
defaultValue = undefined,
|
||||
reloadTrigger = undefined,
|
||||
...config
|
||||
}) {
|
||||
const [value, setValue] = React.useState(defaultValue);
|
||||
const [value, setValue] = React.useState([defaultValue, []]);
|
||||
const [loadCounter, setLoadCounter] = React.useState(0);
|
||||
const socket = useSocket();
|
||||
|
||||
@ -18,24 +20,30 @@ export default function useFetch({
|
||||
setLoadCounter(loadCounter + 1);
|
||||
};
|
||||
|
||||
async function loadValue() {
|
||||
const indicators = [url, stableStringify(data), stableStringify(params), loadCounter];
|
||||
|
||||
async function loadValue(loadedIndicators) {
|
||||
const resp = await axios.request({
|
||||
method: 'get',
|
||||
params,
|
||||
url,
|
||||
data,
|
||||
...config,
|
||||
});
|
||||
setValue(resp.data);
|
||||
setValue([resp.data, loadedIndicators]);
|
||||
}
|
||||
React.useEffect(() => {
|
||||
loadValue();
|
||||
loadValue(indicators);
|
||||
if (reloadTrigger && socket) {
|
||||
socket.on(reloadTrigger, handleReload);
|
||||
return () => {
|
||||
socket.off(reloadTrigger, handleReload);
|
||||
};
|
||||
}
|
||||
}, [url, stableStringify(params), socket, loadCounter]);
|
||||
}, [...indicators, socket]);
|
||||
|
||||
return value;
|
||||
const [returnValue, loadedIndicators] = value;
|
||||
if (_.isEqual(indicators, loadedIndicators)) return returnValue;
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user