This commit is contained in:
Jan Prochazka 2020-06-18 21:18:30 +02:00
parent ac9bd62ecf
commit cecb88f024
13 changed files with 90 additions and 234 deletions

View File

@ -9,6 +9,7 @@
"start:api:portal": "yarn workspace @dbgate/api start:portal", "start:api:portal": "yarn workspace @dbgate/api start:portal",
"start:web": "yarn workspace @dbgate/web start", "start:web": "yarn workspace @dbgate/web start",
"start:sqltree": "yarn workspace @dbgate/sqltree start", "start:sqltree": "yarn workspace @dbgate/sqltree start",
"start:tools": "yarn workspace @dbgate/tools start",
"start:datalib": "yarn workspace @dbgate/datalib start", "start:datalib": "yarn workspace @dbgate/datalib start",
"start:filterparser": "yarn workspace @dbgate/filterparser start", "start:filterparser": "yarn workspace @dbgate/filterparser start",
"build:sqltree": "yarn workspace @dbgate/sqltree build", "build:sqltree": "yarn workspace @dbgate/sqltree build",
@ -26,7 +27,7 @@
"prepare": "yarn build:lib", "prepare": "yarn build:lib",
"start": "concurrently --kill-others-on-fail \"yarn start:api\" \"yarn start:web\"", "start": "concurrently --kill-others-on-fail \"yarn start:api\" \"yarn start:web\"",
"lib": "concurrently --kill-others-on-fail \"yarn start:sqltree\" \"yarn start:filterparser\" \"yarn start:datalib\"", "lib": "concurrently --kill-others-on-fail \"yarn start:sqltree\" \"yarn start:filterparser\" \"yarn start:datalib\" \"yarn start:tools\"",
"ts:api": "yarn workspace @dbgate/api ts", "ts:api": "yarn workspace @dbgate/api ts",
"ts:web": "yarn workspace @dbgate/web ts", "ts:web": "yarn workspace @dbgate/web ts",
"ts": "yarn ts:api && yarn ts:web", "ts": "yarn ts:api && yarn ts:web",

View File

@ -1,6 +1,6 @@
import _ from 'lodash'; import _ from 'lodash';
import { GridConfig, GridCache, GridConfigColumns, createGridCache } from './GridConfig'; import { GridConfig, GridCache, GridConfigColumns, createGridCache } from './GridConfig';
import { ForeignKeyInfo, TableInfo, ColumnInfo, DbType, EngineDriver, NamedObjectInfo, DatabaseInfo } from '@dbgate/types'; import { ForeignKeyInfo, TableInfo, ColumnInfo, EngineDriver, NamedObjectInfo, DatabaseInfo } from '@dbgate/types';
import { parseFilter, getFilterType } from '@dbgate/filterparser'; import { parseFilter, getFilterType } from '@dbgate/filterparser';
import { filterName } from './filterName'; import { filterName } from './filterName';
import { ChangeSetFieldDefinition, ChangeSetRowDefinition } from './ChangeSet'; import { ChangeSetFieldDefinition, ChangeSetRowDefinition } from './ChangeSet';
@ -19,7 +19,7 @@ export interface DisplayColumn {
foreignKey?: ForeignKeyInfo; foreignKey?: ForeignKeyInfo;
isChecked?: boolean; isChecked?: boolean;
hintColumnName?: string; hintColumnName?: string;
commonType?: DbType; dataType?: string;
} }
export interface DisplayedColumnEx extends DisplayColumn { export interface DisplayedColumnEx extends DisplayColumn {
@ -143,7 +143,7 @@ export abstract class GridDisplay {
const column = displayedColumnInfo[uniqueName]; const column = displayedColumnInfo[uniqueName];
if (!column) continue; if (!column) continue;
try { try {
const condition = parseFilter(filter, getFilterType(column.commonType?.typeCode)); const condition = parseFilter(filter, getFilterType(column.dataType));
if (condition) { if (condition) {
conditions.push( conditions.push(
_.cloneDeepWith(condition, (expr: Expression) => { _.cloneDeepWith(condition, (expr: Expression) => {

View File

@ -24,136 +24,12 @@ function objectTypeToField(type) {
} }
} }
/** @returns {import('@dbgate/types').DbType} */ function getColumnInfo({ isNullable, isIdentity, columnName, dataType }) {
function detectType(col) {
switch (col.dataType) {
case 'binary':
return {
typeCode: 'string',
isBinary: true,
};
case 'image':
return {
typeCode: 'string',
isBinary: true,
isBlob: true,
};
case 'timestamp':
return {
typeCode: 'string',
};
case 'varbinary':
return {
typeCode: 'string',
length: col.maxLength,
isBinary: true,
isVarLength: true,
};
case 'bit':
return {
typeCode: 'logical',
};
case 'tinyint':
return {
typeCode: 'int',
bytes: 1,
};
case 'mediumint':
return {
typeCode: 'int',
bytes: 3,
};
case 'datetime':
return {
typeCode: 'datetime',
subType: 'datetime',
};
case 'time':
return {
typeCode: 'datetime',
subType: 'time',
};
case 'year':
return {
typeCode: 'datetime',
subType: 'year',
};
case 'date':
return {
typeCode: 'datetime',
subType: 'date',
};
case 'decimal':
case 'numeric':
return {
typeCode: 'numeric',
precision: col.precision,
scale: col.scale,
};
case 'float':
return { typeCode: 'float' };
case 'uniqueidentifier':
return { typeCode: 'string' };
case 'smallint':
return {
typeCode: 'int',
bytes: 2,
};
case 'int':
return {
typeCode: 'int',
bytes: 4,
};
case 'bigint':
return {
typeCode: 'int',
bytes: 8,
};
case 'real':
return { typeCode: 'float' };
case 'char':
return {
typeCode: 'string',
length: col.maxLength,
};
case 'nchar':
return { typeCode: 'string', length: col.maxLength, isUnicode: true };
case 'varchar':
return {
typeCode: 'string',
length: col.maxLength,
isVarLength: true,
};
case 'nvarchar':
return {
typeCode: 'string',
length: col.maxLength,
isVarLength: true,
isUnicode: true,
};
case 'text':
return {
typeCode: 'blob',
isText: true,
};
case 'ntext':
return {
typeCode: 'blob',
isText: true,
isUnicode: true,
};
case 'xml':
return {
typeCode: 'blob',
isXml: true,
};
}
return { return {
typeCode: 'generic', columnName,
sql: col.dataType, dataType,
notNull: !isNullable,
autoIncrement: !!isIdentity,
}; };
} }
@ -224,14 +100,7 @@ class MsSqlAnalyser extends DatabaseAnalyser {
const tables = tablesRows.rows.map((row) => ({ const tables = tablesRows.rows.map((row) => ({
...row, ...row,
columns: columnsRows.rows columns: columnsRows.rows.filter((col) => col.objectId == row.objectId).map(getColumnInfo),
.filter((col) => col.objectId == row.objectId)
.map(({ isNullable, isIdentity, ...col }) => ({
...col,
notNull: !isNullable,
autoIncrement: !!isIdentity,
commonType: detectType(col),
})),
primaryKey: DatabaseAnalyser.extractPrimaryKeys(row, pkColumnsRows.rows), primaryKey: DatabaseAnalyser.extractPrimaryKeys(row, pkColumnsRows.rows),
foreignKeys: DatabaseAnalyser.extractForeignKeys(row, fkColumnsRows.rows), foreignKeys: DatabaseAnalyser.extractForeignKeys(row, fkColumnsRows.rows),
})); }));
@ -239,14 +108,7 @@ class MsSqlAnalyser extends DatabaseAnalyser {
const views = viewsRows.rows.map((row) => ({ const views = viewsRows.rows.map((row) => ({
...row, ...row,
createSql: getCreateSql(row), createSql: getCreateSql(row),
columns: viewColumnRows.rows columns: viewColumnRows.rows.filter((col) => col.objectId == row.objectId).map(getColumnInfo),
.filter((col) => col.objectId == row.objectId)
.map(({ isNullable, isIdentity, ...col }) => ({
...col,
notNull: !isNullable,
autoIncrement: !!isIdentity,
commonType: detectType(col),
})),
})); }));
const procedures = programmableRows.rows const procedures = programmableRows.rows

View File

@ -22,6 +22,7 @@
}, },
"dependencies": { "dependencies": {
"@types/parsimmon": "^1.10.1", "@types/parsimmon": "^1.10.1",
"@dbgate/tools": "^0.1.0",
"lodash": "^4.17.15", "lodash": "^4.17.15",
"moment": "^2.24.0", "moment": "^2.24.0",
"parsimmon": "^1.13.0" "parsimmon": "^1.13.0"

View File

@ -1,19 +1,11 @@
import { DbTypeCode } from '@dbgate/types'; import { isTypeNumber, isTypeString, isTypeLogical, isTypeDateTime } from '@dbgate/tools';
import { FilterType } from './types'; import { FilterType } from './types';
export function getFilterType(typeCode?: DbTypeCode): FilterType { export function getFilterType(dataType: string): FilterType {
if (!typeCode) return 'string'; if (!dataType) return 'string';
switch (typeCode) { if (isTypeNumber(dataType)) return 'number';
case 'int': if (isTypeString(dataType)) return 'string';
case 'numeric': if (isTypeLogical(dataType)) return 'logical';
case 'float': if (isTypeDateTime(dataType)) return 'datetime';
return 'number';
case 'string':
return 'string';
case 'datetime':
return 'datetime';
case 'logical':
return 'logical';
}
return 'string'; return 'string';
} }

1
packages/tools/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
lib

View File

@ -0,0 +1,26 @@
{
"version": "0.1.0",
"name": "@dbgate/tools",
"main": "lib/index.js",
"typings": "lib/index.d.ts",
"scripts": {
"prepare": "yarn build",
"build": "tsc",
"start": "tsc --watch",
"test": "jest"
},
"files": [
"lib"
],
"devDependencies": {
"@dbgate/types": "^0.1.0",
"@types/node": "^13.7.0",
"jest": "^24.9.0",
"ts-jest": "^25.2.1",
"typescript": "^3.7.5"
},
"dependencies": {
"lodash": "^4.17.15",
"moment": "^2.24.0"
}
}

View File

@ -0,0 +1,27 @@
export function isTypeInteger(dataType) {
return dataType && /int/i.test(dataType);
}
export function isTypeNumeric(dataType) {
return dataType && /numeric|decimal/i.test(dataType);
}
export function isTypeFloat(dataType) {
return dataType && /float|single|double/i.test(dataType);
}
export function isTypeNumber(dataType) {
return isTypeInteger(dataType) || isTypeFloat(dataType) || isTypeNumeric(dataType);
}
export function isTypeString(dataType) {
return dataType && /char/i.test(dataType);
}
export function isTypeLogical(dataType) {
return dataType && /bit|boolean/i.test(dataType);
}
export function isTypeDateTime(dataType) {
return dataType && /date|time/i.test(dataType);
}

View File

@ -0,0 +1 @@
export * from './commonTypeParser';

View File

@ -0,0 +1,14 @@
{
"compilerOptions": {
"target": "ES2015",
"module": "commonjs",
"declaration": true,
"skipLibCheck": true,
"outDir": "lib",
"preserveWatchOutput": true,
"esModuleInterop": true
},
"include": [
"src/**/*"
]
}

View File

@ -1,5 +1,3 @@
import { DbType } from './dbtypes';
export interface NamedObjectInfo { export interface NamedObjectInfo {
pureName: string; pureName: string;
schemaName: string; schemaName: string;
@ -41,7 +39,6 @@ export interface ColumnInfo {
isSparse: boolean; isSparse: boolean;
defaultValue: string; defaultValue: string;
defaultConstraint: string; defaultConstraint: string;
commonType?: DbType;
} }
export interface DatabaseObjectInfo extends NamedObjectInfo { export interface DatabaseObjectInfo extends NamedObjectInfo {

View File

@ -1,66 +0,0 @@
export type DbSizeType = 'small' | 'medium' | 'tiny' | 'long';
export interface DbTypeDatetime {
typeCode: 'datetime';
subType?: 'date' | 'datetime' | 'time' | 'year' | 'interval';
extendedPrecision?: boolean;
hasTimeZone?: boolean;
}
export interface DbTypeBlob {
typeCode: 'blob';
size?: DbSizeType;
isText?: boolean;
isUnicode?: boolean;
isXml?: boolean;
}
export interface DbTypeFloat {
typeCode: 'float';
bytes?: number;
isMoney?: boolean;
}
export interface DbTypeGeneric {
typeCode: 'generic';
sql: string;
}
export interface DbTypeLogical {
typeCode: 'logical';
}
export interface DbTypeNumeric {
typeCode: 'numeric';
precision?: number;
scale?: number;
autoIncrement?: boolean;
}
export interface DbTypeString {
typeCode: 'string';
length?: number;
isUnicode?: boolean;
isBinary?: boolean;
isBit?: boolean;
isVarLength?: boolean;
isBlob?: boolean;
}
export interface DbTypeInt {
typeCode: 'int';
bytes?: number;
autoIncrement?: boolean;
}
export type DbType =
| DbTypeDatetime
| DbTypeBlob
| DbTypeFloat
| DbTypeGeneric
| DbTypeLogical
| DbTypeNumeric
| DbTypeString
| DbTypeInt;
export type DbTypeCode = DbType['typeCode'];

View File

@ -1180,7 +1180,7 @@ export default function DataGridCore(props) {
data-col={col.colIndex} data-col={col.colIndex}
> >
<DataFilterControl <DataFilterControl
filterType={getFilterType(col.commonType ? col.commonType.typeCode : null)} filterType={getFilterType(col.dataType)}
filter={display.getFilter(col.uniqueName)} filter={display.getFilter(col.uniqueName)}
setFilter={(value) => display.setFilter(col.uniqueName, value)} setFilter={(value) => display.setFilter(col.uniqueName, value)}
/> />